CLAUDE.md: How Claude Code Thinks About Your Project
The one file that changes everything: project memory, conventions, and context strategy.
Claude Code loads CLAUDE.md at the start of every session to build its instruction context. This file, combined with a layered system of organization policies, personal preferences, and path-specific rules, shapes what the agent assumes about your repository. It tells the agent how your code is organized, which conventions to follow, and which commands to run.
It helps to be clear about what kind of power that is. CLAUDE.md is strong guidance, not enforcement. Claude Code adds it to the conversation as a message right after the system prompt, not inside the system prompt itself, and Anthropic's memory documentation says Claude treats it "as context, not enforced configuration." Claude usually follows it, but nothing forces it to. For a rule that must never break, such as "never touch the production database," use a permission deny rule or a hook, which Part 4 covers.
What goes in a good CLAUDE.md?
Write down what you would otherwise explain again in every session: how to build and test, where things live, and the rules a new teammate would need. Here is a short example for our side project, a small web app with a TypeScript API (SQLite in development) and a React front end:
Notice how concrete each line is. The docs recommend instructions you could check, such as "Run npm test before committing" instead of "Test your changes," and a target of under 200 lines per file, because longer files use more context and are followed less reliably.
You do not have to start from a blank page. Run /init in a session and Claude reads your codebase and writes a first CLAUDE.md with the build commands, test instructions and conventions it discovers; if one already exists, it suggests improvements instead of overwriting it. To check what actually loaded, run /context and look under Memory files. To open and edit any of your memory files, run /memory.
One more case: if your repository already has an AGENTS.md written for other coding agents and no CLAUDE.md, recent versions of Claude Code (2.1.277 and later) read the AGENTS.md instead, so you do not need to duplicate it.
How does CLAUDE.md get loaded into Claude Code?
Claude Code reads CLAUDE.md files from your working directory and every directory above it. It also loads your organization's managed policy file and your personal files, all before your first prompt is processed. The files are concatenated rather than overriding each other, so the model sees one combined set of instructions.
When you start Claude Code inside services/billing/api/, Claude Code collects CLAUDE.md from that directory, from services/billing/, from services/, and from the repository root. In the context they appear root first, so the most general content comes first and the instructions closest to where you started are read last. The root file describes the overall architecture. The deeper files add stack-specific constraints and local commands.
CLAUDE.md files in folders below where you started are not loaded at launch. Each one loads once Claude reads, writes or edits a file in its folder. If you started in services/ and never touch services/frontend/, the frontend's CLAUDE.md never enters the context. This scoping keeps the context lean and focused on the area you are actually working in.
The full order, from broadest to most specific, looks like this:
Two details in that picture trip people up. ./CLAUDE.md and ./.claude/CLAUDE.md are two places for the same project file, so use one or the other. And CLAUDE.local.md is not loaded last overall: within each folder it comes right after that folder's CLAUDE.md, so your personal notes are the last thing Claude reads at that level.
Later instructions do not erase earlier ones. They all sit in the context together, and the order does not settle conflicts. The docs are blunt about it: "if two instructions contradict each other, Claude may pick one arbitrarily." So do not rely on a local file to quietly override a global one. Remove the contradiction instead. Running /doctor prompt-audit in a session asks Claude to look through your instruction files for outdated or conflicting lines and propose edits.
Claude Code also respects an exclusion list. The claudeMdExcludes setting accepts glob patterns, matched against absolute file paths, that stop certain CLAUDE.md files from loading even though they exist on disk. That helps in a big monorepo where other teams' files would otherwise be picked up. A managed policy file cannot be excluded.
Why does the hierarchy matter for monorepos?
The layered loading lets you put general rules at the root and service-specific rules in subdirectories. Claude Code sees only the instructions that are relevant to the area you are working in. This keeps the effective context small and avoids overwhelming the model with irrelevant detail.
Consider a monorepo: services/billing/, services/frontend/, services/api/. The root CLAUDE.md describes the tech stacks, the shared library layout, and the rule that integration tests must pass before pushing. The services/billing/ CLAUDE.md adds billing domain concepts, payment processor dependencies, and the command to run billing tests. The services/api/ CLAUDE.md defines HTTP API (application programming interface) conventions and local run commands.
When you start Claude Code in the repository root, the agent sees only the root CLAUDE.md at launch. It knows the big picture but not the billing specifics. As soon as Claude opens a file in services/billing/, Claude Code loads that directory's CLAUDE.md, adding the billing rules to the context. The agent now knows both the repo-wide rules and the billing-specific ones.
Where you start is therefore a choice. Starting inside the package folder loads its rules up front instead of on the first file Claude touches there, and it limits Claude's file access to that subtree until you grant more. Anthropic's guide to monorepos and large codebases suggests one CLAUDE.md per package, starting in the package when the work is scoped to it, and starting at the root when a task spans several packages.
What happens when you import external documents?
An @path import pulls the full content of another file into the instruction context. A plain text reference like "See docs/style.md" does not load the file. The model reads the sentence but never sees the file's contents. That is a common source of "Claude ignores our guidelines" reports.
The correct pattern is to write @docs/coding-style.md inside CLAUDE.md. There is no @import keyword: the @ followed by a path is the whole syntax. A relative path resolves from the file that contains the import, not from your working directory. Claude Code reads the file at launch and places its content alongside the CLAUDE.md that imported it, so the model sees the imported text as if it had been written inline. If you only want to mention a path without importing it, wrap it in backticks: import parsing skips code spans.
Imports can nest. An imported file can contain its own @path imports, up to four hops deep. This lets you split a bulky CLAUDE.md into smaller, focused documents and include them where they are needed: the root CLAUDE.md can import a central coding style guide, while a service's CLAUDE.md imports that service's runbook. Keep one thing in mind. Imports organize a long file but do not save context, because imported files also load at launch.
An import path can also start with ~/ to point at your home directory, which is a handy way to share personal instructions across several copies of the same repository. Claude Code treats such imports with care. When a project's CLAUDE.md imports a file from outside your working directory for the first time, Claude Code shows an approval dialog listing the files. If you decline, those imports stay off and the dialog does not appear again. Imports inside your own ~/.claude/CLAUDE.md load without the dialog, because you wrote that file yourself. The model never reads the filesystem to resolve imports; Claude Code does all of it before the conversation starts.
How do path-specific rules interact with CLAUDE.md?
Rules are markdown files in .claude/rules/, one topic per file. A rule without a paths field loads in every session, with the same priority as .claude/CLAUDE.md. A rule becomes conditional only when you add a paths field to its YAML frontmatter. Then it loads when Claude reads, writes or edits a file that matches one of the patterns.
For example, this rule applies only to React test files:
When the agent opens a test file, Claude Code adds the rule to the context. While it works on other files, the rule is absent. This avoids cluttering every session with test-specific guidance.
Path-specific rules complement CLAUDE.md. The root CLAUDE.md defines universal conventions. Directory CLAUDE.md files add package-level guidance. Path-specific rules add file-type-specific instructions that cut across directories. The agent's behavior is a composite of all these layers, and as with CLAUDE.md, the layers do not rank each other: keep them consistent rather than expecting the most specific one to win.
The key difference from a directory CLAUDE.md is that a path-specific rule is not tied to one folder. It follows file types across the whole repository. That makes it a good home for conventions that should apply everywhere, like naming patterns for configuration files or security checks for YAML files. Your own ~/.claude/rules/ folder works the same way for every project on your machine.
Quick Reference
| Property | Value |
|---|---|
| Managed policy (macOS) | /Library/Application Support/ClaudeCode/CLAUDE.md |
| Managed policy (Linux and WSL) | /etc/claude-code/CLAUDE.md |
| Managed policy (Windows) | C:\Program Files\ClaudeCode\CLAUDE.md |
| Your instructions, all projects | ~/.claude/CLAUDE.md and ~/.claude/rules/ |
| Project instructions | ./CLAUDE.md or ./.claude/CLAUDE.md (pick one) |
| Project rules | ./.claude/rules/*.md (a paths field makes a rule conditional) |
| Local, not committed | ./CLAUDE.local.md (add it to .gitignore) |
| Import syntax | @path/to/file.md, relative to the importing file, up to four hops deep |
| Loading order | Managed policy, your files, then each folder from the root down to where you started; subfolder files and path rules on demand |
| Create a first file | /init |
| Check what loaded | /context (under Memory files); /memory to open and edit |
| Size guidance | Under 200 lines per file |
| Exclusion setting | claudeMdExcludes (glob patterns on absolute paths) |
Frequently Asked Questions
Q: Can I have multiple CLAUDE.md files in one repository?
Yes, and they stack. The root CLAUDE.md applies to the entire project. CLAUDE.md files in subdirectories below where you started load when Claude opens a file in that subtree; files in the directories above where you started load at launch.
Q: What if a rule in a subdirectory CLAUDE.md contradicts the root?
Both are loaded, and Claude may follow either one; order does not reliably decide it. Avoid contradictions. Use the root file for rules every package shares and the subdirectory files for additive context, and run /doctor prompt-audit now and then to catch conflicts. If something must never happen, enforce it with a deny rule or a hook instead.
Q: Do @path imports work recursively?
Yes. Imported files can contain their own @path imports, up to four hops deep. Claude Code expands them all at launch, so they cost the same context as writing the text inline.
Q: How do I exclude a CLAUDE.md from being loaded?
Use the claudeMdExcludes setting in a settings file, for example .claude/settings.local.json if the exclusion is just for you. It accepts glob patterns matched against absolute paths, and the lists from different settings files are merged. Your organization's managed policy file cannot be excluded.
Q: What is the difference between CLAUDE.md and .claude/CLAUDE.md?
They are two locations for the same project file, so use one or the other. Putting it in .claude/CLAUDE.md keeps the repository root tidy, next to your rules and settings in the same folder.
Test yourself
You create a CLAUDE.md in services/billing/ with the instruction "Always run npm run test:billing before committing." You edit some billing files yourself in your editor, then start Claude Code from the repository root and ask it to commit your changes. It commits without running the tests. What is the most likely cause, and how would you fix it?
Answer: The billing CLAUDE.md never loaded. You started at the root, so at launch Claude Code loaded the root CLAUDE.md (plus your personal and managed files) and nothing below it. A CLAUDE.md in a subfolder loads only once Claude reads, writes or edits a file in that folder, and committing your edits needed only git commands, so Claude never opened a billing file. You can confirm it with /context: the billing file is not listed under Memory files. To fix it, start Claude Code in services/billing/, which loads that folder's CLAUDE.md and every one above it at launch, or move the rule into the root CLAUDE.md. Keep in mind that even a loaded CLAUDE.md is guidance. If the tests must run before every commit, enforce it with a hook, which Part 4 covers.
Next: Skills and Slash Commands: Teach It Your Workflows. It shows how to package a repeatable workflow so Claude can run it when you ask, or when the task calls for it.
If you want this kind of breakdown every week, how real systems actually work under the hood, subscribe to Internals Decoded at internalsdecoded.com.
Sources
- How Claude remembers your project
- Set up Claude Code in a monorepo or large codebase
- Settings files and precedence
- All settings