CLAUDE.md Hierarchy
How Claude Code layers memory files across user, project, and directory scopes — and why they concatenate rather than override.
CLAUDE.md is Claude Code's persistent memory: a Markdown file whose contents are injected into every session so the agent remembers your conventions without being reminded. What trips people up is that these files exist at three scopes and combine in a specific way. Understanding that layering is the single most tested idea in this lesson.
The three scopes
Claude Code discovers memory files at three levels, from broadest to narrowest. Each answers a different question about *who* and *where* the rules apply.
- User scope —
~/.claude/CLAUDE.mdlives in your home directory, applies to every project you touch, and is never committed. Great for personal preferences; useless to teammates who clone the repo. - Project scope —
CLAUDE.mdat the repo root (or.claude/CLAUDE.md) is version-controlled and shared with everyone automatically. This is where team-wide standards belong. - Directory scope — a
CLAUDE.mdinside a subfolder (e.g.packages/api/CLAUDE.md) adds conventions that only matter when you work in that part of the tree.
| Scope | Location | Shared via git? | Best for |
|---|---|---|---|
| User | ~/.claude/CLAUDE.md | No | Personal style, private notes |
| Project | CLAUDE.md or .claude/CLAUDE.md | Yes | Team conventions, architecture |
| Directory | subdir/CLAUDE.md | Yes | Package-specific rules |
Concatenation, not override
Every discovered file is concatenated into context, ordered broad to specific: user first, then project, then the directory files closest to your working path, with any CLAUDE.local.md appended last at each level. There is no precedence table. If two lines contradict each other, Claude may follow either one — the model treats this content as user guidance, not enforceable configuration.
Memory files merge; they do not override. Because conflicts resolve arbitrarily, never rely on a narrower CLAUDE.md to reliably cancel a broader rule.
When CLAUDE.md is not enough
If a rule *must* hold on every run — a blocked tool, a mandatory formatter, a permission policy — guidance in CLAUDE.md is the wrong home because compliance is not guaranteed. Move it to settings.json, which the client enforces regardless of what Claude decides, or wire it into a lifecycle hook that fires at a fixed point.
| CLAUDE.md | settings.json | |
|---|---|---|
| Conflict handling | Concatenated; arbitrary | Strict: managed > local > project > user |
| Enforcement | Guidance only | Client enforces every time |
| Use case | Behavioral guidance | Hard, non-negotiable rules |
Write "always run the formatter" as a line in CLAUDE.md. It is guidance only, so Claude may skip it on any given run.
# CLAUDE.md
- Always run `prettier --write` before finishing.Enforce it in settings.json (or a lifecycle hook), which the client applies every time regardless of what Claude decides.
// .claude/settings.json
{
"hooks": {
"PostToolUse": [{ "command": "prettier --write ." }]
}
}Modular organization and diagnostics
Large memory files can be split with @ path imports, which inline a referenced file exactly as if pasted. Note that imports load eagerly — they do not shrink the context Claude sees. Use CLAUDE.local.md for gitignored personal tweaks, and run /memory to *see which files are already loaded*. /memory is a diagnostic; it does not load or activate configuration.
# .claude/CLAUDE.md (project scope, committed)
## Conventions
- Use camelCase for variables, PascalCase for types.
- Every new module ships with a colocated *.test.ts file.
## Imported standards
@./standards/error-handling.md
@./standards/testing.mdPut shared team standards in your user-scope ~/.claude/CLAUDE.md. Git never commits it, so teammates who clone the repo get none of the rules.
# ~/.claude/CLAUDE.md (user scope, NOT committed)
- Every module ships a colocated *.test.ts file.Put shared standards in the project-scope CLAUDE.md at the repo root. It is version-controlled, so everyone gets it automatically.
# CLAUDE.md (project scope, committed)
- Every module ships a colocated *.test.ts file.Claude follows conventions perfectly for a veteran but ignores them for a new hire who just cloned the repo. Cause: the rules live in the veteran's ~/.claude/CLAUDE.md (user scope), which git never shares. Fix: move them to the project-level CLAUDE.md.
Ask 'who needs this rule?' Everyone on the repo → project scope. Just this package → directory scope. Just me, everywhere → user scope.
How the exam will try to trick you
The distractors below look right under time pressure — learn the tell.
- The trap
A new teammate gets none of the conventions, so they must install an MCP server or run
/memoryto activate the config files.Correct answerThe shared rules live in the original developer's user-scope
~/.claude/CLAUDE.md; move them to the project-scope.claude/CLAUDE.md.Why: User-scope files are never committed, so a fresh clone only receives project-scope memory — nothing to activate.
- The trap
Running
/memoryloads the configuration files into the session.Correct answer/memoryis a diagnostic that shows which files are already loaded; memory loads automatically by hierarchy and location.Why: It is a debugging view, not an activation mechanism.
- The trap
For conventions that span many directories, add a directory-level
CLAUDE.md.Correct answerDirectory-level files apply only within their own folder; use
.claude/rules/with glob patterns for cross-directory conventions.Why: Directory scope is narrowly bounded, so a widespread convention would need a duplicate file in every folder.
Key takeaways
- CLAUDE.md exists at user, project, and directory scopes.
- Files concatenate broad-to-specific; there is no override precedence.
- Conflicting rules resolve arbitrarily, so don't rely on narrowing to cancel a rule.
- Hard, guaranteed rules belong in settings.json or hooks, not CLAUDE.md.
- @ imports load eagerly and do not reduce context size.
- /memory reveals loaded files but never loads them.
Frequently asked questions
What is CLAUDE.md in Claude Code?+
CLAUDE.md is a Markdown memory file whose contents are injected into every Claude Code session so the agent automatically follows your conventions, architecture notes, and preferences without being re-told each time.
Does a directory CLAUDE.md override the project one?+
No. All discovered files are concatenated into context rather than overriding each other. If a directory-level line contradicts a project-level line, Claude may follow either, so use settings.json for rules that must always win.
Where should team-wide conventions live?+
In the project-level CLAUDE.md at the repo root (or .claude/CLAUDE.md), which is version-controlled and shared with everyone. User-level ~/.claude/CLAUDE.md is never committed, so teammates never receive it.