From a Single File to an MCP Server: Six Rewrites of My Own Harness | by Ian Johnson | Jun, 2026 | Towards AISitemapOpen in appSign up<br>Sign in
Medium Logo
Get app<br>Write
Search
Sign up<br>Sign in
Towards AI
We build Enterprise AI. We teach what we learn. Join 100K+ AI practitioners on Towards AI Academy. Free: 6-day Agentic AI Engineering Email Guide: https://email-course.towardsai.net/
From a Single File to an MCP Server: Six Rewrites of My Own Harness
Ian Johnson
19 min read·<br>Just now
Listen
Share
The file was 1,800 lines long. It lived at ~/.claude/CLAUDE.md. It had grown a table of contents on top, then nested headings, then a few inline rules that contradicted each other, then a section I had forgotten I wrote. I was halfway through adding another rule when I realized I could not remember which of the previous rules it would override. I closed the file. The next morning I broke it into five smaller files. That was the first rewrite.<br>Six months later, the same set of ideas lives inside an MCP server that any agent can talk to. The rules are still there. The skills are still there. The lifecycle is still there. The shape is unrecognizable from the 1,800-line single file, and at the same time, nothing about what the harness means has changed. Every rewrite preserved the content and reshaped the container around it.<br>I want to walk through the six rewrites in order, because each one was driven by a question I asked about my own setup that turned out to be the right question to ask. The rewrites are not a recommendation. You do not need to follow this path. The recommendation is the question that drove each one: what is this rule actually doing, and is the place it lives the place it belongs? If you ask that often enough, your own path will fall out.<br>The thing I did not expect, looking back, is that the rewrites kept making my setup more useful to other people, not less. The opposite of what you would predict. A personal config file should drift toward being more personal over time. Mine drifted toward being more general. I want to explain why.<br>The file got too big<br>The first version of my Claude harness was a single CLAUDE.md at the user-global path. It started small. A paragraph about how I name files. A few rules about testing. A note about not writing comments that narrated the code. Plain markdown, no structure, no frontmatter, nothing the tool was supposed to parse.<br>That worked for about a week.<br>Then I added a section about commit messages. Then a section about how to ask before deleting files. Then a long block about the kinds of refactoring I trust without review and the kinds I do not. Then a paragraph about preferring paratest to phpunit in PHP projects, which contradicted a paragraph I had written a month earlier saying I did not have a strong preference between them. By the time the file hit 800 lines, I was the only person in the world who could load it without skimming, and even I was skimming.<br>The first failure mode was not the agent’s. It was mine. I could not remember what was in my own config. I would write a rule about something, forget I had written it, and write a slightly different version a month later. Two contradictory rules sitting in the same file, both ostensibly mine, both ostensibly active, and no way for the agent to know which one I meant.<br>I broke the file into pieces. One file per topic. Testing. Commits. Editing. Communication. A small MEMORY.md at the top that linked to the others. The split took an afternoon. The morning after, I could find every rule I had written by skimming the directory instead of skimming the file. The agent’s behavior changed, too. The rules stopped fighting each other.<br>That was rewrite one. Modularity at the file level. The lesson was the cheapest one: a configuration file that does not fit on your screen does not fit in your head either, and a thing that does not fit in your head will go wrong in ways you cannot predict.<br>Subdirectory files, scoped to the work<br>The second rewrite came from a different irritation. Most of my rules were global by accident. I had written them in the global config because that was the file I was editing, not because they applied to every project I worked on. The rule about preferring pytest applied to Python projects. The rule about Rails conventions applied to one Rails app. The rule about writing TypeScript types before implementations applied to TypeScript work. None of those were true everywhere, and the agent was loading all of them everywhere.<br>Claude Code had grown subdirectory CLAUDE.md files by then. A file at ~/foo/bar/CLAUDE.md only loaded when the agent was working under that subtree. The path itself decided activation. No frontmatter, no flag, no rule resolver; just the location.<br>I pulled the project-specific rules down to project repos. I pulled the language-specific rules down to language-specific subtrees. The global file shrank to maybe a third of its size. What stayed was the stuff that was...