facebook/react
Treat `/compiler/` and everything else as two separate projects with separate package managers, lockfiles, CI workflows and conventions — the root `CLAUDE.md` says so explicitly, and `compiler/CLAUDE.md` even documents Sapling (`sl`) rather than git for that subtree. Never run `jest` or `rollup` directly; use `yarn test` / `yarn flow` / `yarn linc` / `yarn prettier`, and let CI do builds. The single most important structural fact to internalise before editing is the fork/shim system: `ReactFiberConfig`, `ReactFeatureFlags` and the flight/fizz configs resolve differently under Rollup, Jest and Flow, so 'it works in one channel' is not a signal. Read the work loop, the root scheduler and the feature-flag file before touching reconciler behaviour, and read the relevant `docs/passes/` doc before touching a compiler pass.
- The repo is explicitly split: root `CLAUDE.md` scopes itself to 'All files outside `/compiler/`' and defers the compiler to its own instructions; `compiler/` has its own `package.json`, `yarn.lock`, `Cargo.toml` and CI workflows.
- Read first, in order: `CLAUDE.md`, `packages/react-dom/src/client/ReactDOMRoot.js` (entry), `packages/react-reconciler/src/ReactFiberWorkLoop.js` (the engine), `packages/react-reconciler/src/ReactFiberRootScheduler.js` (when work runs), `packages/shared/ReactFeatureFlags.js` (what's on), and `scripts/rollup/forks.js` + `scripts/shared/inlinedHostConfigs.js` (how modules actually resolve).
- The prescribed pre-commit gate is `/verify`: `yarn prettier` → `yarn linc` (stop on failure), then `/flow`, `/test` and `/test www` in parallel — mirroring the CI jobs, so passing it locally is a strong predictor of green CI.
- Yarn 1 is mandatory (`packageManager: yarn@1.22.22`) and Node is pinned by `.nvmrc`, which every CI job consumes via `node-version-file: '.nvmrc'`.
- Do not invoke Jest directly — the root `jest.testRegex` deliberately points at `scripts/jest/dont-run-jest-directly.js`; run `yarn test -r <channel> --env <env>` instead, and `yarn test-www` / `yarn test-stable` for the common channels.
- Do not build locally unless told to: root `CLAUDE.md` states 'Builds are handled by CI', and `yarn build` runs a multi-channel Rollup + Closure pipeline that also shells out to git and rewrites versions.
- Adding a feature flag is a multi-file edit: the base `packages/shared/ReactFeatureFlags.js` plus each of the 13 forks under `packages/shared/forks/`, verified by `yarn flags` and the CI `flags` job.
- Adding a user-visible `throw` requires running `yarn extract-errors` and committing the new entry in `scripts/error-codes/codes.json`; the script greps the `build` directory, so it only works after a build exists.
- Tests that depend on a flag or channel must carry a `// @gate <expr>` pragma (supports `&&`, `!`, multiple gates); `FIXME`/`TODO` are reserved gate names that disable a test wholesale.
- Compiler work has its own loop: `yarn snap` to run fixtures, `yarn snap -p <pattern> -d` to dump per-pass HIR, `yarn snap -u` to update `.expect.md`, `yarn snap compile <path>` for arbitrary files, `yarn snap minimize <path>` to shrink a repro.
- Before implementing from a Rust-port plan doc, `compiler/CLAUDE.md` requires checking `git log --oneline --grep="<plan-name>"` and the plan's Remaining Work section; afterwards update the plan status, run `/compiler-verify`, and ensure `compiler/scripts/test-babel-ast.sh` passes.
- Trap: `packages/react-reconciler/src/ReactFiberConfig.js` throws on import by design. If a new test or script resolves it, the fix is registering the renderer in `scripts/jest/setupHostConfigs.js` / `inlinedHostConfigs.js`, not editing the shim.
- Trap: `packages/react/src/` contains parallel client and server builds of the same package (`ReactClient.js`, `ReactServer.js`, `ReactServer.experimental.js`, `ReactServer.fb.js`, `ReactSharedInternalsClient.js` vs `…Server.js`) — an export added to one is not automatically present in the other.
- Safe-to-edit boundaries: `fixtures/` are manual-test apps (only `fixtures/flight` has automated e2e), `scripts/` is developer tooling, and `packages/*/src/__tests__/` are tests. High-caution zones are `ReactFiberWorkLoop.js`, `ReactFiberCommitWork.js`, `ReactFiberHooks.js`, `ReactFizzServer.js`, `ReactFlightServer.js` and anything under `scripts/rollup/` or `scripts/release/`. (inferred)
- Flow is the type system for runtime code (`flow-bin@^0.317.0`, `postinstall` runs `scripts/flow/createFlowConfigs.js` to generate per-renderer configs) while the compiler and ESLint plugin are TypeScript — so `@flow` pragmas and `$FlowFixMe` suppressions are normal in `packages/` and out of place in `compiler/`.