Write a CLAUDE.md that actually helps
Write a short CLAUDE.md with the commands, traps and decisions Claude cannot find in your code, and move the rest out.
CLAUDE.md is the file Claude reads at the start of every session in your project. Most people either skip it or let it grow into a wiki that Claude half ignores. This guide is for anyone who has run /init once and wants a file that changes Claude's behaviour for the better. At the end you will have a short CLAUDE.md, a place for personal notes, and a plan for everything that does not belong in it.
What you will have at the end
- A project CLAUDE.md under 200 lines that holds only what Claude cannot find by reading the code
- A
CLAUDE.local.mdfor your personal preferences, kept out of git - Path-scoped rules for instructions that matter in one part of the codebase
- A way to confirm what Claude actually loaded
Before you start
- Claude Code installed and working in a project. See Start here if not.
- Optional: a first draft from
/init. You will mostly cut it down.
Step 1: Start from a draft
In your project, run:
/initClaude analyses the codebase and writes a starting file with build commands, test instructions and conventions it finds. If a CLAUDE.md already exists, /init suggests improvements instead of overwriting it (memory docs).
The file can live at ./CLAUDE.md or ./.claude/CLAUDE.md. Both are shared with your team through git, so write project rules here, not personal taste.
Step 2: Cut what Claude can find on its own
Open the draft and go through it line by line. For each line, ask the two questions from the best practices page: could Claude find this by reading the code, and would it actually go and look? If both answers are yes, delete the line.
This removes most of a typical draft. Directory trees, dependency lists and architecture overviews go first. The same page lists "Describe your architecture and file layout in CLAUDE.md" as old advice you can stop following, because Claude reads the repo itself.
What survives is the short list the docs recommend keeping (best practices):
- How to confirm work: the exact test, typecheck and lint commands, and how to run a single test file
- Places where the code misleads: an old pattern new code must not copy, or a folder that looks dead but is not
- Decisions that are not in the repo: which error helper the team picked, how deploys work
- Anything you have had to correct twice
Step 3: Write it short and concrete
Here is the shape to aim for. It is adapted from the example on the best practices page:
# Commands
- Install: pnpm install
- Run one test file: pnpm vitest run path/to/file.test.ts
- Typecheck: pnpm tsc --noEmit
# Conventions
- Use the error helpers in src/lib/errors.ts, never throw raw strings
- src/legacy/ is still live but don't copy its patterns into new code
# Gotchas
- Integration tests need DATABASE_URL set, see .env.exampleThree habits make each line work harder, all from the memory docs:
- Be concrete enough to check. "Run
npm testbefore committing" beats "test your changes". - Group lines under headings. Claude follows organised sections more reliably than dense paragraphs.
- Remove contradictions. If two lines disagree, Claude may pick either one.
Skip the capital letters. The best practices page says that adding IMPORTANT probably will not fix a line Claude keeps ignoring. Either the file is too long and the line gets lost, or the rule cannot have exceptions and belongs in a hook.
Step 4: Apply the 200-line rule
The docs say to target under 200 lines per CLAUDE.md file (memory docs). Longer files use more context and reduce adherence, because every line competes for attention on every task. Claude Code warns you at startup and in /status when an instruction file is over the recommended length (troubleshooting).
Check your count:
wc -l CLAUDE.mdIf you are over, move things out instead of squeezing them in. The next step shows where.
Step 5: Move the rest to the right place
Not everything you want Claude to know belongs in the file that loads every session.
Imports, for organisation only. You can pull another file in with @path syntax, for example See @README for project overview. Relative paths resolve from the file that contains the import, and imports can nest up to four hops. Imports keep things tidy, but they do not save context: an imported file loads together with the CLAUDE.md that imports it (imports). To mention a path without importing it, wrap it in backticks.
Path-scoped rules, to save context. Put a markdown file in .claude/rules/ with a paths list in its frontmatter, and it loads only when Claude works on matching files (rules):
---
paths:
- "src/api/**/*.ts"
---
# API Development Rules
- All API endpoints must include input validation
- Use the standard error response formatSkills, for procedures. A multi-step release or migration checklist belongs in a skill, not CLAUDE.md. The memory docs say entries that are procedures or only matter for one area should move to a skill or a path-scoped rule. A skill's full body only loads when it is used. See Your first skill in 10 minutes.
Hooks, for rules that must always hold. CLAUDE.md is context, not enforced configuration. If something must happen before every commit or after every edit, make it a hook (troubleshooting).
CLAUDE.local.md, for you. Personal preferences for one project go in CLAUDE.local.md at the project root. It loads alongside CLAUDE.md. Add it to .gitignore so it stays out of commits (memory docs). Preferences for all your projects go in ~/.claude/CLAUDE.md.
Step 6: Keep it current
Treat the file as a list of things you would otherwise re-explain. The memory docs suggest adding a line when Claude makes the same mistake twice, when code review catches something Claude should have known, or when you type the same correction you typed last session.
Two built-in checks help you prune. /doctor proposes trims for content Claude can work out from the codebase. /doctor prompt-audit looks for instructions written for older models, references to files that no longer exist, and files that contradict each other. Nothing changes until you ask Claude to apply the edits (audit).
A small trick: block-level HTML comments such as <!-- note for humans --> are stripped before the file reaches Claude, so you can leave maintainer notes at no context cost (memory docs).
Check it worked
- In a session, run
/context alland look under Memory files. Your CLAUDE.md and any CLAUDE.local.md should be listed (memory docs). - Ask Claude a question that your file answers, such as "how do I run one test file here?". It should give your exact command without searching.
wc -l CLAUDE.mdprints a number under 200.
Common problems
Claude ignores a line. Make it more specific, look for a conflicting line in another CLAUDE.md or rules file, and confirm the file loaded with /context all. If it must hold every time, turn it into a hook (troubleshooting).
A subfolder CLAUDE.md does not show under Memory files. That is expected. Files in subdirectories load on demand, once Claude reads or edits a file in that folder (how files load).
An instruction vanished after /compact. The project-root CLAUDE.md is re-read from disk after compaction. Instructions you only gave in chat are not, so add them to the file if they should persist (after compact).
Your repo uses AGENTS.md and Claude seems unaware of it. By default Claude reads AGENTS.md only when there is no CLAUDE.md or CLAUDE.local.md on the project path. Add a CLAUDE.md that imports it instead (AGENTS.md).
Next
- Explore, plan, code, verify: how to use your test command from CLAUDE.md as the check Claude runs.
- Build a team skill library that stays sharp: the paid guide on moving procedures out of CLAUDE.md for a whole team.
Sources
- https://code.claude.com/docs/en/memory
- https://code.claude.com/docs/en/best-practices
- https://code.claude.com/docs/en/commands
Last checked: 2026-11-06