From prompting to agents · 23 August 2026 · 4 min read

Write a CLAUDE.md the agent actually uses

Put in what code can't say — commands, done criteria, and never-do rules. Leave out anything the agent can read for itself.

CAN READ FROM CODE file layout dependencies function signatures types, imports existing patterns what a function does CANNOT READ FROM CODE exact test/build commands definition of done, stop criteria never-do rules (no force-push, etc.) why a weird pattern exists who to ask, what's out of scope team conventions code can't show CLAUDE.md
CLAUDE.md fills only what the code itself can't tell the agent.

Most CLAUDE.md files fail the same way: they re-describe the codebase. A file that lists your directory structure and dependency versions is dead weight, because the agent can read package.json and run find itself. A CLAUDE.md earns its keep by holding the handful of things no amount of code-reading will reveal.

What actually belongs in the file

Anthropic's own guidance for Claude Code frames this as "the place you write down what you'd otherwise re-explain," and lists concrete triggers for adding a line: "Claude makes the same mistake a second time," "a code review catches something Claude should have known about this codebase," "you type the same correction... that you typed last session" (Claude Code memory docs). That's a good filter: if you've said it more than once, it goes in the file.

In practice that means:

  • Exact commands. Not "run the tests" but pytest tests/ -x or make test. The same docs recommend concrete phrasing: "Run npm test before committing" over "Test your changes."
  • Definition of done. What "finished" means for this repo — lint clean, types clean, no skipped tests.
  • Never-do rules. git push --force to main, editing generated files, touching /prod config. Things a human hire would be told on day one and that a linter can't always catch.
  • The "why" behind odd code. A workaround for a vendor bug, a deliberately duplicated function — context that isn't in the diff.

What to leave out

Anything a Read or Grep call would surface: directory layout, which framework you use, what a function's signature is. The same source is direct about this: keep CLAUDE.md "to facts Claude should hold in every session," and move anything that's a multi-step procedure or only relevant to part of the codebase into a skill or a path-scoped rule instead. Padding the file with restated code doesn't just waste space — it's loaded into context on every single session, so bloat has a recurring cost, not a one-time one.

A real-looking example

## Commands
- Test: `make test` (fast subset: `pytest -m "not slow"`)
- Lint: `make lint` — must pass before any commit

## Definition of done
- Tests green, lint clean, no new mypy errors
- Root cause fixed, not the failing test deleted or skipped

## Never do
- Never edit files under `/migrations/applied/`
- Never commit `.env` or credentials

## Conventions the code doesn't show
- We use soft deletes everywhere; there is no hard DELETE in this repo
- Retry logic lives in `retry.py`, not inline — copy that pattern

In the figure, the left column is what the agent derives from reading; the right column is what only a written file supplies, and CLAUDE.md exists to feed that column specifically.

Try it today

  1. Open your last three corrections to an agent's code — comments you left in review, or things you fixed by hand afterward.
  2. For each one, ask: could the agent have read this from the code? If yes, skip it.
  3. For the ones it couldn't have known, write one line each into CLAUDE.md in imperative form ("Never...", "Always...", "Run...").
  4. Keep the file under roughly 200 lines; the same docs note that longer files "consume more context and reduce adherence."
  5. Re-run the task that caused the original mistake and confirm the agent now avoids it.

Where this breaks

  • CLAUDE.md is loaded as context, not enforced configuration — the docs are explicit that "there's no guarantee of strict compliance." A rule that must always hold (no force-push, ever) belongs in a hook or permission deny-list, not just prose.
  • A file that grows by accretion and is never pruned becomes noise; contradictory instructions get picked "arbitrarily," per the same source.
  • It won't fix a vague task description — that's a separate problem, covered next.

Next: hooks — verification as a loop, not a step.