How CLAUDE.md File Hierarchy Works: User, Project, Subtree, Local
▶ Watch on YouTube & subscribe to The Stack Underflow
You wrote a careful CLAUDE.md. Claude Code still ignores half of it. That is not a bug and it is not Claude being difficult. It is the instruction-resolution system working exactly as designed — and the file you edited is probably not the one Claude is reading, or it is being quietly overridden by a more specific one.
Claude Code does not read a single configuration file. It reads up to five, layers them by scope, and concatenates them into the context window in a defined order. Rules that appear later in context are the ones Claude holds most freshly — which is how specificity “wins.” Put a rule at the wrong tier and a more-specific one overwrites it before the model even sees your line.
The one-sentence version: Claude Code merges CLAUDE.md content from up to five tiers — managed policy, user, project, subtree, and local — and the more specific a file is to the current working directory, the later it appears in context and the more it governs Claude’s behavior.
The Five Tiers
The official docs (code.claude.com/docs/en/memory, 2026) describe the load order from broadest to most specific:
/etc/claude-code/CLAUDE.md <- managed (org-wide, IT/DevOps deployed)
~/.claude/CLAUDE.md <- user (your machine, every project)
<repo-root>/CLAUDE.md <- project (checked in, whole team)
<repo-root>/<subdir>/CLAUDE.md <- subtree (loads on demand, scoped)
<repo-root>/CLAUDE.local.md <- local (git-ignored, just you)
| Tier | File location | Checked in? | Scope |
|---|---|---|---|
| Managed | Platform-specific system path | No (IT-deployed) | Every user on the machine |
| User | ~/.claude/CLAUDE.md | No | Every project on your machine |
| Project | <repo-root>/CLAUDE.md or .claude/CLAUDE.md | Yes | Whole repo, whole team |
| Subtree | <subdir>/CLAUDE.md (any subdirectory) | Yes | Files inside that directory only |
| Local | <repo-root>/CLAUDE.local.md | No (git-ignored) | Whole repo, just you |
The managed tier is new as of 2025-2026 and targets organizations deploying Claude Code at scale. IT or DevOps places a file at a system-wide path (macOS: /Library/Application Support/ClaudeCode/CLAUDE.md; Linux/WSL: /etc/claude-code/CLAUDE.md; Windows: C:\Program Files\ClaudeCode\CLAUDE.md). Individual developers cannot override or exclude it — it always loads, before anything else.
How Loading Actually Works
The loading mechanism is not a merge algorithm with explicit precedence rules. It is ordered concatenation. Claude Code walks up the directory tree from your working directory toward the filesystem root, collects every CLAUDE.md and CLAUDE.local.md it finds, then concatenates them. Files closer to the root appear earlier in context; files closer to your working directory appear later.
Context window at session start:
[managed CLAUDE.md] <- loaded first, appears earliest
[user ~/.claude/CLAUDE.md]
[project <repo>/CLAUDE.md]
[project <repo>/.claude/CLAUDE.md]
[CLAUDE.local.md] <- loaded last, appears latest
... conversation begins ...
Because language models attend to recent tokens more reliably, content that appears later in the concatenation effectively governs behavior when two instructions conflict. A project-level rule that says “indent 2 spaces” overrides a user-level rule that says “indent 4 spaces” because the project rule lands in context after the user rule, and the model reads both but holds the more recent one when it writes code.
This also means the subtree files behave differently from all the others: they do not load at session start. They are included on demand, injected into context the moment Claude reads a file inside that subdirectory. An frontend/CLAUDE.md file is invisible while Claude works in backend/. It becomes active the instant Claude opens any file under frontend/.
Agent editing backend/server.ts:
[managed] [user] [project] [local] (subtree: NOT loaded)
Agent editing frontend/App.tsx:
[managed] [user] [project] [local] [frontend/CLAUDE.md]
One important edge case: after /compact, the project-root CLAUDE.md is automatically re-read and re-injected. Subtree files in subdirectories are not — they reload the next time Claude reads a file in that subdirectory. Instructions you gave only in conversation (not in any file) are lost entirely after compaction. This is why CLAUDE.md should hold anything you want Claude to remember across a long session.
The .claude/rules/ Directory
For larger projects, a flat CLAUDE.md file becomes unwieldy. The .claude/rules/ directory lets you split instructions into topic-specific markdown files — each one covering a single concern. The directory supports path-scoped rules using YAML frontmatter: a rule file with a paths field only enters context when Claude works with files matching that glob.
your-project/
.claude/
CLAUDE.md <- main project instructions
rules/
code-style.md <- always loaded (no paths field)
testing.md <- always loaded
api-design.md <- always loaded
frontend.md <- loads only when matching files are touched
A path-scoped rule looks like this:
---
paths:
- "src/api/**/*.ts"
- "lib/**/*.ts"
---
# API Rules
All handlers must validate input.
Use the standard error response format.
Rules without a paths field load unconditionally, the same as .claude/CLAUDE.md. Rules with a paths field are lazy-loaded, the same as subtree CLAUDE.md files — they only appear in context when Claude reads a file matching the pattern. This is a powerful way to keep context lean in a large monorepo: backend rules never pollute a frontend session.
User-level rules also exist at ~/.claude/rules/, applying to every project on your machine. Project rules load after them, giving project rules higher effective priority.
Placing Rules in the Right Tier
A practical heuristic: ask how broadly this rule is true, then place it at the outermost tier where it remains accurate.
| Example rule | Where it belongs | Why |
|---|---|---|
| ”Use Azure, never AWS” | User (~/.claude/CLAUDE.md) | True for every project you touch |
”Use pnpm; run pnpm ci before commit” | Project (CLAUDE.md) | True for this repo, should be shared |
| ”This folder is React and Tailwind only” | Subtree (frontend/CLAUDE.md) | True only for files under frontend/ |
| ”Verbose debug logging during issue #412” | Local (CLAUDE.local.md) | True only for you, only right now |
”All engineers must run make lint” | Managed (/etc/claude-code/CLAUDE.md) | Enforced policy for the whole org |
The most common mistake is placing a subtree-specific rule in the project file. A rule like “use Tailwind utility classes” in the root CLAUDE.md will fire when Claude is editing Rust backend code, where it is irrelevant and wastes context space. Move it to frontend/CLAUDE.md and it only fires when Claude is actually in that folder.
The second most common mistake is the opposite: placing a genuinely team-wide rule in the local file so it never gets shared. Commit team conventions to the project tier.
Imports and the @-Syntax
CLAUDE.md files can pull in other files using the @path/to/file syntax anywhere in the document body. Imported files are expanded and injected into context at session start alongside the file that references them. This lets you break a growing project CLAUDE.md into topic-specific files without losing the “loads at startup” guarantee:
See @README for project overview.
See @package.json for available scripts.
# Additional Instructions
- Git workflow: @docs/git-instructions.md
Relative paths resolve from the file containing the import, not from the working directory. Imports can be nested up to four hops deep. Wrapping a path in backticks (`@README`) treats it as literal text and prevents import resolution — useful when documenting the syntax itself.
One note on context cost: importing a file does not make it lazy-loaded. Every @-imported file is expanded into context at startup, the same as if you had pasted its content inline. If you want rules to load on demand instead, use .claude/rules/ with paths frontmatter.
Common Misconceptions
-
“My rule is being ignored.” More often, it is in the wrong tier, or it lives in a subtree file that never loaded because Claude did not read any files in that directory. The
/memorycommand lists every file currently loaded in your session. If your file is not in that list, Claude cannot see it. -
“The project CLAUDE.md overrides user settings.” This is directionally correct but the mechanism is ordered concatenation, not an explicit override. The project file appears later in context than the user file, so when both give conflicting guidance the model follows the project instruction. It is a feature: team conventions should govern shared code even when your personal defaults say otherwise.
-
“CLAUDE.local.md is just a secret version of CLAUDE.md.” It is git-ignored and personal, but it applies at the whole-repo level — it is not scoped to a subfolder. For folder-specific personal overrides, you would need to add a subtree file, which would then be checked in. If you want a personal subtree-level override, the recommended pattern is to import a home-directory file from a subtree CLAUDE.md you do check in.
-
“All CLAUDE.md files load at startup.” Only files at or above your working directory in the tree load at startup. Subdirectory (subtree) files load on demand. Testing a subtree rule by running a command that only touches a different directory will make the rule look inert — it simply never fired.
-
“CLAUDE.md instructions are enforced like configuration.” They are not. CLAUDE.md content is delivered as a user message after the system prompt, not as enforced configuration. Claude reads it and tries to follow it, but there is no guaranteed compliance for vague or contradictory instructions. If you need something to happen unconditionally — like running a linter before every commit — use a hook instead. Hooks execute as shell commands at fixed lifecycle events, regardless of what Claude decides to do.
Frequently Asked Questions
Can I have more than one subtree CLAUDE.md in a project?
Yes. Any subdirectory can have its own CLAUDE.md. A monorepo with frontend/, backend/, and infra/ directories can carry a separate file in each, with none of them loading when Claude is in a different part of the tree. You can also nest them: frontend/components/CLAUDE.md only loads when Claude works inside frontend/components/.
Does CLAUDE.local.md override project instructions or only user instructions?
It overrides both user and project, because it appears later in the concatenated context. The effective load order from earliest to latest context position is: managed, user, project, local, then any in-scope subtree files. An in-scope subtree file is the last thing Claude reads, so it holds the most contextual weight when conflicts arise.
What happens if I put a CLAUDE.md in a directory above the repo root?
Claude Code walks up the tree from your working directory, so ancestor directories outside the repo also contribute. This is usually unintentional. If you are in a monorepo and picking up another team’s CLAUDE.md from a parent directory, use claudeMdExcludes in your .claude/settings.local.json to skip it by glob pattern.
How do I debug which files are actually loaded?
Run /memory inside a session. It lists every CLAUDE.md, CLAUDE.local.md, and .claude/rules/ file currently in scope. If a file you expected to see is missing, Claude cannot see it either. You can also enable the InstructionsLoaded hook to log exactly which files load, when they load, and why — useful for diagnosing path-specific rules that are not firing.
How does this interact with subagents, skills, and hooks?
The CLAUDE.md files that are in scope when a subagent is spawned are also in scope for that subagent. The instructions steer not just the main conversation but all parallel subagent tasks. Skills and hooks are separate mechanisms that sit on top of the CLAUDE.md foundation — CLAUDE.md tells Claude how to behave; skills package repeatable workflows that load on demand; hooks enforce actions at fixed lifecycle points regardless of Claude’s decisions. The next tutorial covers exactly how those three interact.
Where this fits in the series
This tutorial builds on How Claude Code Works: the Agent Loop, where you saw how Claude Code reads context at session start — CLAUDE.md files are the primary content loaded at that moment. It also connects directly to Claude Code Hooks Explained, because hooks are the enforcement layer you reach for when CLAUDE.md instructions are not reliable enough. The mental model overview shows where CLAUDE.md sits in the full Claude Stack — Layer 4, the Surfaces layer that wraps the model, the context window, and the tool layer underneath.
The next episode in the series, Claude Code Skills, Subagents, Hooks, and Plugins, covers the building blocks that your CLAUDE.md instructions steer. Browse all tutorials to follow the full sequence.
Found this useful? The deep version lives on YouTube — new breakdowns of how AI dev tools actually work, weekly.
Subscribe on YouTube →