Course · Lesson 8 of 30
CLAUDE.md
Beginner · 6 min read
CLAUDE.md is a markdown file in your repository that Claude Code
reads automatically at the start of every session. It's how a codebase
briefs its agents: conventions, commands, architecture, boundaries —
written once, supplied every time, versioned with the code it
describes. Lesson 4 introduced knowledge-that-persists; this is that
idea living in git, and it is the highest-leverage
file-per-hour-invested in all of agentic work. This lesson: what goes
in, what a great one looks like, the enforcement caveat that keeps you
honest, and the maintenance practice that keeps it true.
What goes in: onboarding notes for a brilliant amnesiac
The framing that produces good files: you're writing for a very strong contractor who arrives every morning with total amnesia. What do they need every day, that they can't cheaply figure out by reading the code?
The commands, exactly. Build, test, lint, run-one-test — as literal invocations:
## Commands
- npm run dev # local server on :3000
- npm test # full suite (~40s)
- npx vitest run path/to/file.test.ts # one file
- npm run lint # eslint; must pass before commit
Without these, every session burns tokens rediscovering your test runner — or guesses, runs the wrong thing, and trusts the wrong result.
The map, in one screen. Where things live, what the major directories mean, which parts are generated versus authored. Not the architecture doc — the two-minute whiteboard orientation a senior dev gives a newcomer. Five to fifteen lines.
The rules with teeth. Conventions your linter doesn't enforce: "errors are returned, never thrown across module boundaries," "server components by default," "money is integer cents." House style the model can't infer from any single file it happens to read.
The boundaries — highest value per token. What must not be touched: generated directories, vendored code, migration history, files owned by another process. As in lesson 4, negative knowledge is the premium content: it's exactly what reading the code cannot teach, and violating it is what turns a helpful session into a cleanup.
The definition of done. "Run the linter before committing." "Never commit with failing tests." "Update the changelog for user-facing changes." The session-ending checklist, standing.
And the size discipline that makes all of it work: a few hundred
lines, maximum. This file rides the desk every single turn
(lesson 2) — a 2,000-line CLAUDE.md is a tax on every request and a
dilution of its own important rules, which now drown in trivia exactly
where attention is weakest. When a section outgrows a screen, move the
detail to a doc and leave a pointer ("PDF pipeline details:
docs/pdf.md") — pointers are nearly free, and the agent follows them
when relevant. That's lesson 20's resident-versus-on-demand split,
practiced in miniature.
The honest caveat: advice, not enforcement
Every line in CLAUDE.md is an instruction to a model — strongly weighted, usually followed, never guaranteed. Under context pressure, in a long session, or against a cleverly conflicting request, any instruction can lose. This has a sharp, practical edge, and it's worth a decision pass over your own file:
- Rules that are preferences ("prefer early returns") belong here, and occasional misses cost nothing.
- Rules that are invariants ("never edit
migrations/", "never print credentials") should be written here and enforced by machinery — a hook that blocks the action (lesson 15), a CI check that rejects the commit (lesson 28). The file states intent so the model plans around it; the mechanism makes it true when planning fails.
The discipline: every time you write "never" or "always" into this file, ask what would make this true if the model ignored it? If the answer is "nothing," you've written a hope. Some rules deserve only a hope — but know which of your rules are hopes, because the difference is the whole subject of the harness lessons (15, 16, 28).
Maintenance: the file is a living artifact
Stale guidance is worse than none — the model follows the file over the code, confidently, because you told it the file is authoritative (lesson 4's trap, in the file easiest to forget about). Three habits keep it true:
- Update it in the same PR that invalidates it. Renamed the test command? Moved a directory? Changed a convention? The CLAUDE.md edit belongs in that diff — same commit, same review. A file updated "later" is a file updated never.
- Feed it your corrections. The second time you type the same
correction to an agent, that sentence is the file's missing
content, verbatim. Claude Code's
#shortcut appends a memory mid-session for exactly this — use it the moment you notice, not at some future cleanup that won't happen. Your repeated corrections are a to-do list the file is writing for you. - Prune on contact. When a session goes sideways because of the file — stale advice, a rule that backfired, a section the model keeps misreading — fix it then, while the failure is concrete. Review its diff history occasionally: it's the changelog of how your team works with machines, and it should read like one.
Layers and scope
Claude Code composes several levels: ~/.claude/CLAUDE.md for your
personal preferences across all projects (your prose style, your
pet peeves — things that would be rude to impose on teammates), the
repo root for the project (the team's file: keep personal taste out),
and subdirectory CLAUDE.md files for area-specific guidance in large
codebases — the closest file adds detail for work in that area. The
repo-root file is the one CI agents and teammates inherit, which makes
it, quietly, one of the most consequential files in the repository:
it shapes as much output as your linter config, and deserves the same
seriousness of review.
A personal teaching project, in development. The registry it builds is a teaching artifact and is not an assurance opinion about any issuer. Not affiliated with or endorsed by any employer, or by any vendor whose tools it describes. Where a unit depends on a specific flag or path, it names the version it was verified against. All units.