Six agents, one repo, and the 225 KB file that kept tripping them
I run four to six Claude Code sessions against this repo at once, from my phone. They kept crashing, burning tokens, and concluding they were 2-3 commits behind main. The diagnosis surprised me: the agent instructions file itself had become a 55,000-token tax and the #1 merge hotspot. A build log about the annoyance, the diagnosis, and the three boring fixes that ended it.
Lately I run this site from my phone. Four Claude Code sessions at once, sometimes five or six, all humming away in the Android app. One's waiting on a plan approval. One's pushing a PR. One whose PR I just merged from the couch. It's fun, it's a little absurd, and it worked great right up until it didn't. Sessions started stalling mid-task, burning tokens on nothing I could see, and then, after a long and expensive pause, announcing with total confidence that they were 2-3 commits behind main. This is a build log about why that kept happening and what finally fixed it.
The annoyance
Main on this repo moves fast. Twenty-seven commits a day on average, sixty-three in one recent twenty-four-hour stretch, nearly all of it merged Claude branches. Run several sessions in parallel against that and you start seeing a pattern. A session branches off main, works for an hour, opens its PR, and finds out the world moved. Then comes the expensive part. Instead of shrugging, the session treats "behind main" as an emergency. It rebases, hits the same conflict again, re-fetches, tries again. The git history filled up with merge commits like "resolve ADDON_CATEGORIES conflict: keep both" - two PRs that had each appended one entry to the same registry file, colliding on adjacent lines while being completely unrelated. Meanwhile other sessions were quietly dying a different death. Long sessions would slow down, compact their context, slow down again, and eventually fall over. Crashes, token burn, and stale branches looked like three problems. They were one.
The diagnosis
The culprit was the agent guide itself. CLAUDE.md is the instructions file every Claude Code session loads before it does anything, and it had grown the way these files always grow: every shipped surface tacked on its own deep-dive section, and nothing ever got deleted. By last week it hit 2,879 lines, about 225 KB, roughly 55,000 tokens. Every session paid that toll at startup. And every time a long session compacted its context, the whole thing got injected again. That was the "crashing" — context exhaustion with a paperwork smell.
The same file was also the number-one merge hotspot. Every feature PR appended a section, so any two concurrent PRs collided right there, on adjacent lines, over features that had nothing to do with each other. Hotspot two was the registry files: NavMenu rows, the command palette list, the add-ons catalog, the redirects. Their conflicts resolved the same way every single time. Keep both. The third finding was softer but just as real. Being behind a fast-moving main is physics, not failure. Nobody had ever told the sessions that.
The fix, in three moves
The manual went on a diet. Twenty-four per-surface deep-dives moved verbatim into docs/surfaces/<name>.md (byte-diff-verified, nothing rewritten), and the env-var table got its own file. What's left in CLAUDE.md is a 256-line core: the stack, the commands, the guardrails, plus a domain map where every route points at its doc. A session reads the deep-dive for the surface it's actually touching, and only then. Context tax dropped about ninety percent. But the convention is what keeps it that way. A new surface documents itself in a new file and one table row. Nobody appends to CLAUDE.md anymore, so concurrent PRs have nothing to fight over there.
Sessions sync themselves now. A SessionStart hook fires on startup, resume, and compaction. It fetches origin/main, and if the working tree is clean, it merges. On conflict it aborts and names the files. If the tree is dirty it tells you how far behind you are and which hotspot files moved upstream, then gets out of the way. Up to date means silence, zero context spent. Sessions start fresh instead of discovering they're stale at PR time, which was the worst possible moment to learn it.
The physics got written down. The core now has a short "Concurrent sessions & branch hygiene" section: behind-but-mergeable is normal, merge origin/main once right before you open the PR, and never loop rebases mid-task. Registry conflicts are almost always two PRs appending entries — resolve keep-both, move on. Maybe fifteen lines. It turns a panic spiral into a one-step routine.
It tested itself on the way in
The PR carrying all this got to prove its own point. Live. Three times. The hook ran for the first time in the same session that wrote it, and it auto-merged ten commits that had landed under me before I'd finished the branch. Then, in the few hours the PR sat open, four other PRs merged sections into the old CLAUDE.md and conflicted with my split twice. Both times the fix was exactly the recipe now written into the repo: keep the slim core, move the upstream additions verbatim into their surface doc, check byte-for-byte that nothing dropped. The third conflict I resolved from a phone screenshot of GitHub's "branch has merge conflicts" banner. Want proof the old file was a contention point? The PR that deleted it collected three conflicts in one afternoon.
What I deliberately did not build
I looked at a few tempting options and passed on all of them. Take a bot that auto-updates open PR branches whenever main moves. Sounds great. Until it pushes to a branch some live session is already mid-push on, and then the two of them just fight each other, and you've bought yourself more reconciliation churn instead of less. Or a .gitattributes union merge driver. That would "solve" the keep-both conflicts, sure, by silently producing broken JavaScript, duplicate keys, missing commas. Worse than the conflict it was supposed to kill. And yes, GitHub's merge queue is the grown-up answer for a repo like this one. I deferred it anyway. The three changes above might make it pointless, and I'd rather measure before I reach for the heavy tool. What actually mattered was the boring stuff: keep the shared file small, sync early, write the norms down.
Get the next one
An occasional note when something genuinely new ships here — essays, free tools, projects. No schedule, no filler, easy out.
Need something like this built?
I design and ship AI tools, full-stack apps, and data pipelines — end to end, to production. Tell me the problem in a sentence; I'll give you an honest read on fit within a day.
Work with me →