Blog
The CLAUDE.md Hierarchy Falls Apart in a Monorepo
10 min read
Claude Code lets you nest CLAUDE.md files: one at the repo root, one in your home directory, and one in any subdirectory that needs its own context. In a small project this is tidy. In a real monorepo it becomes a sprawl of partially-overlapping files at a dozen levels of staleness, where you cannot tell which one loaded, which one is wrong, or whether the right one was even consulted.
The feature is sold as "scoped context." What you actually get at scale is fragmentation — the same codebase described in eight different files by eight different people at eight different points in time.
What the hierarchy looks like at scale
Picture a normal monorepo — a couple of apps, a few services, some shared packages — translated into the CLAUDE.md hierarchy:
A real monorepo, in CLAUDE.md terms
~/.claude/CLAUDE.md # user-level, your personal prefs
/CLAUDE.md # root: "we use pnpm, turborepo"
/apps/web/CLAUDE.md # "Next.js, app router, RSC"
/apps/admin/CLAUDE.md # "legacy CRA, do not copy patterns"
/services/payments/CLAUDE.md # "Python, async SQLAlchemy"
/services/auth/CLAUDE.md # last edited 8 months ago
/packages/ui/CLAUDE.md # "Tailwind tokens live in..."
/packages/sdk/CLAUDE.md # ...does this even exist?
8 files. 8 owners (in theory). 8 staleness clocks.Each file was a good idea when someone created it. Collectively they are a maintenance surface nobody owns. The root file knows nothing about the packages; the package files know nothing about each other; and the auth service's file has not been touched since before the last rewrite. This is the team drift problem multiplied by the number of directories.
The questions the hierarchy can't answer
A monorepo exists precisely because the parts depend on each other. That is the one thing per-directory files are structurally incapable of describing:
The questions the hierarchy can't answer
-> Which CLAUDE.md actually loaded for THIS edit?
-> When root says "async everywhere" and a package
predates that rule, which wins?
-> A change in packages/ui breaks apps/web — whose
CLAUDE.md describes that relationship? (none of them)
-> Who reviews 8 markdown files for accuracy on a PR? (no one)The most important facts in a monorepo are the relationships between packages — and those live in the gaps between the files, owned by none of them. When a change in packages/ui ripples into three apps, there is no CLAUDE.md that captures the ripple, because each file only describes its own folder.
You don't know which file the model used
Even setting accuracy aside, the loading behavior is opaque in practice. Depending on where the agent is working and how deep the tree goes, you do not have a clear, auditable view of which files were pulled into context and which were not. When the model gets something wrong, you cannot easily tell whether it read a stale file, missed the relevant one, or saw two that contradicted each other. Debugging the grounding becomes its own task.
Conflicts make this worse. When the root file states a rule the team adopted last quarter and a package predates it, both statements are "true" in their own file, and there is no precedence the model reliably honors. You are left guessing which version of reality won.
A monorepo needs one representation, not many files
The fix is not better discipline across eight files — it is a single representation that spans the whole tree and understands the dependencies between its parts:
What a monorepo actually needs
Per-file CLAUDE.md:
-> describes one package, in isolation
-> blind to cross-package dependencies
-> fragments the picture into N partial views
Cross-package semantic index:
-> one representation spanning every package
-> knows apps/web imports packages/ui imports ...
-> answers "what breaks if I change this" across the treeA cross-package index does not care about directory boundaries. It knows that apps/web imports packages/ui, that services/payments calls services/auth, and can answer the question that no per-folder file can: what breaks if I change this. That is the same cross-repo capability described in /init vs. a semantic index, applied within a single monorepo.
Where Kognita fits
Kognita indexes the whole monorepo as one continuously updated semantic representation, spanning every app, service, and package, and including the dependencies between them. There is no hierarchy of files to maintain, no ambiguity about which one loaded, and no blind spot at the package boundaries — because the index does not have boundaries, it has the actual import and call graph. The agent retrieves the relevant cross-package context per query, current as of the last merge, instead of assembling a guess from a scatter of folder-local markdown.
Final take
The nested CLAUDE.md model promises scoped context and delivers fragmentation: many files, many owners, many staleness clocks, and a structural blindness to the cross-package relationships that are the whole reason you have a monorepo.
A monorepo is defined by how its parts connect. You cannot describe that with a file per folder — you need one index that spans the tree and knows what depends on what.