One change
Set up Claude Code in a monorepo or large codebase
large-codebases
Nearest release: v2.1.239, published under an hour before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
large-codebases Changed · +16 / -25 lines
from line 71
A common split is two levels: -* **Root `CLAUDE.md`**: instructions that apply everywhere, such as coding standards, commit conventions, and repository layout +* **Root `CLAUDE.md`**: instructions that apply everywhere, such as coding standards and commit conventions * **Per-subdirectory `CLAUDE.md`**: conventions specific to that area's stack. In a monorepo that's one per package. In a large single tree it's one per subsystem such as `src/db/` or `src/api/` Commit these files to the repository so teammates inherit them. Each directory's owner typically maintains its file. -The root `CLAUDE.md` orients Claude to the repository structure: +To trim a file that is already checked in, run the [`/doctor` checkup](/docs/en/memory#my-claude-md-is-too-large). The root `CLAUDE.md` holds the rules that apply in every package: ```markdown CLAUDE.md theme={null} -This is a monorepo with three packages under packages/: - -- packages/api: Node.js REST API with Express, TypeScript, and PostgreSQL -- packages/web: React frontend with Vite, TypeScript, and TailwindCSS -- packages/shared: shared TypeScript utilities used by both api and web - -Run commands from the package directory, not the monorepo root. -Each package has its own tsconfig.json, package.json, and test suite. +Run package scripts from the package directory, not the monorepo root. +Prefix commit subjects with the package name, for example `api: add rate limiting`. +Never edit files under packages/*/generated/. Run `npm run codegen` in the package instead. ``` -Each subdirectory's `CLAUDE.md`, here `packages/api/CLAUDE.md`, adds context specific to that area's stack: +Each subdirectory's `CLAUDE.md`, here `packages/api/CLAUDE.md`, adds the conventions specific to that area: ```markdown packages/api/CLAUDE.md theme={null} -This package is the REST API server. - -- Run tests: `npm test` (uses Vitest) -- Run dev server: `npm run dev` (port 3001) -- Database migrations: `npm run migrate` -- Environment variables: copy `.env.example` to `.env` - -API routes are in src/routes/. Each route file exports an Express router. -Database queries use Knex in src/db/. Never write raw SQL strings in route handlers. +Copy `.env.example` to `.env` before running anything. Tests and the dev server fail without it. +Write database queries with the Knex query builder. Never put raw SQL strings in route handlers. +Never edit a migration after it has merged. Add a new migration instead. ``` When you start Claude from `packages/api/`, it loads both `packages/api/CLAUDE.md` and the root `CLAUDE.md`. Claude sees the local instructions alongside the repository-wide rules, with no instructions from `packages/web/` in context. The same holds for any subdirectory in a non-monorepo tree. To confirm which files loaded, run `/context` and check the list under **Memory files**.
from line 149
Claude's content searches respect `.gitignore` by default, so paths already listed there, such as `node_modules/`, `dist/`, and `build/`, stay out of search results without additional configuration. -For paths that are checked in, such as a vendored SDK or committed generated code, add `Read` deny rules in `permissions.deny` to block Claude from opening those files even when a search lists them. +For paths that are checked in, such as a vendored SDK or committed generated code, add `Read` deny rules in `permissions.deny` to block Claude from opening those files. The deny rules can cover everyone working in the repository, only you, or every session on the machine, depending on which settings file you put them in:
from line 172
} ``` -Deny rules cover Claude's built-in file tools and recognized Bash file commands, including `cat`, `head`, `grep`, and `find`, when a denied path is passed as an argument. They do not filter denied paths out of a recursive search's output, and they do not cover arbitrary subprocesses that open files themselves. For the full pattern syntax, see [Read and Edit permission rules](/docs/en/permissions#read-and-edit). +Deny rules cover Claude's built-in file tools and recognized Bash file commands, including `cat`, `head`, `grep`, and `find`, when a denied path is passed as an argument. Claude Code also makes a best-effort attempt to leave denied paths out of the results of the built-in Grep and Glob tools. Claude still sees denied paths in the output of a Bash search such as `grep -r` or `find`. +Deny rules don't cover subprocesses that open files themselves. For the full pattern syntax, see [Read and Edit permission rules](/docs/en/permissions#read-and-edit). + ### Reduce file reads with code intelligence In a large codebase, finding where a symbol is defined or used can cost many file reads and grep calls. [Code intelligence plugins](/docs/en/discover-plugins#code-intelligence) connect Claude to a language server so it can jump to definitions, find references, and surface type errors directly instead of scanning the tree.
from line 461
Two techniques help keep a cross-package change consistent: * **Give Claude the whole change in one session**: handing over the shared edit and its call sites together keeps the decisions behind each edit consistent, rather than re-deriving them per package -* **Save the plan to a file before editing**: [plan first](/docs/en/best-practices#explore-first-then-plan-then-code) and ask Claude to write the plan to a markdown file in the repository. A long cross-package session [compacts its context](/docs/en/context-window#what-survives-compaction) along the way, and the saved plan survives where conversation history may not +* **Plan before editing**: [plan first](/docs/en/best-practices#explore-first-then-plan-then-code) in [plan mode](/docs/en/permission-modes#analyze-before-you-edit-with-plan-mode), and Claude writes the plan to a file. A long cross-package session [compacts its context](/docs/en/context-window#what-survives-compaction) along the way. Claude Code re-injects the plan file after each compaction, so the plan survives where conversation history may not ## Next steps