CLAUDE.md Is a Table of Contents, Not a Rulebook
Most CLAUDE.md files I've seen are bloated. Pages of tone instructions and motivational filler the model half-follows, plus a bunch of restated defaults it already knows. None of it moves the needle, and every line is a tax on the model's attention — anything vague just dilutes the parts that work.
Most CLAUDE.md files I've seen are bloated. Pages of tone instructions and motivational filler the model half-follows, plus a bunch of restated defaults it already knows. None of it moves the needle, and every line is a tax on the model's attention — anything vague just dilutes the parts that work.
After enough iterations on my own projects, I stopped treating the file as a rulebook and started treating it as a map. It ended up doing three distinct jobs, stacked on one page: how to work, where we are, and where things live. They decay at different rates, so it helps to keep them straight in your head.
Layer 1: A few behavioral guardrails
This is the only part that's actually about how the agent works, and it should be short — under a dozen imperative lines, not an essay. The high-leverage rules counteract known failure modes:
- Ground before asserting. Read the real file, the actual signature, the
--helpoutput before claiming something exists. Most "dumb agent" moments are just confident reasoning from stale priors. - Verify, don't assert. Never say "fixed" or "passing" without running it. If it can't be run, say so and mark the claim unverified.
- Diagnose root cause, don't pattern-match the fix. A bug that looks like the textbook version often isn't. Reproduce, locate, confirm the mechanism, then fix.
- Minimal diff, match existing conventions. Do what's asked. Don't refactor things nobody asked you to refactor.
- Re-read state after mutating it. On a long task, the file you edited three steps ago no longer matches your memory of it.
That's the universal layer. Anything aspirational gets ignored, so I keep it tight.
Layer 2: A journal of decisions, not a transcript
This is the part most people mean when they say they want the agent to "remember the project." The instinct is right, but "journal" drifts two ways, and only one of them is useful.
The append-everything version — log every action — just produces a transcript nobody reads. It's staleness wearing a different coat. The version that works is closer to a ship's log that gets edited down: you append as you go, but every update includes reconciliation, not just addition. When a TODO closes, it gets deleted or promoted to a decision in the same commit. That prune clause is the load-bearing half; without it, "always update CLAUDE.md" reliably grows the file forever, because adding is easy and removing takes judgment the model won't exercise unless told to.
I split it into three tenses, because they have different lifespans:
- Locked decisions — append-mostly, rarely change.
- Active TODOs — churn constantly.
- Parked / known-broken — things deliberately set aside.
Mixing them buries the stable stuff in the churn. And the decisions are worth recording with their why, not just their what. The value of a decision isn't the choice, it's the constraint that produced it — so nobody relitigates it later:
Bedrock support via GeyserMC, not native — cross-platform was a hard requirement. Don't suggest dropping it.
That single line tells the next agent what not to propose. Same with the dead-ends. The code shows what I built; it can't show what I already tried that didn't work. A fresh context can't recover "we ruled this out for X reason" by reading the repo — which is exactly why it belongs in the journal.
Layer 3: An index of what matters and where it lives
This is the piece that compounds, and it's the one people skip. Every fresh session re-derives the same map: where's the entry point, where does config get loaded, which file actually owns the thing everything touches. An index turns that repeated search into a lookup.
A good index is not a file tree. ls -R already gives you that and it's useless — it tells you what exists, not what matters. The whole value is in curation and annotation. Three rules keep mine from rotting:
Index roles, not files. Map concept to location, because the agent searches by intent, not by name:
Rate-limit headers get captured in
proxy/intercept.jsFirmware color constants live infirmware/display.ino
"Where X happens" also survives a rename that a bare filename wouldn't. Even if the path goes stale, the agent knows what it's grepping for.
Only the load-bearing nodes. Worth a slot if it's central, non-obvious, or dangerous to touch. A file that's easy to find when you need it doesn't earn one. An index of everything is an index of nothing.
Pin the externals — they're the most expensive to re-find. The references that hurt most to lose aren't even in the repo. The datasheet for the Waveshare board. The one Geyser doc that actually explained the port forwarding. The GitHub issue where I found that Proxmox 8.4 wants media=disk instead of omitting media=cdrom. A fresh context can't re-Google its way back to the specific source that fixed the problem. One line each — the URL plus what it answered — is pure recovered discovery time.
The densest entries fuse all three layers at once:
Bedrock via Geyser — config in
docker-compose.yml, port-forward rationale in [issue link]. Cross-platform was non-negotiable.
That's the what, the where, and the why in one unit, carrying its own evidence trail.
The mechanism that keeps it alive
None of this holds if upkeep depends on me remembering. "I'll keep it tidy" never happens. So I gave Claude a global memory instruction to maintain CLAUDE.md as it works — the agent that's already in the loop on every change is the only thing that can keep the file true.
Two guardrails on that instruction. Prune on a trigger, not a schedule — closing a TODO is the event that fires the cleanup, not some imagined future tidy-up. And scope it to projects that already have a CLAUDE.md, so it doesn't spin up a ceremony file in a throwaway script.
The payoff is continuity across resets. The agent picking up my project next week has no memory of this week — but the file does. So I steer what it writes toward the stuff a fresh context genuinely can't reconstruct: the decisions, the reasons, the dead-ends, the map. The repo can always show the what. The file's job is the why and the ruled-out.
Keep the rules short, the journal pruned, and the index curated, and CLAUDE.md stops being a wall of text the model ignores and becomes the one thing that makes a fresh agent act like it's been here the whole time.