Claude Code Learning Hub
中文 Mingyu's Library

Hub / Tips / E · Configuration & choosing tools

Claude Code in a large monorepo

A million lines and dozens of packages — Claude's context fills up fast with unrelated code and other teams' conventions. The fix is to scope what it sees.

Large-repo configuration boils down to one sentence: let Claude see only the part relevant to the current task. There are four kinds of levers — layered CLAUDE.md files, choosing scope by launch directory, deny rules that block irrelevant reads, and exploration in isolated context. They stack on top of each other; they don't replace each other.

One-line answer

Answer Keep the root CLAUDE.md to repo-wide layout and shared conventions (under 200 lines); give each package its own CLAUDE.md (subdirectory files load on demand and don't consume startup context); launch Claude from the package directory for single-package tasks to shrink the scope; then use claudeMdExcludes to exclude other teams' files and Read deny rules to block dist/build/vendored code.

Steps

  1. Layer your CLAUDE.md files: root for the global picture, packages for local detail.OfficialAt startup Claude Code loads the CLAUDE.md of the working directory and all ancestor directories; subdirectory CLAUDE.md files are not loaded at startup, but on demand when Claude reads a file in that directory with the Read tool. So the right division of labor is: the root CLAUDE.md covers repo structure and global coding/commit conventions; packages/api/CLAUDE.md covers that package's test commands, directory layout, and local rules. Commit all of them so the whole team inherits them. Target under 200 lines per file — beyond that, move reference material into a skill or .claude/rules/ (rules can use a paths: frontmatter to load only when matching files are involved; see D4 CLAUDE.md & rules).
  2. Pick your scope with the launch directory.OfficialWhere you run claude from determines file access and which CLAUDE.md files load: for cross-package tasks launch from the repo root (it can read all files, loads only the root CLAUDE.md up front, subdirectory ones arrive on demand); for single-package tasks launch from packages/api/ (only that package's + its ancestors' CLAUDE.md load, and other packages never enter context at all). Note that .claude/settings.json project settings load only from the launch directory — unlike CLAUDE.md they are not inherited from parent directories. If you launch from a subdirectory and then need to change files across packages, use --add-dir ../shared or configure additionalDirectories in settings.
  3. Exclude the irrelevant: two switches.OfficialFirst, claudeMdExcludes (put it in .claude/settings.local.json to keep it personal) skips other teams' CLAUDE.md files by glob, e.g. "**/packages/web/**"; CLAUDE.md files delivered by managed policy cannot be excluded. Second, content search respects .gitignore by default, so ignored node_modules/ and dist/ never show up in search results; but for committed generated code and vendored dependencies, add Read deny rules such as "Read(./**/dist/**)", "Read(./**/*.generated.*)", "Read(./vendor/**)" — Claude won't even open them.
  4. Search and context strategy.OfficialTwo moves against "reading dozens of files to find one symbol": install the code intelligence plugin for your language (/plugin install typescript-lsp@claude-plugins-official) so Claude jumps to definitions and finds references through the language server instead of scanning text; and hand broad exploration to a subagent, which reads files in its own context and brings only conclusions back to the main session (D10 Subagents). Before a big cross-package change, plan first and have Claude write the plan to a markdown file — long sessions compact their context, but a plan on disk doesn't get lost.
  5. Optional extras.OfficialWhen developing in isolated worktrees, worktree.sparsePaths makes new worktrees check out only the listed directories (remember to include .claude), and symlinkDirectories links node_modules back to the main checkout; each package can also carry its own .claude/skills/, so the API package's testing playbook loads only during API tasks. Once configured, run /context and confirm the Memory files section lists exactly the files you expect.

Copy-paste prompt

This is a monorepo — help me set it up for large-repo work:

1. Read the root layout and what each package under packages/ does, then write a
   CLAUDE.md at the repo root, under 200 lines: repo layout only, a one-line
   description per package, and global conventions (package manager, commit style,
   rules like "run commands in the package directory, not the root");
2. Write a dedicated CLAUDE.md for the package I'm working on, packages/<name>:
   build/test/migration commands, directory layout, package-specific conventions;
3. In the launch directory's .claude/settings.json, add permissions.deny Read
   rules blocking dist/, build/, *.generated.* and vendored code;
4. List every file you created or modified. Afterwards I'll restart the session
   and use /context to verify that Memory files loads only the expected files.

Sources & last verified