Where the CLAUDE.md file lives and what to put in it
Where Claude Code looks for a CLAUDE.md file, what belongs in it, how imports and scopes work, and copy-paste examples for real projects.
A CLAUDE.md file is a plain markdown file that Claude Code reads at the start of a session. You use it to give Claude context it can't infer from your code: build and test commands, style rules that differ from defaults, repo etiquette, and project gotchas. Put it at ./CLAUDE.md or ./.claude/CLAUDE.md for a project, or at ~/.claude/CLAUDE.md for personal preferences across all projects.
The quickest way to create one is to run /init inside Claude Code. It generates a starter file from your current project structure, and you refine it over time. There's no required format, but keep it short, specific and organized under headers.
CLAUDE.md file location: the four scopes#
CLAUDE.md files can live in several places, and each has a different scope. This table is in load order, broadest first, so a project instruction lands in context after a user instruction.
| Scope | Location | Shared with |
|---|---|---|
| Managed policy | macOS: /Library/Application Support/ClaudeCode/CLAUDE.mdLinux and WSL: /etc/claude-code/CLAUDE.mdWindows: C:\Program Files\ClaudeCode\CLAUDE.md |
Everyone in the organization |
| User | ~/.claude/CLAUDE.md |
Only you, all projects |
| Project | ./CLAUDE.md or ./.claude/CLAUDE.md |
Your team, via source control |
| Local | ./CLAUDE.local.md |
Only you, current project |
My advice on which to pick:
- Project file for anything a teammate would also need: architecture notes, test commands, conventions. Commit it.
- User file for your own habits, like editor-style preferences or personal tooling shortcuts. This is the "global CLAUDE.md" people ask about.
- Local file for sandbox URLs or preferred test data. Add
CLAUDE.local.mdto.gitignore. - Managed policy only if you're IT or DevOps deploying company standards. Individual settings can't exclude it.
If your repo also has an AGENTS.md, see the section on instruction files below.
How CLAUDE.md files work when Claude loads them#
Claude Code loads CLAUDE.md and CLAUDE.local.md from your current working directory and every directory above it. Launch it in foo/bar/ and you get foo/bar/CLAUDE.md, foo/CLAUDE.md, and any CLAUDE.local.md files next to them.
These files are concatenated, not overridden. Content is ordered from the filesystem root down to your working directory, so instructions closest to where you launched are read last. Within a directory, CLAUDE.local.md is appended after CLAUDE.md.
Files in subdirectories below your working directory behave differently. They don't load at launch. Claude Code loads each one once Claude reads, writes or edits another file in that subdirectory. That makes nested files a good home for rules that only apply to, say, packages/api/.
One detail worth knowing: CLAUDE.md content is delivered as a user message after the system prompt, not as part of the system prompt. Claude tries to follow it, but there's no guarantee of strict compliance, especially for vague or conflicting instructions.
How to write a CLAUDE.md file that Claude follows#
Write instructions concrete enough to verify:
- "Use 2-space indentation" instead of "Format code properly"
- "Run
npm testbefore committing" instead of "Test your changes" - "API handlers live in
src/api/handlers/" instead of "Keep files organized"
Then apply the size rule: target under 200 lines per file. Longer files consume more context and reduce adherence. For each line, ask whether removing it would cause Claude to make mistakes. If not, cut it.
What the docs suggest including and excluding:
| Include | Exclude |
|---|---|
| Bash commands Claude can't guess | Anything Claude can figure out by reading code |
| Code style rules that differ from defaults | Standard language conventions |
| Testing instructions and preferred runners | Detailed API docs (link instead) |
| Branch naming and PR conventions | Information that changes frequently |
| Architectural decisions specific to the project | Long explanations or tutorials |
| Required env vars and environment quirks | File-by-file codebase descriptions |
| Non-obvious gotchas | Self-evident advice like "write clean code" |
If Claude keeps skipping one instruction, you can add emphasis such as "IMPORTANT" to that line alone. Emphasize many lines and none of them stands out.
CLAUDE.md file example for a real project#
Here's a project file I'd start from. The commands and paths are placeholders, so swap in your own.
# Project: storefront-api
## Commands
- Install: `npm ci`
- Run one test file: `npm test -- path/to/file.test.ts`
- Typecheck: `npm run typecheck`
## Code style
- Use 2-space indentation
- Prefer named exports over default exports
## Layout
- API handlers live in `src/api/handlers/`
- Database migrations live in `db/migrations/`; never edit an existing one
## Workflow
- Run the typecheck after a series of code changes
- Prefer running single tests, not the whole suite
- Branch names: `feat/<short-name>` or `fix/<short-name>`
## Gotchas
- Tests need `DATABASE_URL` set to the local test database
A small user-level file in ~/.claude/CLAUDE.md can be even shorter:
# Personal preferences
- Keep explanations brief; show the diff first
- Use 2-space indentation unless the project says otherwise
And a CLAUDE.local.md for one project:
# My local setup
- Sandbox URL: http://localhost:4000
- Use the `test-user-2` fixture when testing checkout
There's also a compaction tip from the best-practices page: you can customize compaction in CLAUDE.md with a line like "When compacting, always preserve the full list of modified files and any test commands".
Imports, comments and organizing a long file#
CLAUDE.md files can import other files using @path/to/import syntax:
# Project: storefront-api
See @README.md for an overview.
# Git workflow
- @docs/git-workflow.md
Imports help you organize a long file, but they don't reduce its context cost, because imported files also load at launch. If part of your guidance only matters for some files, move it into path-scoped rules under .claude/rules/, which load only when Claude works with matching files. For domain knowledge or workflows needed only sometimes, the best-practices page recommends skills instead.
You can also leave notes for human maintainers with block-level HTML comments such as <!-- maintainer notes -->. They're stripped before the content reaches Claude's context, so they cost no tokens. Comments inside code blocks are preserved.
Here's a small script you can run to sanity-check a draft. It strips block comments, counts lines against the 200-line target, and flags a few vague phrases from the docs' own "don't write this" list.
import re
draft = """# Project
<!-- maintainer note: update after the Q3 migration -->
- Format code properly
- Use 2-space indentation
- Test your changes
- Run `npm test` before committing
"""
vague = ["format code properly", "test your changes", "keep files organized", "write clean code"]
clean = re.sub(r"^<!--.*?-->\s*$", "", draft, flags=re.M | re.S)
lines = [l for l in clean.splitlines() if l.strip()]
print(f"non-empty lines after stripping comments: {len(lines)} (target: under 200)")
for l in lines:
if any(v in l.lower() for v in vague):
print("vague, make it concrete:", l.strip())
Claude md file not working: how to debug#
When Claude ignores your file, work through this list from the docs:
- Run
/contextand check the Memory files list. If your file isn't there, Claude can't see it. Use/memoryto open and edit the files. - Remember that subdirectory files don't appear under Memory files, because they load on demand. When one loads, a
Loadedline with its path appears in the terminal. To test a new one, create it from your shell rather than asking Claude to write it, then ask Claude to read a file in that subdirectory. - Confirm the file is in a location that gets loaded for your session.
- Make instructions more specific.
- Look for conflicts across files. If two files disagree, Claude may pick one arbitrarily.
- Check whether your rule competes with built-in guidance. If your CLAUDE.md sets commit or pull request rules, you can turn off the built-in ones with
includeGitInstructionsand set attribution text withattribution.
If something must happen at a fixed point, like before every commit or after each file edit, write a hook instead. Hooks run as shell commands at lifecycle events regardless of what Claude decides. The same logic applies to enforcement generally: settings such as permissions.deny are enforced by the client, while CLAUDE.md shapes behavior but isn't a hard enforcement layer.
To find stale content, run /doctor prompt-audit (needs v2.1.283 or later). It reports outdated instructions, references to files or commands that don't exist, and files that contradict each other, and it changes nothing until you ask.
AGENTS.md, extra directories and monorepos#
If you also keep an AGENTS.md, open /config and set Project instructions. The default, claude-md-or-agents-md, reads your CLAUDE.md files, or your AGENTS.md files when there's no CLAUDE.md or CLAUDE.local.md in your working directory or above. claude-md-and-agents-md reads both, and claude-md reads CLAUDE.md only.
The --add-dir flag gives Claude access to extra directories, but their CLAUDE.md files aren't loaded by default. To load them too:
CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD=1 claude --add-dir ../shared-config
In a monorepo where other teams' ancestor files get picked up, skip them with claudeMdExcludes in .claude/settings.local.json. Patterns are matched against absolute paths:
{
"claudeMdExcludes": [
"**/monorepo/CLAUDE.md",
"/home/user/monorepo/other-team/.claude/rules/**"
]
}
Common mistakes#
- Writing a manual. The over-specified CLAUDE.md is a named failure pattern: important rules get lost in the noise. Prune ruthlessly, and if Claude already does something right without the instruction, delete it.
- Vague wording. "Format code nicely" gives Claude nothing to check.
- Contradictions between layers. User, project, nested and rules files all concatenate. Audit them together.
- Treating it as enforcement. Use hooks or settings for anything that can't be skipped.
- Documenting what the code already shows. File-by-file descriptions and standard conventions just cost context.
- Committing personal notes. Those belong in
CLAUDE.local.md, which should be in.gitignore.
For more on keeping the file lean, the best practices page is worth a read, and the memory docs cover every location and setting above.
Quick reference checklist#
- Create it with
/init, then edit by hand. - Project:
./CLAUDE.mdor./.claude/CLAUDE.md. Personal everywhere:~/.claude/CLAUDE.md. Personal per project:./CLAUDE.local.md. - Stay under 200 lines; use headers and bullets.
- Write verifiable rules with real commands and paths.
- Use
@path/to/importto split files, knowing imports still load at launch. - Use path-scoped rules or skills for guidance that applies only sometimes.
- Check loading with
/context; edit with/memory; audit with/doctor prompt-audit. - Use hooks for anything that must always happen.
- Commit the project file; gitignore the local one.
Quick answers
Where is the CLAUDE.md file located?
For a project, use ./CLAUDE.md or ./.claude/CLAUDE.md. For personal preferences across all projects, use ~/.claude/CLAUDE.md, and for personal notes on one project use ./CLAUDE.local.md.
How do I generate a CLAUDE.md file?
Run /init in Claude Code. It creates a starter file based on your current project structure, which you then refine by hand.
How do I open or update my CLAUDE.md file?
Type /memory in a session to open and edit the files Claude loads. You can also edit the markdown file directly in any editor. Run /context afterward to confirm it loaded.
Why is my CLAUDE.md file not working?
Check /context to see whether the file is listed under Memory files, and look for vague or conflicting instructions. CLAUDE.md is context rather than enforced configuration, so use a hook for anything that must always run.
How long should a CLAUDE.md file be?
Target under 200 lines per file. Longer files consume more context and reduce adherence, so move part-of-codebase guidance into path-scoped rules.
Next note