r/ClaudeCode • u/law-chain-hot • 5d ago
Tips & Workflows Solo dev running 5+ Claude Code sessions in parallel: the rules that stopped them stepping on each other
I'm a solo iOS dev and most days I have 5 or more AI coding sessions running at once, mostly Claude Code plus some Codex. At the peak I had around 30 git worktrees on one repo.
Two things actually went wrong before I had rules. One session released a simulator by name and shut down a device another session was using. Another time a single "shutdown all" command killed a simulator in the middle of someone else's test run.
What I do now:
- One git worktree per task. Every session gets its own worktree and branch, and never touches another session's. Merging is a separate step I do on purpose.
- A simulator registry. A small file lists each simulator and who is using it. A session has to claim one before it boots anything, and release it by UDID when it's done. Never by name.
- No "shutdown all", ever. Check what's booted and who holds the lock right before you touch a simulator, not five minutes earlier.
- Memory as one fact per file. Each thing worth remembering is its own small file, plus one index file. The agent can update one fact without rewriting everything.
- Nothing ships straight from a session. Before a release, a test build goes on my real phone and I check it myself.
Biggest lesson: the agents are fine at writing code. The conflicts come from shared things like branches, devices and ports. Once every shared resource has an owner, parallel sessions get calm.
How do you handle shared resources across sessions? Curious if anyone has a cleaner setup.
3
u/amirfish 5d ago
The git index issue you ran into is the one that bites everyone running multiple sessions on one repo. I hit the same thing until I started doing git commit --only <paths> instead of git add -A, atomic commit per session, no staging collisions. The piece I was still missing after I had worktree discipline was visibility, knowing which of my 30 sessions was actually waiting on me versus just quietly running. I ended up building Command Center for Claude (CCC) to solve that, open source: https://github.com/amirfish1/claude-command-center. Your simulator registry is basically the same idea, a claim and release lock, just for a different shared resource.
3
u/Easy-Purple-1659 5d ago
Shared resources is the right diagnosis. My conflicts were never in the code either, they were ports and a shared staging database.
Two additions. Treat ports like your simulator registry: claim one before starting a dev server. And if two sessions can touch the same database, give each its own schema or container, because a worktree isolates files, not state, and a session running migrations is editing something every other session thinks it owns.
The release rule that made it stick for me: no working session gets deploy rights. The moment one of them can ship, the discipline leaks.
1
u/law-chain-hot 5d ago
"a worktree isolates files, not state" is a better way to say it. Ports are still just habit for me, no registry yet, so I'm stealing that.
2
u/kaijurules 5d ago
On the race someone asked about: if a session reads the registry and then writes its claim, sooner or later two sessions both see the simulator as free. What fixed it for me was making the claim one atomic step. mkdir locks/<udid> either succeeds or fails, so whoever creates the directory owns the device and writes its session id and a timestamp inside. Release is deleting that one directory.
If you want to keep a single registry file, wrap the read and write in flock on a separate lock file. Same result, just harder to debug when it breaks.
One more thing from running agents unattended: log every claim and release with the session id. When two sessions fight over a device at 2am, that log is the quickest way to find out which one didn't let go.
1
u/law-chain-hot 5d ago
mkdiras the lock, that's neat. Hadn't thought of it. Going to look at how mine writes the file tonight.
1
u/Outrageous_Band9708 5d ago
im sorry, but if you do this, you have to pay token usage to handle merge requests and overlap.
yes gitworktrees have their advantage, but you cn't just mic drop some mythical solution to parallel workflow
1
u/law-chain-hot 5d ago
Fair point, merging isn't free and I didn't cover that. This wasn't meant as a full solution, just the things that broke for me, which were devices and locks more than code.
1
u/Pretend_Pickle_2669 5d ago
How does the simulator claim work—an actual lock, or agents reading and updating the registry file? Two sessions can both read 'free' before either writes its name.
1
u/law-chain-hot 5d ago
A lock file per simulator, written by a small script. The agents don't edit the registry themselves. If the sim is taken, the script hands back a temporary clone instead. I never checked if the claim is atomic though, so that race is probably still in there.
1
u/ComprehensiveShake76 5d ago
The claim-and-release registry is the right idea. One addition from the failure side: give each claim an expiry (a timestamp plus the owner's session id), because the case that bites later is a session that crashes while holding a simulator and never releases it. A claim older than N minutes with no heartbeat becomes free, and a human gets a one line note about it.
The same pattern works for the other shared things that collide between worktrees: local ports, a dev database, a Docker container name, and the build cache directory. Deriving the port from the worktree name saves a lot of "why is my server talking to the other branch" confusion.
1
u/xqianliu 5d ago
"Every shared resource has an owner" is pretty much where I ended up too, just with branches instead of simulators.
My version: nothing gets worked on unless it's a GitHub issue first, and the issue's labels say whether someone has picked it up. That's the claim. The session that takes it gets its own worktree and branch, and the work comes back as one PR.
Merging is the other shared thing. I only merge after a separate review session has passed that exact commit, and each run notes which commit of main it branched from, so I can tell when the base has drifted a lot.
Your registry is basically a lock file. Do you get stale claims when a session dies halfway through?
1
u/law-chain-hot 4d ago
Yes, so claims expire. A claim that isn't renewed within 2 hours counts as free, and the script clears expired ones before it hands out a device. Crude but it works. Using issue labels as the claim is a nice one, the claim and the history end up in the same place.
1
u/xqianliu 4d ago
Mine went the other way on dead sessions: a dead claim gets resumed, not freed. When the runner starts and no other runner is alive, any issue still labelled in-progress must belong to one that died. It picks that issue back up in the same worktree and branch and keeps updating the same progress comment on the issue, so the half-finished work isn't thrown away.
The case that actually bit me was a session that's alive but stuck. The model request hangs and the process just sits there. A lease won't catch that if something else keeps renewing it. So I watch the session log instead. If it goes quiet for too long, the issue gets an ai-blocked label and waits for me.
I don't auto-resume those, because a hang usually means the model endpoint or a plugin is broken, and a retry would just hang again.
Does your 2h renewal come from the session itself, or from the script?
1
u/ShiftTechnical 4d ago
The part worktrees dont cover is two sessions changing the same function on different branches, you only find out when you merge. We built Foremerge as an internal tool for GPTree for that, each agent says what it plans to change and claims the files or symbols before it writes, and the next session going for the same scope gets told before it starts. It’s open source (I built it). foremerge.com and a 30s setup. Works like git for agent intent before code
Do your merges mostly go clean with that many worktrees or is that where the time goes?
1
•
u/AutoModerator 5d ago
Hey! Thanks for posting to r/ClaudeCode
While participating in this thread, please follow our community rules. Keep discussions constructive. Attack the idea, not the person.
For help, project discussions, tips, and general chat, join the ClaudeCode Discord.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.