← All packs

Writing a CLAUDE.md that actually changes behavior

Most CLAUDE.md files fail the same way: they read fine, and the agent still doesn't do the thing. That's usually not a following-instructions problem — it's an authoring problem. A file full of generic engineering advice ("write clean code," "add tests," "be careful with security") gives the model nothing it doesn't already default to, so it has no measurable effect. The fix is writing instructions that only make sense in this repo, stated so specifically that ignoring them would be obviously wrong.

1. Cut anything a competent default would already do

"Write readable code," "handle errors properly," "don't break existing tests" — these describe baseline competence, not this project. Instructions like this add length without adding constraint: the model was already going to try. Every line should fail a simple test — would a generically good engineer, with zero context on this repo, do the opposite by default? If not, the line is decoration.

Check: for each instruction, name the specific alternative behavior it rules out. If you can't name one, cut it.

2. Write the constraints that aren't derivable from reading the code

The highest-value lines are the ones no amount of code-reading would surface: "never call the billing API from a background job — refunds must be synchronous so support can see the result immediately," or "this repo intentionally avoids an ORM — raw SQL is reviewed, not accidental." These are decisions with a reason, and the reason is what makes them durable — without it, a future edit (by a person or a model) will look like an oversight to fix rather than a rule to keep.

Check: does the instruction include enough of the why that someone could correctly judge an edge case it doesn't explicitly cover?

3. Separate "always true" from "true for this task"

CLAUDE.md is loaded on every single turn, in every session, for the life of the project — anything task-specific in it becomes stale advice the moment the task changes, and stale advice competes with current advice for attention. A note about "the migration we're mid-way through" or "the bug we're chasing this week" belongs in a plan, a task list, or a commit message, not in a file the model reads forever.

Check: would this line still be true and useful six months from now, on a completely different task in the same repo? If not, it doesn't belong here.

4. Give commands, not descriptions, for anything runnable

"Run the test suite before committing" forces a guess at how. "Run make test-unit (the full make test also spins up docker and takes 8 minutes — only run it before a PR, not every edit)" removes the guess and explains the cost tradeoff that justifies the shortcut. The same applies to linting, formatting, building, and deploying: paste the actual command, plus the one piece of context that explains why it's not simply "run everything, always."

Check: could someone with no memory of this conversation run the exact command from the text alone, no inference required?

5. Don't restate what a skill already encodes

If a workflow is already codified as a skill — a checklist for safe migrations, a procedure for diagnosing flaky tests, a fixed sequence for root-cause tracing — repeating a summary of it in CLAUDE.md creates two sources of truth that will eventually disagree. Reference the skill by name and let it own the procedure; keep CLAUDE.md for the project-specific facts the skill can't know on its own (which database, which deploy target, which team's on-call convention).

Check: if a paragraph describes a repeatable multi-step procedure rather than a fact about this codebase, it's a candidate to become a skill instead of a paragraph.

6. Prune on a schedule, not just on complaint

CLAUDE.md files grow by accretion — one line added per incident, never removed — and a long file trains both humans and models to skim rather than read carefully, which defeats the purpose of the highest-priority lines along with the lowest. Periodically re-read the whole file and ask, per line, whether it's still earning its place per the checks above.

Check: when a line stops matching checks 1-5, delete it in the same change that prompted the re-read — don't leave it for later.

Output: fewer lines, each one load-bearing

A good CLAUDE.md is short enough to read in full every time and dense enough that every line changes what happens next. If removing a line wouldn't change any future turn's behavior, it shouldn't be there — that space is better spent on the one constraint that's actually specific to this repo and actually easy to get wrong.

None of this requires an LLM to apply — it's a set of checks against a text file you already have. Where a model helps is later, once the file is right: turning its project-specific facts into consistent behavior across debugging and release work, which is what the skills in the Claude Code Power Pack and Claude Code Debug Pack are built to do.

A CLAUDE.md sets context once for every task. For the separate problem of writing the instructions for one specific task well, see writing task descriptions an agent can actually execute.

Writing the content is only half the job — once a CLAUDE.md ships and gets edited again, it needs the same diff/rollback discipline as any other deployable; see versioning and rolling back agent system prompts.