File purpose: operational rules for automated or assisted code changes. Human-facing conceptual docs belong in README.md or the docs site.
Stream Video SDKs for:
- React
- React Native
- Plain JavaScript (core client)
Goals: API stability, backward compatibility, predictable releases, strong test coverage, accessibility, and performance discipline.
Please find the instructions in @packages/client/CLAUDE.md.
Please find the instructions in @packages/react-sdk/CLAUDE.md.
Please find the instructions in @packages/react-native-sdk/CLAUDE.md.
For research about native WebRTC behavior, iOS/Android audio session or ADM internals, or react-native-webrtc native module wrapper behavior, delegate to the webrtc-reference subagent (.claude/agents/webrtc-reference.md). It holds the reference codebase map and prefers the locally-installed @stream-io/react-native-webrtc fork over upstream.
- Languages: TypeScript, React (web + native)
- Runtime: Node (use
nvm usewith.nvmrc) - Package manager: Yarn (workspaces)
- Testing: Vitest (unit/integration), Playwright (E2E)
- Lint/Format: ESLint + Prettier
- Build: Package-local build scripts (composed via root)
- Release: Conventional Commits -> automated versioning/publishing
- Platforms:
- React: Web
- React Native: iOS and Android
nvm useyarn install- (Optional) Verify:
node -vmatches.nvmrc - For package-scoped work, run only affected package commands first (example:
yarn build:client && yarn test:ci:client) - Before finalizing cross-package changes, run CI-parity checks:
yarn lint:ci:all && yarn test:ci:all && NODE_ENV=production yarn build:all
packages/react-sdk/react-native-sdk/client/(core, no UI)
sample-apps/react/react-native/client/
- Config roots: linting, tsconfig, playwright, babel
- Do not edit generated output (
dist/, build artifacts)
- Start from the most specific package instructions first (
packages/*/CLAUDE.md), then apply this root guide. - Prefer workspace-scoped commands while iterating; run full-monorepo commands only for final verification.
- Match CI commands and Node version before considering work complete.
| Action | Command |
|---|---|
| Install deps | yarn install (CI uses yarn install --immutable) |
| Full build (all workspaces) | yarn build:all |
| Build core client only | yarn build:client |
| Watch core client | yarn start:client |
| Lint (local autofix) | yarn lint:all |
| Lint (CI strict) | yarn lint:ci:all |
| Tests (all workspaces, CI profile) | yarn test:ci:all |
| Tests (core client only, CI profile) | yarn test:ci:client |
| Tests (React Native SDK) | yarn test:react-native:sdk |
| E2E | package-specific (for example yarn workspace @stream-io/egress-composite run test:e2e) |
| Clean | yarn clean:all |
- Semantic versioning
- Use
@deprecatedJSDoc with replacement guidance - Provide migration docs for breaking changes
- Avoid breaking changes; prefer additive evolution
- Public surfaces: explicit TypeScript types/interfaces
- Consistent naming:
camelCasefor functions/properties,PascalCasefor components/types
-
All class methods must be arrow-function class fields, not method syntax — including
private/protectedmethods. This is the convention acrosspackages/client/src/(e.g.,Call.leave = async (...) => {},BasePeerConnection.isHealthy = () => {}). Method syntax breaks it.// good class Foo { doThing = (x: number) => x + 1; private helper = () => { /* ... */ }; } // bad class Foo { doThing(x: number) { return x + 1; } private helper() { /* ... */ } }
-
Declare state as explicit class fields at the class body level, not as TypeScript parameter-property shorthand (
constructor(private foo: Foo)). Assign them from the constructor body. Use field initializers for constants.// good class Foo { private a: number; private b: number; private cache: Map<string, number> = new Map(); constructor(a: number, b: number) { this.a = a; this.b = b; } } // bad class Foo { constructor( private a: number, private b: number, ) {} }
- Mark with
@deprecated+ rationale + alternative. - Maintain for at least one minor release unless security-critical.
- Add to migration documentation.
- Remove only in next major.
- Minimize re-renders (memoization, stable refs)
- Use
React.memo/useCallback/useMemowhen profiling justifies - Clean up side effects (
AbortControllerfor network calls) - Monitor bundle size; justify increases > 2% per package
- Prefer lazy loading for optional heavy modules
- Avoid unnecessary large dependency additions
- All interactive elements keyboard accessible
- Provide ARIA roles/labels where semantic tags insufficient
- Maintain color contrast (WCAG AA)
- Do not convey state by color alone
- Announce dynamic content changes (ARIA live regions if needed)
- Public API: throw descriptive errors or return typed error results (consistent with existing patterns)
- No console noise in production builds
- Internal debug logging gated behind env flag (if present)
- Never leak credentials/user data in errors
- Cancel stale async operations (media, network) when components unmount
- Use
AbortControllerfor fetch-like APIs - Avoid race conditions: check instance IDs / timestamps before state updates
- Unit: pure functions, small components
- Integration: component-tree interactions, state flows
- React Native: target minimal smoke + platform logic (avoid flakiness)
- E2E: critical user journeys (Playwright)
- Mocks/fakes: prefer shared test helpers
- Coverage target: maintain or improve existing percentage (fail PR if global coverage drops)
- File naming:
*.test.ts/*.spec.ts(x) - Add tests for: new public API, bug fixes (regression test), performance-sensitive utilities
- Mandatory in primary workflow (
.github/workflows/test.yml):yarn lint:ci:all,yarn test:ci:all,NODE_ENV=production yarn build:all, andyarn test:react-native:sdk - Node version:
24.xin CI (align with.nvmrc/v24) - Failing or flaky tests: fix or quarantine with justification PR comment (temporary)
- Zero new warnings
- Conventional Commit messages on PR merge
- Release automation aggregates commits
- Version bump + changelog + tag
- Publish to registry
- Deprecations noted in CHANGELOG
- Ensure docs updated prior to publishing breaking changes
- Avoid adding large deps without justification (size, maintenance)
- Prefer existing utility packages
- Run
yarn audit(or equivalent) if adding security-impacting deps - Keep upgrades separate from feature changes when possible
- New public feature: update at least one sample app
- Breaking changes: provide migration snippet
- Keep code snippets compilable
- Use placeholder keys (
YOUR_STREAM_KEY)
- Clear Metro cache if module resolution issues (dogfood app):
cd sample-apps/react-native/dogfood && yarn start --reset-cache - Test on iOS + Android for native module or platform-specific UI changes
- Avoid unguarded web-only APIs in shared code
- Run
yarn lint:allbefore commit - Narrowly scope
eslint-disablewith inline comments and rationale - No broad rule disabling
- Small, focused PRs, follow the @.github/pull_request_template.md template
- Never commit directly to the
mainbranch, always create a feature branch - Never commit or push unless instructed to do so
- Use conventional commits (fix, feat, chore)
- Include tests for changes
- Label breaking changes clearly in the description
- Document public API changes
- No credentials or real user data
- Use placeholders in examples
- Scripts must error on missing critical env vars
- Avoid introducing unmaintained dependencies
- Do not edit build artifacts (
dist/, generated types) - Do not bypass lint/type errors with force merges
- Build succeeds
- Lint clean
- Type check clean when the touched package has a
typecheckscript - Tests (unit/integration) green
- Coverage not reduced
- Public API docs updated if changed
- Samples updated if feature surfaced
- No new warnings
- No generated files modified
Refine this file iteratively for agent clarity; keep human-facing explanations in docs site / README.md.