What you’ll be able to do
- State what CLAUDE.md is for and why it lives in git
- Layer configuration from user scope down to directory scope correctly
- Decide what belongs in CLAUDE.md versus a system prompt
What you need to know
CLAUDE.md is project memory, checked into version control
CLAUDE.md is a plain-text file Claude Code reads automatically at the start of a session. It exists to answer the questions a new engineer would otherwise ask in the first ten minutes: how this repo is structured, which commands build and test it, which conventions are non-negotiable, and which shortcuts are actually landmines.
The detail that matters architecturally: it is versioned alongside the code it describes. When the build command changes, the person who changed it updates CLAUDE.md in the same commit. There is no separate system to keep in sync, and no drift between "what the docs say" and "what's actually true this week" — because if it drifts, the next PR that touches the build script is the one that fixes it.
Scope layers broad to specific
Claude Code resolves CLAUDE.md at more than one level, and the architecture question is which level owns which fact:
- User-level — a person's own preferences that apply across every project they touch (their preferred verbosity, their editor conventions). This is about the human, not the repo.
- Project-level (repo root) — facts true for anyone working in this codebase: the stack, the test command, the deploy process, the architectural rules everyone must follow.
- Directory-level — narrower facts true only inside one package or service in a monorepo, layered on top of the project-level file rather than repeating it.
The design failure is copying the same project-wide fact into every directory's file "just in case." That's not defense in depth, it's N places to update the next time the fact changes — and N-1 of them will eventually be wrong.
What doesn’t belong in CLAUDE.md
CLAUDE.md is for durable, repo-true facts. It is not a place to restate the current request, and it is not a substitute for a system prompt in an API-driven application.
The first version is stale the moment the task changes and actively misleads the next session. The second is still true a year later. A CLAUDE.md that needs editing every session is a sign the instructions belong in the prompt for that session, not in project memory.
Key concept
CLAUDE.md is versioned, layered project memory — durable facts about the repo, not the request. If a line stops being true when the task changes, it doesn’t belong there.
When a scenario describes a team's CLAUDE.md growing unreadable or contradicting itself across packages, the fix is almost always re-layering it by scope, not trimming prose.
Practice scenario
Work it through, then open this
The root file should hold only what’s true for the whole repo — the shared conventions and the fact that packages exist. Each team’s package-specific build steps belong in a CLAUDE.md inside their own package directory, which Claude Code layers on top of the root file automatically. This removes the merge conflicts because each team edits a file the others never touch, and it removes noise because a session working in one package doesn’t need the other two teams’ build steps in context at all.
Build exercise — Audit a CLAUDE.md for scope leaks
Intermediate · 20 min
What you’ll learn
- Spotting request-specific content that has leaked into project memory
- Deciding what moves to a directory-level file versus staying at the root
- Recognizing when a file’s size is a layering problem, not a content problem
-
Open a project’s root CLAUDE.md and flag any line that would stop being true if the current task changed.
- Why: Those lines are prompt content masquerading as project memory, and they’ll mislead the next unrelated session.
- You should see: At least one line that’s really about “what I’m doing today,” not “what this repo is.”
-
For a monorepo, check whether package-specific facts are duplicated at the root instead of living in that package’s own file.
- Why: Duplication at the wrong scope is what turns CLAUDE.md into a merge-conflict magnet as the repo grows.
- You should see: Either clean layering, or an opportunity to push a fact down to where it actually belongs.
Exam traps
Treating CLAUDE.md as a place for one-off, per-request instructions
It’s project memory, not a scratchpad for today’s task. Request-specific instructions belong in the prompt.
Duplicating the same convention across every subdirectory’s CLAUDE.md
Layering exists so a fact is stated once, at the scope where it’s true, and inherited everywhere below.
Assuming a single monolithic CLAUDE.md scales to a large monorepo
It becomes a merge-conflict bottleneck. Directory-level files scoped to each package solve this.
Putting secrets or environment-specific values in a file committed to git
CLAUDE.md is checked into version control and often shared broadly; secrets belong in environment configuration, not project memory.
Believing CLAUDE.md changes take effect mid-session without a reload
It’s read at session start. A running session doesn’t pick up an edit made to it in another terminal until it’s restarted.