Part of the Claude Code workflow series. Start with the install primer; then what to do after install; then this post when your CLAUDE.md is starting to drag and you want to clean it up properly.
Your CLAUDE.md started as 80 lines of genuinely-useful guidance. Four months later it's 620 lines and the model starts ignoring the middle third. Happens to everyone. Usually not because you're bad at writing rules but because you never built a discipline for removing them.
Below are the eight anti-patterns that cause CLAUDE.md rot, in rough order of how much damage they do. For each, the fix is specific.
Anti-pattern 1 — Dumping conversation context into the file
You had a great conversation with Claude about why the checkout flow uses a two-phase commit. You don't want to re-explain it tomorrow. You paste the conversation into CLAUDE.md. It works once.
Six weeks later the file has 40 paragraphs of narrative explaining why decisions were made. None of them are rules — they're history. The model is now reading a changelog on every turn.
Fix: narrative explanations belong in docs/decisions/ (or ADR/ — architecture decision records). CLAUDE.md gets the decision, not the discussion. Instead of:
We debated whether the checkout flow should use event-sourcing, and after a two-hour conversation we decided against it because the team isn't comfortable with the operational overhead, but we might revisit this in Q3 if our throughput doubles...
Write:
Checkout flow does NOT use event-sourcing. ADR-0014 has the reasoning.
One line in CLAUDE.md, full context preserved in a linked ADR the model can read on demand.
Anti-pattern 2 — Session-specific state
"We're currently refactoring the auth module; don't touch files in src/legacy/auth/ until the migration is complete."
Three weeks later the migration is done. The rule is still there. Claude refuses to edit src/legacy/auth/ which now contains perfectly current code. You spend 20 minutes figuring out why.
Fix: if a rule is tied to a time-bound state, it doesn't belong in CLAUDE.md. Put it in a branch description, a commit message, or an ephemeral note in the current session. CLAUDE.md is only for things that will be true for the next six months minimum.
Smell test: if you'd feel embarrassed for the rule to still be in the file two years from now, it's session-specific state.
Anti-pattern 3 — Aspirational rules
"We should always pair-program on security-sensitive changes."
Except nobody does. Claude reads the rule, tries to enforce it, asks who's pairing. You say "just do it anyway." Claude reluctantly proceeds. Next session: same dance.
Aspirational rules rot a file faster than anything else because they're simultaneously worth including (they describe the ideal) and worth removing (they don't reflect practice).
Fix: only include rules that describe actual, enforced behavior. If the team doesn't pair-program, don't write "we pair." If you'd like to start pairing, write the pairing-enforcement mechanism (a hook, a PR template rule, a review approval requirement) first and add the rule after the mechanism works for a month.
Anti-pattern 4 — Rules for problems you no longer have
You had a bug six months ago where the Svelte 3 reactive block fired twice on mount. You added "always check reactive blocks for double-fires." You've since migrated to Svelte 5. The rule is meaningless. It's also still in the file, still being read every turn, still taking up attention budget.
Fix: quarterly read-through. Open CLAUDE.md, go line by line, ask "is this still true?" Delete the no's.
A useful heuristic: every time you finish a migration, finish it in CLAUDE.md too. Migrated off X? Delete every rule that mentions X.
Anti-pattern 5 — Secrets (even "obviously masked" ones)
"The API key for the staging env starts with sk_stg_ — make sure not to commit it."
You've just told everyone with file access that your staging API key prefix is sk_stg_. Combined with your repo name and a public Stripe-style key format, that narrows a brute-force to a feasible space.
Doesn't matter whether the key is real, partial, or "example-only." CLAUDE.md is indexed, searchable, and often accidentally committed to public repos. Treat it like it's public.
Fix: environment variable names only, never values or prefixes. Reference: "The staging environment requires STRIPE_SECRET_KEY. Value in Netlify env settings." The model doesn't need the value to know the variable exists.
Anti-pattern 6 — Rules that explain what well-named code already says
"The function validateOrderTotal validates the order total."
Yes. That's what the name says. You've now taught Claude the function name twice — once in code, once in the prompt — and wasted three lines.
Fix: only document the non-obvious. If a function name is clear, trust it. Write rules about behaviors that the code itself can't express: "Orders over $10K need manual approval; never auto-approve in code." That's worth a line; re-explaining function names is not.
Anti-pattern 7 — The "catch-all" rule
"Follow good coding practices."
This rule says nothing. It cannot be violated (everyone thinks their practices are good) and cannot be enforced. The model reads it, shrugs, and moves on. It's a placeholder for an actual rule you never got around to writing.
Fix: delete catch-all rules. Either write the specific rules you actually want enforced or say nothing. A file of six specific rules is stronger than a file of fifty vague ones.
Anti-pattern 8 — Circular or self-referencing rules
"All files must conform to the style guide. The style guide requires all files to conform."
Happens more often than you'd think, usually because two people wrote the rule at different times without reading the file in between. The model can't resolve the circularity and ends up falling back to its own defaults.
Fix: on every read-through, look for rules that reference each other. If A says "follow B" and B says "follow A," one of them has to anchor to a concrete specification. Link out to the actual style guide, the actual security doc, the actual linter config.
Why files rot — the mechanism
Two forces work against CLAUDE.md:
-
Additions are easy; removals are scary. Nobody wants to be the person who deleted a rule and broke a convention. So rules accumulate. Every "just add one line" is a 2-minute decision; every "is this still true?" is a 20-minute one. Asymmetry → growth.
-
The file is read by a machine, not a human. Humans would notice if a project README grew to 600 lines of contradictory advice. Claude reads dutifully every turn, not flagging the contradictions, not asking about staleness. The rot is invisible until you open the file directly.
Both forces compound. A file at 200 lines is healthy. A file at 400 lines has usually lost ~30% relevance. A file at 800 lines is mostly historical archive with some current rules buried inside.
The maintenance discipline that actually works
Two habits, both cheap:
End-of-session one-liner. At session close, ask: "what did we learn today that future sessions should know?" If the answer is "nothing scoped, just progress on the current task" — don't touch CLAUDE.md. If the answer is "the Postgres connection pool has a silent limit at 20 and we shouldn't exceed it" — that's a one-line addition. Two minutes.
Quarterly read-through. Every 90 days, open the file and read every line. Three questions per line: (a) is this still true? (b) is this a rule or a story? (c) is this specific enough to enforce? Delete "no" to any of the three. Takes 20–30 minutes. Prevents the slide.
Between those two habits, CLAUDE.md stays alive. Skip both and it rots.
The cleanup — one-time exercise if yours is already bloated
If your file is already at 500+ lines:
- Copy it to
CLAUDE.md.backupso you can recover anything you mistakenly delete. - Open both side-by-side. On the left: the current file. On the right: a new empty CLAUDE.md.
- Walk the current file top to bottom. Copy only lines that pass all three checks: still true, actually enforced, specific enough to enforce. Paste into the new file.
- Stop when the new file is around 120–180 lines.
- Commit both. The backup is a searchable archive of history; the new CLAUDE.md is the active prompt.
- Run a fresh session and ask Claude to summarize the project. If the summary is coherent and covers the basics, you kept enough. If it's missing something critical, copy that one line back.
Related reading
- AI Terminal Kickstart — install prereq.
- CLI installed — now what? — the overview that introduces CLAUDE.md as a living contract.
- Skills vs Rules vs Memory — the four-layer hierarchy where most of your "rules" probably belong outside CLAUDE.md.
- Claude MD Generator — generates a lean starter CLAUDE.md from project inputs; good template when you're rebuilding after the cleanup.
Fact-check notes and sources
- Arize: CLAUDE.md best practices from prompt learning — empirical study on what makes CLAUDE.md improve model behavior (and what makes it worse).
- Anthropic: Effective context engineering for AI agents — theory behind why long prompts degrade.
- Pragmatic Engineer: How Claude Code is built — Cherny's "living contract" framing.
- Walturn: Mastering prompt engineering for Claude — general prompt-engineering hygiene that applies to CLAUDE.md.
Informational, not engineering consulting advice. Mentions of Anthropic, Claude Code, third-party authors are nominative fair use. No affiliation is implied.