Claude Code in a monorepo: how to split CLAUDE.md files across teams
A single CLAUDE.md file works well for one team in one repository. In a monorepo it slowly turns into a problem. The payments team adds its rules, the frontend team adds theirs, the platform team adds a deployment section, and soon every session starts by loading three hundred lines of instructions

Posted on Oct 26 • Originally published at aiworkspacebuilder.ai • Fully Autonomous
A single CLAUDE.md file works well for one team in one repository. In a monorepo it slowly turns into a problem. The payments team adds its rules, the frontend team adds theirs, the platform team adds a deployment section, and soon every session starts by loading three hundred lines of instructions, most of which have nothing to do with the task.
That costs more than context space. The Claude Code documentation recommends keeping each CLAUDE.md under 200 lines, because longer files consume more context and reduce how reliably Claude follows them. It also warns that when two instructions contradict each other, Claude may pick one arbitrarily. A file that four teams edit is where contradictions come from.
The fix is to stop treating instructions as one file and start treating them like code: split by owner, loaded only where they apply.
Three loading rules matter for a monorepo.
Files above you load at launch. Claude Code loads CLAUDE.md (and CLAUDE.local.md) from the directory you start it in and every directory above it. Start a session in services/payments/ and you get services/payments/CLAUDE.md, services/CLAUDE.md and the root CLAUDE.md. They are concatenated, not overridden, ordered from the root down, so the most specific file is read last.
Files below you load on demand. CLAUDE.md files in subdirectories don't load at launch. Each one loads the first time Claude reads, writes or edits a file in that subdirectory. Start at the root and touch only the frontend, and the payments instructions never enter the session.
Rules can be scoped to paths. Markdown files in.claude/rules/ can carry a paths field in their frontmatter. A scoped rule loads only when Claude works with a file that matches one of its patterns:
--- paths: - " services/payments/**/*.ts" --- # Payments rules - Amounts are integers in minor units. Never use floating point for money. - Every new endpoint needs an idempotency key. Enter fullscreen mode Exit fullscreen mode Rules without a paths field load at launch like the root CLAUDE.md.
Put that together and a monorepo can look like this:
repo/ ├── CLAUDE.md # shared: build, test, git workflow, ownership ├──.claude/ │ ├── settings.json # shared permissions and hooks │ └── rules/ │ ├── security.md # no paths field: always loaded │ └── migrations.md # paths: "db/migrations/**" ├── apps/ │ └── web/ │ └── CLAUDE.md # frontend team: components, styling, state └── services/ ├── payments/ │ └── CLAUDE.md # payments team: money handling, idempotency └── search/ └── CLAUDE.md # search team: indexing, query conventions Enter fullscreen mode Exit fullscreen mode What goes where:
Add the per-directory files to your CODEOWNERS so each team reviews changes to its own instructions, the same way it reviews its code.
A CLAUDE.md can pull in other files with @path/to/file, for example @docs/git-workflow.md. Paths are relative to the file that contains the import, and imports can nest up to four levels deep.
Imports are useful for reusing a document that already exists rather than copying it. But the documentation is explicit that they don't reduce context cost: imported files load at launch along with the file that imports them. If the goal is a smaller session, use directory files and scoped rules, not imports.
Because files above your working directory always load, someone working deep in the tree still gets every ancestor file. If an ancestor file carries instructions that don't apply to your work, the claudeMdExcludes setting skips files by path or glob pattern:
{ "claudeMdExcludes": [ "**/monorepo/CLAUDE.md", "/home/user/monorepo/other-team/.claude/rules/**" ] } Enter fullscreen mode Exit fullscreen mode Patterns match absolute paths, which differ from one machine to the next, so the documentation's example puts this in.claude/settings.local.json, the uncommitted personal settings file. Treat it as a personal escape hatch. If many people are excluding the same file, the real fix is to move that content down into the directory it belongs to.
One thing can't be excluded: an organization's managed CLAUDE.md, deployed by IT to a fixed system path. Company-wide policy stays in force regardless of individual settings.
Many monorepos already carry an AGENTS.md for other coding tools. Recent versions of Claude Code read AGENTS.md as project instructions, but by default only when there is no CLAUDE.md in your working directory or above it. Once you add a CLAUDE.md, Claude reads that instead.
If you want one source of truth, the simplest option is a CLAUDE.md that imports it: put @AGENTS.md in your CLAUDE.md and add any Claude-specific instructions below the import.
One root file for what is true everywhere. One file per team, next to that team's code. Scoped rules for the concerns in between. Each file small enough that its owner can read the whole thing in a minute.
Most teams already have this knowledge, spread across READMEs, onboarding guides and wiki pages. That is what we built AI Workspace Builder for. You upload the docs your team already has, and it generates the CLAUDE.md, a profile for each role, and an install script in 15 to 30 seconds, using your own Anthropic API key. There's one free trial workspace, no card required, and our free templates are a good starting point for the root file.