
Why Claude Ignores Your CLAUDE.md — and the Fixes That Hold
Your rules work on turn one and are gone by turn five. That is not defiance, it is dilution — and the fixes are shorter files, rules kept near the work, a canary you can actually check, and mechanisms instead of prose.
You wrote the rule down. It is in CLAUDE.md, in bold, near the top. It worked on Monday. By Wednesday the assistant is creating files in the folder you told it not to touch, using the naming convention you retired in March, and writing its own error shape for the fourth time this week. You add the rule again, louder, with a warning emoji. It holds for a few turns and then it does not.
This is the single most common complaint about agentic coding tools, and it is not a mystery, a bug report, or a sign that you wrote the rule badly. It is a predictable consequence of how an instruction file is used — and once you know the mechanism, the fixes are obvious and mostly boring.
The short version: a longer instruction file is followed less, not more. Every line you add competes with every line already there. The rule you care about most is usually the one buried deepest in the file you keep growing.
CLAUDE.md is not configuration. It is text in the conversation.
This is the part that trips people up. A settings file is read by a program that then behaves differently. CLAUDE.md is not read by a program — it is placed into the conversation as more words, alongside your prompt, the files that got opened, the output of every command that ran, the diff you just asked about, and the last forty minutes of back-and-forth. It has no special standing. It is not enforced by anything. It is advice sitting in a room that gets noisier by the turn.
That explains the shape of the failure people report: fine at the start of a session, worse as the session grows, and worse again the longer the instruction file itself is. Nothing broke between Monday and Wednesday. The ratio changed — of instruction to everything else — and it changed in the direction you kept pushing it by adding rules.
Other people describe it the same way
The Hacker News thread "Writing a good Claude.md" (item 46098838) ran to several hundred comments, and the recurring theme is not that the model is disobedient — it is that attention is a budget. One commenter's phrasing for what happens when you keep adding material is that it "dilutes attention". That is a good description of the observed behaviour: nothing is switched off, everything is simply weighted less.
Anthropic's own documentation for Claude Code points in the same direction with the way Skills are designed. Rather than one permanent block of instructions that is always present, a skill is loaded when the task at hand matches it, so the always-on layer stays small and the specific material arrives only when it is relevant. That design choice is only worth making if permanently-present instructions have a real cost — which is the whole argument of this article, made by the vendor, in the shape of a feature.
A useful reframing: you are not writing a config file, you are writing the briefing note that a very fast, very literal contractor skims before every single task. Nobody skims eleven pages before every task. Neither does this.
The four fixes that actually hold
None of these are clever. They are the same four moves in a different order every time, and they work because they attack the mechanism rather than the symptom. Do them in this order — the first one makes the other three cheaper.
1. Make the always-on file shorter
Keep only what is true across the whole repository, non-obvious, expensive to discover by reading the code, and costly to get wrong. That is a surprisingly short list for most projects — the deploy target, the one database driver you actually use, the directory nobody may edit, the command that verifies a change, the two habits from your other project that would be actively wrong here. Everything else is a candidate for deletion or relocation.
2. Put the rule where the work is
Distance is the enemy. A convention explained on line 380 of a root-level file is something the assistant has to recall; the same convention written in the folder being edited is something it is looking at. Use directory-scoped instruction files next to the code they govern, and load specialised material as a skill that activates on the task instead of parking it in context forever. Same words, much better position.
3. Plant a canary and watch for it
Add one cheap, harmless, unmistakable instruction to the file and then check whether it shows up. If it does, the file was in play at that moment. If it does not, you have your answer, and you have it in seconds instead of after an hour of arguing with a rewritten module. This is the only feedback loop in the whole business, and almost nobody sets one up.
4. Move rules out of prose entirely
Anything a machine could check should be checked by a machine rather than described in an instruction file. A type that makes the wrong shape impossible, a lint rule, a hook that refuses a commit, a template file to copy from, a script in package.json. Prose is what you spend on the things that genuinely cannot be mechanised. Spending it on the things that can is how instruction files get long in the first place.
The canary instruction, and the brown M&Ms
The Hacker News thread reached for an analogy that lands perfectly: Van Halen's touring contract famously buried a clause requiring a bowl of M&Ms backstage with the brown ones removed. It was not a diva demand. It was an instrument. The contract also specified how much weight the stage floor had to bear, and a promoter who had skipped the snack clause had probably skipped the structural one too. One glance at the bowl told the crew whether the document had been read.
You can do exactly this with an instruction file, and it takes about a minute. Add something trivially observable and completely harmless, then look for it during ordinary work.
Canaries that work well in practice:
- Ask for a fixed acknowledgement token at the top of a reply — one short line naming the instruction file — and nothing else about it. You will notice its absence immediately.
- Ask that every new file created in the repo open with a specific comment header. This one is durable: it leaves evidence in the diff, so you can check adherence after the fact rather than having to watch live.
- Ask for a specific, slightly unusual word in the summary at the end of a task. Cheap, invisible to anyone reading the code later, and easy to grep out of a transcript.
- Put the canary at the END of the file, not the top. If the last line is still landing, the middle probably is too. A canary at the top tells you almost nothing — that part was never the part at risk.
- Check it again after every material edit to the file, and again deep into a long session. Adherence decays with both file length and conversation length, so a canary you checked once, on a short file, on turn two, is a measurement of the easiest possible case.
Be clear about what the canary proves. Present means the file was in play at that moment. Absent means it was not, or it lost. It does not tell you the other forty lines were followed, and it is not a substitute for looking at the diff. It is a smoke alarm, not an inspection.
More like this, occasionally.
Practical write-ups on shipping software with AI assistants — what holds up in a real codebase and what does not. No spam, unsubscribe anytime.
No spam. Unsubscribe anytime.
A rule a human has to remember to enforce is not enforced
This is the part worth taking away even if you ignore everything else. Every line in an instruction file is advisory. Nothing happens when it is ignored. No build fails, no test goes red, no reviewer is paged. Its entire enforcement mechanism is a person noticing — and people notice things at the end of a long day about as reliably as a language model does on turn forty.
So the useful question about any line in your CLAUDE.md is not "is this correct?" but "what happens if this is ignored?". If the answer is "nothing, until someone spots it in review", that line is decoration. Either give it a mechanism or accept that it is a preference rather than a rule.
The same rule, written two ways:
| Written as prose | Given a mechanism |
|---|---|
| "All API responses must use our standard error shape." | One exported error type plus one helper that builds it. The wrong shape does not compile. |
| "Never import directly from the database layer in a component." | A lint rule with the import path banned. The editor underlines it before anyone commits. |
| "Run the type check before saying a change is done." | One script in package.json that runs check, lint and build together, named in the instruction file. |
| "Follow the existing pattern for new routes." | A template route in the repo, referenced by path. Copying beats interpreting. |
| "Do not edit files in the generated directory." | A hook that refuses the commit, plus a one-line banner at the top of each generated file. |
Notice what happens to the instruction file in the right-hand column: it gets shorter. Each mechanised rule turns into a single sentence pointing at the mechanism — "error shapes come from the shared type; see libs/errors.ts" — instead of a paragraph explaining a convention and hoping. That is fix one and fix four doing the same work from opposite ends.
A half-hour audit you can run today
Open your instruction file and go through it once, line by line, asking a single question of each line: does this survive?
- Delete anything that is already the default behaviour. "Write clean, readable code" and "use meaningful variable names" are not instructions, they are throat-clearing, and they sit in the same budget as the line about your deploy target.
- Delete anything that restates public framework documentation. It is already known, and repeating it takes the place of something that is not.
- Move anything that applies to one folder into that folder. If the admin dashboard has its own auth rules, those rules belong beside the admin dashboard.
- Convert anything checkable into a check. Work down the table above until you run out of easy ones.
- Rewrite what is left as short, concrete, imperative sentences. Prefer "deploy is `npm run ship`; never push to main" over three sentences of background about why.
- Keep the hazards. Non-obvious, expensive, project-specific traps are the highest-value lines in the file and the reason it exists at all: the thing that silently corrupts files, the folder that is generated, the command that costs money.
- Plant your canary at the bottom, then run one real task and look for it.
Do the same audit again in a month. Instruction files grow the way a junk drawer grows — one reasonable addition at a time, each of which made sense on the day. The audit is not a one-off; it is the maintenance.
What none of this fixes
A shorter file is still not binding. Better placement improves the odds; it does not make an instruction mandatory, and there is no wording, formatting, capitalisation or emphasis that does. If a rule genuinely must hold every time, it needs a mechanism outside the conversation — a type, a check, a hook, a review step. That is true of a new hire on their first week for exactly the same reason, and we do not find that controversial when the contractor is human.
The honest summary is that an instruction file is a briefing, not a contract. Treat it like one: keep it short enough that someone would actually read it before every task, put the specifics next to the work, verify occasionally that it is landing at all, and give the rules that really matter something harder than good intentions to stand on.
This article describes a mechanism and the practices built on it. It does not report a measurement, and no figures about instruction length are claimed here.
Sources
Want a second pair of eyes on your codebase?
We build and maintain software for businesses in Waco and across Central Texas, and we review AI-assisted codebases that grew faster than their conventions did. Tell us what is going wrong and we will tell you what we would do about it.
Talk to Us