Free guide · Claude Code
CLAUDE.md that actually works
Most CLAUDE.md files fail the same way: they grow. What starts as six useful lines becomes three hundred, and then the instructions that mattered stop being followed. This page covers where the files live, how they combine, how long yours should actually be, and how to check what is loaded rather than guessing.
The short version
- Target under 200 lines. Anthropic’s own docs say bloated files cause Claude to ignore your actual instructions — how long it should be.
- Memory files are concatenated, not overridden. A project file does not replace your user file — the hierarchy.
- Run
/contextand look under Memory files to see what actually loaded — verifying. - It is context, not enforcement. If something must never happen, use a hook instead — the limit.
New to Claude Code? Skip the box — the explanation starts below.
What CLAUDE.md is for
Every new conversation starts from nothing. Claude does not remember that your build command is unusual, that one package is generated, or that you always want single tests rather than the whole suite. Without somewhere to write that down, you retype it forever.
CLAUDE.md is that place. It is an ordinary markdown file that Claude Code reads at the start of every conversation. There is no required format — headings and bullet points are enough.
A small, genuinely useful one looks like this:
# Commands
- Build: `pnpm build` (never `npm run build` — the lockfile is pnpm)
- Test a single file: `pnpm test path/to/file.test.ts`
# Style
- ES modules only. No `require`.
- Errors return a problem+json body, never a bare string.
# Gotchas
- `packages/legacy-api` is generated. Do not edit it by hand.
- Integration tests need `DATABASE_URL` set or they fail silently.Notice what those lines have in common: every one is something Claude could not work out by reading the code. That is the entire test for whether a line belongs.
Where the files live
Claude Code reads memory from several scopes, loading them broadest first:
| Scope | Path |
|---|---|
| Managed policy | /Library/Application Support/ClaudeCode/CLAUDE.md (macOS), /etc/claude-code/CLAUDE.md (Linux and WSL), C:\Program Files\ClaudeCode\CLAUDE.md (Windows) |
| User | ~/.claude/CLAUDE.md — applies to all your projects |
| Project | ./CLAUDE.md or ./.claude/CLAUDE.md — committed, shared with the team |
| Local | ./CLAUDE.local.md — gitignored, just for you |
Within a directory tree they load from the filesystem root down toward your working directory, and CLAUDE.local.md loads after CLAUDE.md in the same folder.
The critical word is concatenated, not overridden. A project instruction does not replace a user instruction — it simply appears later in context. If your personal file says one thing and the project file says the opposite, both are present, and the docs are blunt about the outcome: if two rules contradict each other, Claude may pick one arbitrarily. Contradictions are not resolved for you.
What actually belongs in it
Anthropic publishes guidance on this, and it is unusually concrete. Worth including:
- Commands Claude could not guess — your real build and test invocations.
- Code style rules that differ from the language’s defaults.
- Testing instructions and which runner you prefer.
- Repository etiquette: branch naming, PR conventions.
- Architectural decisions specific to this project.
- Environment quirks, such as required environment variables.
- Non-obvious gotchas — the things that bite newcomers.
Worth leaving out:
- Anything Claude can determine by reading the code.
- Standard language conventions it already knows.
- Detailed API documentation — link to it instead.
- Information that changes frequently.
- File-by-file descriptions of your codebase.
- Self-evident advice. “Write clean code” costs you context and buys nothing.
There is also a good documented trigger for when to add a line: Claude made the same mistake twice, a review caught something it should have known, you typed the same correction you typed last session, or a new teammate would have needed the same context. If none of those happened, you are probably writing documentation rather than memory.
How long it should be
The documented target is under 200 lines per file. Claude Code loads a CLAUDE.md of up to 4 MiB in full and skips a larger one entirely — so an enormous file does not degrade gracefully, it simply stops being read.
Long before that limit, though, you hit the practical one. The documentation names the over-specified CLAUDE.md as a failure pattern outright: if the file is too long, important rules get lost in the noise and Claude ignores half of it. The recommended discipline is a per-line question — would removing this line cause a mistake? If not, cut it.
This is the opposite of how most people treat the file. The instinct is to add a line every time something goes wrong, and never remove one. That instinct produces a file that is simultaneously very long and increasingly ignored — which then reads as the tool being unreliable rather than the file being bloated.
Splitting a file with imports
@path/to/import pulls another file in from anywhere in your CLAUDE.md. Relative paths resolve against the importing file rather than your working directory, and imports recurse up to four hops deep.
One useful subtlety: a path wrapped in backticks is treated as literal text and not imported. That is how you mention @README in prose without loading it.
Imports do not reduce your context cost — an imported file is still loaded. They help you organise, not economise. If your goal is a smaller context, the answer is deleting lines or moving them into a skill, not moving them into another file.
Checking what is actually loaded
Two different commands, often confused:
/contextvisualises current context usage. Check the list under Memory files to confirm which files actually loaded. This is the one that answers “is my file being read?”/memorylists your memory file locations across user and project scopes — including ones that do not exist yet — lets you toggle auto memory, and opens any file for editing. Selecting a file that does not exist creates it first.
Use /context to diagnose and /memory to edit. Reading your own file in an editor tells you what you meant to write, which is never the question you actually have.
Monorepos and large repositories
Memory files load from your working directory and every ancestor directory. Files in subdirectories load on demand — when Claude reads something in that folder — rather than all at once up front, which keeps a large repo from flooding context immediately.
When that is still too much, claudeMdExcludes in your settings skips specific files by path or glob:
{
"claudeMdExcludes": [
"**/monorepo/CLAUDE.md",
"/home/user/monorepo/other-team/.claude/rules/**"
]
}For larger projects there is also a .claude/rules/ directory holding topic-scoped files, which can be limited to certain paths with paths: frontmatter — closer in spirit to how Cursor scopes its own rules.
Worth knowing for long sessions: a project-root CLAUDE.md survives compaction. After /compact, Claude re-reads it from disk and re-injects it. Nested files and path-scoped rules reload as it reads files they apply to.
When it should be a skill instead
This is the distinction that keeps a file short. CLAUDE.md is loaded every single session, so it should only contain what applies broadly. Domain knowledge or a workflow that is relevant occasionally belongs in a skill, which loads on demand without bloating every conversation.
A good test: if a line only matters when you happen to be working on one subsystem, it is paying rent in every unrelated conversation you will have this month.
The limit worth understanding
CLAUDE.md shapes behaviour. It does not enforce it. The documentation is explicit that memory is treated as context, not as enforced configuration — and mechanically, its content is delivered as a user message after the system prompt rather than as part of the system prompt itself.
So “never push to main” in CLAUDE.md is a strong instruction, not a guarantee. If an action must be impossible rather than merely discouraged, the documented answer is a PreToolUse hook, which can block it regardless of what the model decides. Writing rules in ever-firmer capital letters is not the escalation path; hooks are.
A note on the # shortcut
You will find plenty of posts telling you to type # followed by a note to save it straight into CLAUDE.md. That was a real, shipped feature — but it does not appear anywhere in the current official documentation, and there is an open bug report describing it no longer saving, with the text being treated as an ordinary prompt instead.
Treat it as uncertain rather than as a workflow to rely on. Use /memory to open and edit the file directly, which is documented and works.
If you also use Cursor
Then one more fact matters a great deal: Cursor reads CLAUDE.md too, and applies it to every conversation. Your memory file is instructing both tools, which is either very convenient or very confusing depending on whether you knew. That asymmetry — and the fact that Claude Code does not read Cursor’s rules in return — is unpacked in CLAUDE.md vs .cursor/rules.
What to read next
Brand new to the CLI? Start with Getting started with Claude Code. For dividing responsibilities between the two tools, read Using Claude with Cursor. If you are setting Cursor up from scratch, start with Getting started with Cursor.