The people getting the least out of Claude Code have a 400-line CLAUDE.md and add a rule every time it slips. The people getting the most delete. Here's the ablation workflow, with a real before/after.
You can tell a lot about someone’s Claude Code setup by how they treat their CLAUDE.md. The people getting the least out of the tool have a 400-line manifesto. Every time the model does something dumb, they add a rule. The file only grows. It’s a scar for every bug, and nobody ever goes back and checks if the scar is still doing anything.
The people getting the most out of it do the opposite. They delete.

The 80% delete
When Boris Cherny — who created Claude Code — talked about a model upgrade, he described something that sounds insane if you’ve been hoarding instructions: on the bump, the team deleted about 80% of their system prompt. Not trimmed. Gutted.
The reasoning is the interesting part. Most of the lines in a long system prompt aren’t there because they describe how the model should work. They’re there because at some point a dumber model got something wrong, and someone wrote a rule to stop it. “Don’t forget to run the tests.” “Always use absolute paths.” “Never assume the file exists.” Each line is a patch for a specific past failure.
Now hand that pile of patches to a smarter model. It already knows to run the tests. It already handles paths correctly. But it still has to read all of it, every single turn. And here’s the part that stings: a wall of corrective instructions doesn’t just cost tokens, it can actively make a capable model worse. You’re pre-loading it with the assumption that it’s the kind of thing that forgets to run tests. You’re talking down to a model that didn’t need the lecture, and you’re spending attention budget to do it.
Per the interview, that gap widens with each model generation — the forward-looking claim is that something like Opus 5 makes even more of your carefully-tuned scaffolding redundant. Treat that as “per the interview,” not settled fact. But the direction is the point: your instructions are calibrated to a model that no longer exists.
System prompt debt
Call it what it is. Every instruction you keep is tech debt with a nicer font.
Regular tech debt at least announces itself — the build gets slower, the flaky test fails, someone rage-quits the module. System prompt debt is silent. A stale instruction doesn’t throw. It just sits in context, quietly costing you attention and quietly nudging the model toward behavior it would’ve gotten right on its own. It never shows up in a diff as “this line made things worse,” because you never A/B’d it. You just… kept it. Forever. Out of a vague sense that it was helping.
So here’s the test for every line in your config. It has to map to a specific, reproducible failure it prevents. Not “this feels like good practice.” Not “a blog said to.” A failure you can point at. If you deleted this line right now, what exact thing breaks, and can you make it break on demand?
If you can’t answer that, the line isn’t an instruction. It’s a superstition.
This applies to the whole surface, not just CLAUDE.md:
~/.claude/CLAUDE.md(global) and repoCLAUDE.md- Everything in
.claude/commands/ - Hooks and permission rules in
.claude/settings.json - Your subagent definitions in
.claude/agents/ - Every MCP server you’ve bolted on that the model reads a description for
All of it is context. All of it is billed every turn. All of it is up for deletion.
The ablation workflow
Ablation is a word borrowed from ML research: you remove a component to see how much it was actually contributing. Same move here. You don’t reason about whether an instruction helps. You cut it and measure.
The workflow, step by step:
- Move the whole thing out of the way. Not delete-delete — stash it.
mv CLAUDE.md CLAUDE.md.bak. Same for a suspect command or hook. You want the model running raw. - Run a real task against it. Not a toy. Pick something representative of your actual work — a bug fix in your real repo, a refactor you’d normally hand it.
claudeinteractively, orclaude -p "..."for a scripted one-shot you can re-run identically. - Watch exactly where it stumbles. Don’t fix anything yet. Just observe. Where did it guess wrong? What convention did it miss? Did it actually miss it, or did you just assume it would?
- Add back single lines — only for documented, repeatable failures. If it botched something twice in a way that’s clearly about your project (not general competence), that earns a line. One line. Then you re-run and confirm the line actually fixed it.
The default state of a CLAUDE.md line should be “deleted.” It has to earn its way back in by preventing a failure you watched happen. Most of your old lines won’t survive that bar, and that’s the whole point.
Worked example
Here’s a CLAUDE.md that looks a lot like real ones I’ve seen — and written. This is a TypeScript project. Read it and count how many lines are teaching a competent model to breathe.
# CLAUDE.md
## About this project
This is a web application built with TypeScript. It is a modern
codebase and we care about code quality. Please be thorough and
careful when making changes.
## General rules
- Always read a file before you edit it.
- Think step by step before writing code.
- Do not make assumptions about the codebase.
- Write clean, readable, maintainable code.
- Follow best practices at all times.
- Always double-check your work before finishing.
- If you are unsure, ask the user.
- Never delete code unless asked.
- Add helpful comments to explain complex logic.
- Prefer simple solutions over clever ones.
## TypeScript
- Use TypeScript. This is a TypeScript project.
- Always use types, avoid `any` where possible.
- Use `const` instead of `let` when a variable is not reassigned.
- Use async/await instead of raw promises.
- Handle errors properly with try/catch.
## Testing
- We use Vitest for testing.
- Always run the tests after making changes.
- Run tests with: npm test
- Make sure all tests pass before you finish.
- Write tests for new features.
## Formatting
- We use Prettier.
- Run the formatter before finishing.
- Use 2 spaces for indentation.
- Use semicolons.
## Git
- Write clear commit messages.
- Do not commit unless asked.
## Package manager
- This project uses pnpm, not npm. Run `pnpm test`, `pnpm build`.
Now run the ablation. Move it aside, hand the model a real ticket, watch. Here’s what survives, and here’s why:
# CLAUDE.md
- Package manager is pnpm. Tests: `pnpm test`. Build: `pnpm build`.
- Vitest tests live next to source as `*.test.ts`.
- Do not commit unless asked.
Three lines. Let me defend every cut, because “just delete it” without the why is its own cargo cult.
The entire “General rules” section — gone. “Read a file before you edit it” — the model already does; the Edit tool literally requires it. “Think step by step,” “don’t make assumptions,” “be thorough,” “double-check your work” — this is motivational-poster prompting. A current model doesn’t do better because you told it to care. It’s already trying. “Prefer simple over clever,” “add helpful comments” — taste directives so vague they change nothing. If you can’t point at the botched output these prevent, they’re not doing anything.
Most of “TypeScript” — gone. “Use TypeScript. This is a TypeScript project.” The model can see the .ts files. “Use const over let,” “async/await over promises,” “avoid any” — this is the model’s default style already. You’re describing water to a fish. If your project genuinely bans any at the lint level, the linter enforces it and the model reads the error — you don’t need a prose reminder too.
Most of “Testing” and “Formatting” — folded down. “Always run the tests,” “make sure they pass” — good models already run tests when they change behavior; if yours doesn’t, that’s a real repeatable failure and it earns one line, but “always double-check” fluff doesn’t. Prettier config lives in .prettierrc — the tool is the source of truth, not a paraphrase of it in prose that’ll drift the moment someone changes the config.
What survived and why it’s load-bearing: the pnpm line prevents a specific, reproducible failure — the model’s prior is npm, and it’ll reach for npm test unless told, wasting a turn on a wrong command. That’s a real bug you can reproduce on demand. The test-location convention is genuinely non-obvious — some projects use __tests__/, some co-locate, the model can’t know yours without looking, and telling it saves a search. “Don’t commit unless asked” is a guardrail against an action that’s annoying to undo. Each of these three maps to a concrete thing that goes wrong without it.
Everything else was teaching a senior engineer how to use a keyboard.
The intelligence floor
There’s a probe worth knowing about, with a big flashing caveat: it’s undocumented and experimental, it can change or vanish without notice, and you should treat it as a diagnostic toy, not a setting you leave on.
CLAUDE_CODE_SIMPLE=1 strips the system prompts — including the tool prompts — down to the bone.
CLAUDE_CODE_SIMPLE=1 claude -p "refactor the auth middleware to use the new session helper"
What you’re looking at with this is the intelligence floor. How well does the model do your task with almost nothing scaffolding it? Because if it does fine — and on a lot of tasks it does — that’s your evidence that most of the scaffolding you’ve been carrying was for a model that isn’t in the seat anymore.
Again: undocumented, experimental, not a daily driver. It exists to answer one question — “how much of this does the model actually need?” — and the answer is usually “less than you think.” Run it, get the gut-check, go back to normal mode. Don’t build a workflow on a flag that isn’t promised to exist next week.
Measuring “did it get worse”
The whole thing collapses into vibes unless you measure. Cutting a line and feeling like it’s fine is how you delete something load-bearing and don’t notice for two weeks.
So make it a controlled test:
- Pin a task. One real, representative job. Write the prompt down verbatim so it’s identical every run.
claude -pis your friend here — same input, comparable output. - Baseline it. Run with the current config. Note what happened: did it pick the right file, use the right command, follow the convention, finish clean?
- Cut one thing. One line, one command, one hook. Not five. If you pull five and it breaks, you don’t know which one mattered.
- Re-run the identical task. Same prompt, cut config.
- Compare. Same result or better → the line was debt, leave it deleted. Worse in a specific, repeatable way → restore that one line and note what failure it prevents right there in the file.
That last habit is underrated. When a line earns its place, write the why next to it as a comment. Future-you doing the next ablation gets to read // pnpm, model defaults to npm otherwise instead of guessing whether it’s safe to cut. You’re leaving a test case, not a decree.
One line at a time is slow. It’s also the only version of this that tells you anything. Ablate in bulk and you’ve run an experiment with no controls — congratulations, you’ve learned nothing and now your config is a mystery.
Why it’s a habit, not a spring clean
Here’s the trap. You read this, you do one glorious purge, you feel great, you never do it again. Six months later you’re back to a 300-line file because you went right back to adding a rule for every hiccup.
Delete-first is a habit, and it fires on a specific trigger: every model bump.
Because that’s exactly when your instructions go stale. A new model rolls out. Overnight, a chunk of your CLAUDE.md is now correcting mistakes the new model doesn’t make. The lines didn’t change — the model underneath them did. If the Claude Code team can bring themselves to delete 80% of their system prompt on an upgrade, your personal pile of “always remember to…” lines can survive a re-run.
So bake it into your upgrade ritual. New model lands → before you trust your old scaffolding, ablate it against a real task. Assume the new model needs less. It usually does. The config that was perfectly tuned for last generation is, by definition, over-tuned for this one.
The two failure modes
This habit has exactly two ways to bite you, and they pull in opposite directions.
Cutting a load-bearing line. You delete something that was quietly doing real work, and now the model face-plants on a convention only your project has. This is the scary one, and it’s entirely preventable — it only happens if you cut without measuring. The fix is the workflow above: pin the task, cut one thing, re-run, compare. If output degrades, you restore the line and now you know exactly what it prevents — which is more than you knew when it was just sitting there unexamined. A caught load-bearing cut isn’t a failure. It’s how a line earns documentation.
Keeping cargo-cult lines out of fear. This one’s quieter and way more common. You suspect a line is dead weight, but cutting it feels risky, so you leave it “just in case.” Multiply by a hundred lines and that’s how configs rot. Fear is not evidence. “I’m not sure this does anything” is not a reason to keep something — it’s the exact signal to run the experiment. The CLAUDE_CODE_SIMPLE=1 probe exists partly to break this fear: watch the model do fine on almost nothing, and “just in case” loses its grip.
Notice the asymmetry. The measured cut is cheap to reverse — it’s one git revert on a text file. The hoarded line is expensive precisely because it’s invisible; it never announces the tax it’s charging. So bias toward cutting. Deletion is a reversible experiment. Keeping-out-of-fear is a permanent one you never actually ran.
The ablation checklist
Tape this next to your keyboard. Run it every model bump, and any time your CLAUDE.md crosses a smell threshold (mine is about 40 lines).
- Stash, don’t delete:
mv CLAUDE.md CLAUDE.md.bak. Same for suspect commands, hooks, subagent defs. - Pick one real task. Representative of actual work. Write the exact prompt down so it’s repeatable.
- Baseline raw. Run with config stashed. Note precisely where it stumbles — file choice, commands, conventions, cleanup.
- Add back only documented failures. A line earns its place only if you watched the failure and can reproduce it.
- One line per failure. No bundling. No “while I’m here.”
- Comment the why. Next to each surviving line, one note on the failure it prevents.
- Re-run identical after each cut. Same prompt. Same or better → stays cut. Worse → restore that one line.
- Gut-check the floor:
CLAUDE_CODE_SIMPLE=1 claude -p "<task>"to see how little the model actually needs. (Experimental. Diagnostic only.) - Sweep the whole surface:
.claude/commands/,.claude/settings.jsonhooks and permissions, MCP servers, subagents — all context, all billable, all cuttable. - Re-run this on the next model bump. It’s a habit, not an event.
The best config isn’t the one that anticipates every mistake. It’s the one small enough that you can hold all of it in your head — where every line is there because you watched something break without it.
Your model got smarter. Your instructions should get shorter. Go delete something.