Five months of Claude Code building its own tooling, steered by me, across a fleet of machines and a handful of separate codebases β a proper todo database, two-tier memory, and a session routine that runs itself.
Most write-ups of AI coding assistants are about a clever prompt or a plugin you can install. This one's about something slower, and I think more useful: having the assistant build its own tooling over months, in a git repo, tuned to exactly how you work.
I've been running Claude Code across a real business for the past five months. Not one codebase but a small portfolio: the oldest and gnarliest is a bike workshop's booking system β twenty years of classic ASP I wrote myself, on Windows, inevitably β and around it a separate public website, a stack of Node services that didn't exist before, a second business's system, and the assistant's own tooling. Each its own git repo, all run from the same machines: Proxmox hosts, Linux servers, a few laptops, a work desktop, and an Android phone running Claude Code in a terminal. Before Claude Code, the oldest of these had been quietly stagnating. Five months on it's been optimised, bug-fixed, and given features that had sat on the someday list for years, while the newer projects grew up beside it. Claude Code itself grew the same way β one small script at a time β into something that knows my machines, remembers its own mistakes, tracks its own work, and starts and ends every session with a single word.
None of that was planned. There's a stripped-down, sanitised example on GitHub β the bootstrap script, the memory layout, the todo CLI, the session hooks:
βΈ Demo repo:[github.com/pyfd/self-improving-claude-code] Everything below is real and in daily use. Take the ideas, not the specifics β the specifics are shaped like my life, which is rather the point.
One repo, every machine #
Everything lives in one git repo of dotfiles and scripts. Every machine clones it and runs a single bootstrap: SSH config, shell aliases, git hooks, Claude Code settings, and Claude's memory. Bare to working in about ten minutes, and every machine behaves the same.
The other half of the glue is Tailscale: every machine sits on the same tailnet, so the phone in a cafΓ© reaches the same todo database and dashboards as the laptop at home.
git moves the tooling; Tailscale moves the traffic.
Together they're the foundation. Claude's whole configuration is versioned, synced and reviewable. Improve the tooling on one machine and every machine has it at the next pull β and once the config is just a repo, the assistant can improve itself the same way it improves your code.
The todo system (a markdown file doesn't survive a fleet) #
Most AI task setups are a markdown file the model edits. Fine for one person on one machine; it falls apart the moment two sessions run at once, or you jot a task on your phone that the laptop needs to see.
Ours is a SQLite database on a server, behind a small authenticated API, with an append-only event log β every add, close, edit and note records who, when and why. On top of that:
- A CLI any machine can call. Tailscale reaches the database from anywhere; with genuinely no signal, the write queues locally and flushes at the next sync.
- The
TODO.md
files still exist, but as generated read-only mirrors. Claude can't hand-edit them. The database is the truth; the markdown is a view of it. - A ranked "what's next", plus a small-model ranker that picks a daily top five and records its picks β so I can see what I chose versus what it suggested.
- A reconcile pass: a cheap model periodically checks open todos against recent git history and flags anything that looks already shipped. Sessions drift; this catches it.
- Guard rails for parallel sessions. Before claiming a task, a session checks what its peers are doing (a peer-check script plus a live dashboard), and the sync scripts lock per machine and never stash another session's work.
Task state is shared, audited infrastructure β not a file the model politely edits.
Memory in two tiers #
Claude Code loads instruction files into every session, and context is a budget. The obvious approach β one ever-growing "remember this" file β quietly fails: it bloats until parts of it stop .
So, two tiers. The first is always loaded: the global instructions plus a memory index β one line per memory, a title and a one-sentence hook. A hundred-odd lines, pruned hard, because every line is paid for on every session. The second tier is a folder of individual memory files β preferences, project state, runbooks, and a lot of hard-won corrections ("never rsync --delete to a server" β earned the day a stray --delete
wiped nineteen files). A file is read only when its topic comes up.
The index is the bridge: it tells each session what detail exists and when to fetch it. Hot and cold storage. The discipline is all in the curation β a vague line never gets fetched, too many lines blows the budget, and past a hard ceiling the index drops its own tail with no warning. It just quietly forgets.
The memory folder lives in the dotfiles repo, so memories sync across the fleet like everything else: something learned on the phone is known to the laptop by the next pull.
The most valuable memory isn't a set of best practices β it's a written record of every mistake the assistant has made for me, and why. You can't download that.
The session routine: go #
and fin
Sessions have a shape, so we made the shape executable.
Typing go
pulls the dotfiles, re-runs the bootstrap and syncs every project repo β flushing the offline todo queue, regenerating the mirrors, and checking the servers for uncommitted drift on the way. One word, and the session starts from a known-good state, whichever machine I'm on.
fin
is the complement, not the reverse: go
restores a known-good state, fin
captures what changed. It updates every doc whose subject moved β changelog, project state, any spec the work touched β reconciles the todo flags, writes a resume point (a machine-stamped note saying exactly where to pick up), closes finished todos with the commit hash as the reason, then commits, pushes and syncs out.
Two details worth pinching:
Resume points are anchored comments in project docs, indexed by a script β any session on any machine can list the newest open ones and pick up half-finished work. Close the linked todo and the resume point retires itself.The routine is timed. A timer brackets everygo
andfin
and posts durations to a central store, so when a step starts dragging, the numbers say which one. You can't tune a ritual you don't measure.
Letting it maintain itself #
Most of what I've described, Claude built. Because the whole configuration is just a repo, it edits its own tooling the way it edits any of the projects β a branch, a diff, a commit you can read afterwards.
That only works because the self-modification runs through the same discipline as everything else. Every change lands with a changelog entry; every closed todo records why; every memory carries the reason it exists. When the assistant gets something wrong, the fix isn't a scolding that evaporates when the chat ends β it's a new memory or guard rail, written down so the next session can't repeat it.
None of it was designed up front. The todo database exists because two sessions once clobbered the markdown file it replaced. The deploy guards exist because a deploy once went out wrong. The curation rules exist because the index blew its budget and forgot its own tail. It accreted, one correction at a time.
The corrections stuck because they live in the repo, not in my head.
It runs real things #
None of this would matter if it were toys. The same system runs actual operations: an alerting stack Claude built and maintains, dashboards for everything (including its own token usage, per machine and per model), and guard rails written after its own mistakes β a pre-commit hook that refuses a commit until the changelog is staged (it blocked me twice while I assembled the example repo for this article β precisely its job), and a deploy that won't touch the live site until the dev version's been eyeballed in a real browser. It holds itself to rules it learned the hard way.
A sideline: the plugin question #
While I was building this, a genre of article appeared β "I cancelled $220 of monthly subscriptions, five Claude Code plugins replaced them all." They're not wrong, and if you're paying separately for a security scanner, a PR-review bot and a browser-testing service, read one. Still: should I have just installed the plugins instead? I evaluated the popular ones, and out of it fell a small lens I now use before adding anything β plugin, MCP server, framework:
Does it regress something I've already built better? A database-backed todo API with an audit trail beats a plugin keeping tasks in a flat markdown file. The better your setup, the more "top plugins" fail this one.What does it cost to keep resident? My fleet includes an 8 GB phone and an 8 GB laptop. Anything running a persistent daemon belongs on the bigger machines only.What does it cost in context? Anything that injects a large instruction set into every session dilutes your own conventions, and near the budget can push your own rules out. Nothing that rides in every prompt is free.Does it fit the actual stack? Mine includes twenty-year-old ASP with deliberately pinned-old dependencies. Modern TDD/LSP tooling helps the modern half and does nothing for β or fights β the legacy core. Your stack will have an equivalent.What's the sync overhead? Every per-machine install is one more thing the bootstrap manages forever. Worth it only when the payoff is real.
Plugins are priced in dollars. The real currency is RAM.
Against those five, the famous plugins mostly came out "already covered" β not because they're bad, but because five months of tooling tuned to your exact setup is a high bar. It should be; that's the point of building rather than installing.
When you should ignore all of this #
If you're starting fresh, install the plugins. Building it yourself only wins when three things are true: you'll use the system daily for years, so the tuning compounds; your environment is genuinely odd (a fleet, a phone, a legacy stack, a real business's guard rails); and you're willing to let the assistant maintain its own tooling, with the discipline that stops that becoming chaos.
If that's you, start small. One repo. One bootstrap script. A memory index you actually prune. The rest builds up on its own β the demo repo above is roughly where I was after the first fortnight.
The interesting outcome isn't saving a subscription. It's a tool that knows how you work, on every machine you own, with a written record of every mistake it's ever made for you. That doesn't come from a directory. It builds up, in a git repo, a little at a time.
Still to come #
Two pieces wouldn't fit here and deserve write-ups of their own:
What five months of Claude Code did to a twenty-year-old codebaseβ the booking-system story: the optimisations, the bug back-catalogue finally cleared, the features that had sat on the someday list for years, and the Node services that grew up around the legacy core.The voice bridgeβ settling design decisions by talking to the Claude app over morning coffee, with the decisions landing back in the todo database as structured, audited history by the time I'm at the keyboard.
Happy to talk any of it through β comments are open below, or over on the demo repo. Written with, inevitably, Claude Code.