The CLAUDE.md that survived contact
How I went from a four-hundred-line wish list to a short instructions file and one command that either exits zero or does not.
My first CLAUDE.md was about four hundred lines long and did almost nothing. It was a wish list: be careful, write clean code, prefer readable solutions, always add tests. Every line was true and none of it changed a single decision the model made. I had written a values statement and filed it as configuration.
What follows is how I stopped doing that: what I read, what I got wrong, and what the setup looks like now. I am still changing it. The parts I trust most are the parts I can point a command at.
The single highest-leverage change was moving correctness out of the prompt and into a command. My instructions file no longer says “make sure the types are right.” It says: run mise run check, and do not tell me you are done until it is green.
That ordering is not an aesthetic preference. When an agent is iterating, feedback loop length is the thing you are optimising, and most failed attempts fail for a boring reason. Putting the 200ms check first means boring failures cost 200ms. The expensive check only runs on work that already cleared the cheap ones.
Two properties of this gate matter more than what is in it:
- It is one command. Not a README section listing five things to run. An agent that has to assemble its own verification procedure will assemble a different one each time, and the one it picks on a tired afternoon will be the short one.
- It has no baseline file. No ignore list of existing violations. A rule that does not fit this stack gets turned off in
.oxlintrc.jsonwith a written reason, which is a decision someone made and can defend. A list of grandfathered violations is debt made invisible, and an agent reads a passing gate as permission.
This is the distinction I got wrong for months. There are two completely different things that both look like “telling the model what to do”:
- Context: facts the model needs to decide well. Which package manager this repo uses. That TypeScript is pinned to 6, and why. What the colour tokens mean.
- Enforcement: things that must be true regardless of what the model decided. Formatting. Type safety. Coverage floors.
Enforcement written as prose is a suggestion with extra steps. It works most of the time, which is worse than not working, because the failures are the ones you stop checking for. Enforcement belongs in a hook, a gate, or a CI job, something that returns a non-zero exit code. Once I moved everything enforceable out of the instructions file, the file got much shorter and much more useful, because what was left was only the stuff a command could not express.
CLAUDE.md: could this be a failing exit code instead? If yes, make it one and delete the line.I want to be specific here rather than gesture at “best practices,” because the changes I made came from particular claims in particular places.
Anthropic's own best practices for agentic coding (April 2025, since folded into the docs) is where I got the pruning test I still use on every line of an instructions file: would removing this cause Claude to make mistakes? The same document is blunt about the constraint underneath it. The context window is the most important resource to manage, and performance degrades as it fills. That is the sentence that made me delete three hundred lines.
Building Effective AI Agents (Schluntz and Zhang, December 2024) is the one I recommend to people who are about to adopt an agent framework. Their finding was that the most successful implementations they saw weren't using complex frameworks. They were built from simple, composable patterns, many of them a few lines of code. That is why my setup is a shell script and a TOML file instead of an orchestration layer.
Effective context engineering for AI agents (September 2025) gave me the idea I stole most directly: just-in-time retrieval. Keep lightweight identifiers in context, such as file paths and queries, and load the actual content at runtime when it is needed. My global instructions file is now an index of per-language rule files rather than the rules themselves, and most sessions load none of them.
Writing effective tools for agents (September 2025) is about tool design rather than instruction files, but it carries the same lesson with a number attached: switching a Slack tool to a concise response format cut token consumption roughly threefold, 206 tokens down to 72. Verbosity is not free anywhere in the loop.
And how we built our multi-agent research system (June 2025) has the finding I think about most: on their BrowseComp evaluation, token usage by itself explained 80% of the variance in performance. Number of tool calls and model choice accounted for most of what was left.
The blog posts above all lean on the same underlying result, and it is worth reading in the original because the effect is stronger than the summaries suggest.
Lost in the Middle (Liu et al., 2023) is the early one: performance is highest when the relevant information sits at the beginning or end of the context, and degrades significantly when the model has to reach into the middle. If you have ever watched an agent ignore a constraint you stated forty messages ago, that is the shape of it.
The more recent and more uncomfortable one is Chroma's Context Rot (Hong, Troynikov and Huber, July 2025). They evaluated 18 models across the GPT, Claude, Gemini and Qwen families and found that models do not use their context uniformly: performance degrades as input length grows even on tasks that are trivially simple. The number that stuck with me is from their LongMemEval runs, where focused prompts of roughly 300 tokens beat full prompts of roughly 113,000 tokens across every model family tested. A single distracting passage measurably hurt; four of them compounded.
A long instructions file is a distractor you wrote yourself and then attached to every request you will ever make.
Most of what is published about agent workflows is a screenshot of a terminal captioned with a productivity multiple and no method attached. Two exceptions I keep up with:
- Chase AI covers practical Claude Code workflow material: skills, subagent setups, what a real configuration looks like end to end. Useful because he shows the whole setup rather than the one clip where it worked. Note the handle is
@Chase-H-AI; there is a near-identical empty channel at the obvious name. - Nate B Jonesruns AI News & Strategy Daily. Less tooling, more judgement: what a release actually changes, what the second-order effect on a team looks like, which claims to discount. He has a twenty-year product background and it shows in what he refuses to get excited about.
Neither is a substitute for the primary sources. Both are good at the thing primary sources are bad at, which is telling you what a change means on a Tuesday when you have work to ship.
Stripped down, four things.
1. mise.toml every runnable command as a task 2. CLAUDE.md context that cannot be a command 3. scripts/verify.sh the gate, one exit code 4. contexts/*.md per-language rules, loaded on demand
The mise.toml one is quiet but pays off constantly. When every command is mise run <task>, there is exactly one correct way to build, test, format and deploy, and it is discoverable by listing tasks. Before that, the model would reconstruct commands from package.json scripts, from the README, or from memory of a similar project. Those three sources drift apart the moment one of them changes.
The fourth took longest to get right. I used to have every language convention in one global file: Rust rules, Go rules, Python rules, all loaded on every request regardless of what I was touching. Now the global file holds a short index and a trigger condition, and the detailed rules live in files that get read when a task enters that language.
Being honest about the parts I am least sure of, since a post that only lists wins is marketing.
- The comment policy in my instructions file runs to a paragraph on what earns a comment and a list of what never does. It works, but it is prose doing a job I have not found a way to make mechanical, and by my own argument above that makes it suspect.
- I have more custom skills and hooks than I can justify one by one. Some of them I added because a video made them look good, and I have not measured whether they help.
- The coverage threshold in this repo gates lines and functions but not branches, because bun has no reliable branch reporting. That is a real gap dressed up as a decision, and I note it in the config so it stays visible rather than becoming a number nobody questions.
The general principle, though, has survived everything I have thrown at it: write down what the model cannot infer, make everything else exit non-zero, and keep the file short enough that it is still being read on turn forty.