What is CLAUDE.md?
CLAUDE.md is the memory file Claude Code reads automatically at the start of every session. It’s plain Markdown — no schema, no frontmatter, no registration step. Whatever you write in it is pulled into the model’s context before it touches your code, which makes it the single highest-leverage file in the repo: build commands, naming conventions, the one directory it must never touch — say it once in CLAUDE.md and you stop repeating it in every prompt.
Think of it as an onboarding doc with a different reader. A README explains the project to a human who will poke around and infer the rest; CLAUDE.md gives instructions to an agent that follows exactly what it’s told and guesses at everything else. The best ones read less like documentation and more like a checklist from a slightly paranoid tech lead.
Where CLAUDE.md lives — and which one wins
Claude Code looks for memory files in several places and loads every one that applies, broadest first:
| Location | Scope | Typical contents |
|---|---|---|
| Managed policy (OS-specific system path) | Every user in the org — IT-deployed, can’t be overridden | Org-wide security and compliance rules |
~/.claude/CLAUDE.md |
You, in every project | Personal preferences: tone, editor habits, “always use spaces” |
<repo>/CLAUDE.md (or .claude/CLAUDE.md) |
The project — committed, shared with the whole team | Commands, architecture, conventions, project rules |
<subdir>/CLAUDE.md |
One subtree; loaded on demand when Claude works there | Package-specific rules inside a monorepo |
Two details worth knowing. First, Claude Code also reads CLAUDE.md files in
parent directories of wherever you launch it — so in a monorepo, starting a
session inside packages/api/ still picks up the root file. Second, precedence
is not a hard override: all applicable files are concatenated into context, broadest first, so
the more specific file lands last and gets a little more of the model’s attention. But this
is guidance, not enforced configuration — if your user file and project file give
contradictory orders, Claude may just pick one arbitrarily. Don’t rely on it; keep each level
about what only that level knows. (When a rule must hold, use a hook, not prose.)
There’s also CLAUDE.local.md — a project-root file for your own
preferences (sandbox URLs, test data) that loads alongside CLAUDE.md. Add it to
.gitignore so it stays off the repo. One catch: because it’s gitignored, it only
exists in the worktree where you made it — if you use multiple git worktrees, import a file
from your home directory instead (covered next).
Imports: the @path syntax
A CLAUDE.md can pull in other files with an @ reference on its own
line:
See @README.md for the project overview and @docs/architecture.md
for how the services fit together.
# Personal, per-machine notes (not committed):
@~/.claude/my-project-notes.md
Imports resolve recursively (up to four hops deep), and paths can be relative or absolute
(a relative path resolves against the file that contains the import, not your working
directory). References inside code spans and fenced code blocks are left alone, so you can
safely write @decorator examples without triggering an import. This keeps the
committed CLAUDE.md organized and lets each developer bolt on private notes without a merge
conflict. One thing it does not do is save context: imported files are expanded into
the prompt at launch, same as if you’d pasted them inline — to actually cut tokens, plain-link
the doc (no @) or use path-scoped rules that load only when relevant.
What to put in it (and what to leave out)
Everything in CLAUDE.md is paid for in context tokens, every session, whether or not it’s relevant to the task at hand. That one constraint drives all the good advice:
- Commands, with exact flags. The single test file invocation
(
npx jest path/to/test.ts) saves more time than anything else you’ll write — agents love running the whole suite when they only need one file. - Rules the code can’t teach. “Never commit unless asked.” “Don’t
touch
.env.” “Ask before adding a dependency.” An agent can infer your formatting from the code; it cannot infer your boundaries. - The surprises. The build step that must run twice, the directory that’s generated, the API that looks deprecated but isn’t. Anything a new teammate would trip over in week one.
- Not: things the tools already enforce. If Prettier and the linter run on save, three paragraphs about formatting is pure token spend. Point the linter at the problem instead — or a hook, which is deterministic where prose is a polite request.
- Not: a mission statement. The agent doesn’t need to know the product vision to fix the failing test.
Treat it like a prompt you’re iterating on, because that’s what it is. When Claude
keeps making the same mistake, that’s a missing line in CLAUDE.md. A shortcut worth knowing:
/init generates a starter file by scanning your repo (and if an
AGENTS.md or .cursorrules already exists, it folds those in). You
can also just tell Claude “add this to CLAUDE.md” mid-session and it edits the file for you.
CLAUDE.md vs AGENTS.md
AGENTS.md is the vendor-neutral take on the same idea — one Markdown file of agent instructions at the repo root, read by a growing list of coding agents (OpenAI Codex, Cursor, Gemini CLI, and others). Same content, same philosophy, different filename.
Claude Code reads CLAUDE.md, not AGENTS.md. If your team standardizes on AGENTS.md, don’t maintain two copies that will drift apart — keep one source of truth and have CLAUDE.md import it. A one-line CLAUDE.md is all you need, and you can append Claude-specific rules below the import:
@AGENTS.md
## Claude Code
Use plan mode for changes under `src/billing/`.
A symlink also works if you don’t need any Claude-specific additions — but on Windows it requires Administrator privileges or Developer Mode, so the import above is the more portable choice:
ln -s AGENTS.md CLAUDE.md
The generator above writes either flavor; the content is identical because the content is the point. One caveat if you go the AGENTS.md route: keep it tool-agnostic. A rule like “use the Task tool for searches” means nothing to half its readers — put tool-specific instructions in the tool-specific file.
Two real CLAUDE.md examples
A good CLAUDE.md is shorter than you expect. Here’s a sensible one for a TypeScript web app:
# acme-storefront
## Project
- Type: Web app (Next.js 15, App Router)
- Stack: TypeScript, strict mode
## Commands
- Dev server: `npm run dev`
- Test: `npm test` — single file: `npx jest src/cart/cart.test.ts`
- Lint + typecheck: `npm run check` (run before calling any task done)
## Conventions
- Named exports only; no default exports
- Server components by default — add `"use client"` only when interaction demands it
- All money is integer cents; never floats
## Rules
- Never commit or push unless explicitly asked.
- Never read or modify `.env*` files.
- Ask before adding any new dependency.
- `src/generated/` is machine-written — never edit it by hand.
And a Python library, where the whole job is guarding the public API:
# chronoparse
Python library for fuzzy date parsing. Public API surface is `chronoparse/__init__.py`
only — everything else is internal and may change freely.
## Commands
- Test: `pytest` — single file: `pytest tests/test_ranges.py -x`
- Lint: `ruff check . && ruff format --check .`
- Type check: `mypy chronoparse/`
## Rules
- Any change to a public function signature needs a CHANGELOG entry.
- New public functions need docstrings with a doctest example.
- Match existing code style; don't reformat code unrelated to your change.
- Run the full test suite after changes; a task isn't done until it passes.
FAQ
Should CLAUDE.md be committed to git?
The project-root one, yes — it’s team infrastructure, and everyone’s agent benefits
from the same rules. Personal preferences belong in ~/.claude/CLAUDE.md,
and per-machine, per-project notes in an imported file (see
imports) so they never hit the repo.
How long should a CLAUDE.md be?
Shorter than you think. It’s loaded into context every single session, so every line
is a recurring cost — Anthropic suggests targeting under 200 lines, and for most projects
well under that. If it’s ballooning, move detail into separate docs and plain-link them, or
use .claude/rules/ with path scoping so instructions load only when Claude
touches the matching files. (An @-import tidies the file but still loads at
launch, so it won’t shrink the context bill.)
CLAUDE.md or settings.json — which one do I want?
CLAUDE.md instructs the model: prose the agent reads and follows, which
makes it flexible but probabilistic. settings.json configures the
harness: permissions, hooks, and environment enforced deterministically by
Claude Code itself. “Prefer small commits” is CLAUDE.md; “deny all Bash access to
rm” is settings.json. When a rule absolutely must
hold, prefer the harness.
Does Claude Code read AGENTS.md directly?
No. Claude Code reads CLAUDE.md, not AGENTS.md. If your repo
already uses AGENTS.md, don’t duplicate it — put a one-line @AGENTS.md import
at the top of CLAUDE.md so both tools read the same instructions (and add any
Claude-specific rules below it). The symlink above also works, but
the import is the more portable choice — a symlink needs Administrator or Developer Mode on
Windows.
My agent keeps ignoring a rule in CLAUDE.md. Why?
Usually one of three things: the rule conflicts with another memory file (see which one wins), it’s buried in a wall of prose, or it’s phrased as background rather than instruction. Make it a short imperative bullet under a clear heading. And if it’s a hard constraint, stop asking nicely — enforce it with a hook.