CLAUDE.md that actually steers: lessons from real repos
I have read a lot of CLAUDE.md files by now: mine, my team's, and the ones strangers check into public repos. The bad ones all look the same: a corporate style guide stapled to a wishlist. The good ones look like the note a senior engineer leaves you on your first day — short, specific, slightly paranoid.
The difference matters more here than in ordinary docs, because CLAUDE.md is not documentation. It is loaded at the start of every session and rides along on every turn that follows. That makes it the most expensive text in your repo, and the strongest steering lever you have.
What earns a line
Three categories pay rent, in my experience.
- Commands. The exact build, lint, and test incantations (above all, how to run a single test). Nothing wastes a session like an agent rediscovering your test runner by trial and error.
- Conventions that defy defaults. Only where you differ from what the model would guess: errors as return values in a codebase that never throws, a house import order, the internal wrapper you use instead of the standard client. The model already knows idiomatic; it needs to know where you are deliberately not.
- Landmines. Generated directories, the config that looks editable but is overwritten by CI, the module nobody touches without a design review. Tribal knowledge is tribal precisely because it is surprising. Write it down.
The test I apply to a candidate line: would a competent new hire need this in week one, and would they fail to guess it? Two yeses and it goes in. Anything less and it does not.
What does not earn a line
Whole style guides are the classic mistake. If a linter can enforce a rule, let the linter enforce it: a hook can run it after every edit, deterministically, which beats prose every time. Aspirational process ("write clean, maintainable code") is worse than useless: it spends attention and changes nothing. Same for anything discoverable in one directory listing, and for framework docs the model already knows cold.
Every line in CLAUDE.md is a tax on every turn that follows, so each one has to earn more than it costs.
The tax compounds. A 400-line file does not give you 400 rules. It gives you 400 candidates competing for the model's attention, and models follow a ten-item list far more reliably than a hundred-item one. Staleness is worse: the first time the agent hits a documented command that no longer works, every neighboring line loses credibility with it.
Use the hierarchy deliberately
Claude Code layers memory. ~/.claude/CLAUDE.md carries your personal defaults into every project; the repo's CLAUDE.md is the team contract, checked in and reviewed; local uncommitted variants hold private per-repo notes; nested files in subdirectories load when work moves into their area. The layering is the point: my user file holds my habits, the project file holds only what the team actually agreed on, and neither repeats the other. An @path import can split an overgrown file, though needing imports is usually a sign you need deletions instead.
None of this is Claude-specific. The same economics govern AGENTS.md on the Codex side and GEMINI.md for Gemini CLI; the filename changes, the tax does not. The general craft of these files has its own piece.
Treat the file like code. Changes go through PRs; lines that stop being true get deleted the day they die; the only metric is whether the agent stopped making the specific mistake a line was written to prevent. Mine sit around a screenful, and every time one crept meaningfully past that, trimming made the agent sharper, not dumber. When in doubt, cut: the model guesses defaults well. It is only your exceptions it cannot guess.