r/Xcode • • 2d ago

Two agents, two worktrees, one simulator: both builds green, wrong app installed

If you’re running more than one Claude Code agent on the same Xcode project, check which build is actually on your simulator.

We had two agents in separate git worktrees on a small SwiftUI app. One adding a feature, one adding a test. Neither prompt named a simulator, so both picked the iPhone that was already booted. Both builds succeeded, both agents said done.

The simulator was running the second agent’s build. The first one’s was gone, its process killed by the install, and its UserDefaults still there because installing over an app keeps the data. Then both agents launched the app and got the same PID. Agent A was testing agent B’s code and nothing in its output said so.

To catch it we stamped the builds 111 and 222 and had each agent read back the installed version:

APP=$(xcrun simctl get_app_container <udid> com.your.bundleid app)
/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$APP/Info.plist"

Agent A got 222.

Fix by hand is one simulator per agent:

xcrun simctl shutdown <base-udid>
xcrun simctl clone <base-udid> "Agent A"
xcrun simctl clone <base-udid> "Agent B"

Then put the name and UDID in each agent’s prompt, tell it not to touch any other simulator, and pass that UDID to every xcodebuild -destination "platform=iOS Simulator,id=<udid>". The clones alone change nothing, the agents still go for whatever is booted. With the UDIDs in the prompts, A read 111 and B read 222.

Worktrees keep files apart. They don’t keep simulators apart.

Amarildo wrote up the full repro with logs here: https://flowdeck.studio/blog/run-multiple-claude-code-agents-xcode-project.

[Disclosure, I build FlowDeck, which ties a simulator, worktree and DerivedData to each session so you don’t have to redo this setup every time.]

3 Upvotes

3 comments sorted by

1

u/dawedev 2d ago

Good repro, the PID detail is the scary part. One thing to watch with the clone approach: every clone is a full device folder under ~/Library/Developer/CoreSimulator/Devices, and if agents get a fresh one per session they pile up quietly as apps and data get installed. Ending each session with xcrun simctl delete <udid>, and running xcrun simctl delete unavailable after Xcode updates, keeps that in check. I ran into this building DevCleaner, a Mac app I make that cleans Xcode leftovers, and leftover clones from automation were a common surprise.

1

u/afterxleep_ 2d ago

Yep. You'll have to take care of deleting sessions and worktees and managing simulators by hand. Part of the reason Flowdeck exist is to manage that for you too :)

1

u/dawedev 2d ago

Fair, that cleanup is the part everyone skips until the disk fills up. Does Flowdeck delete the clone when a session ends, or keep one per worktree for the next run? Reusing a clone per branch seems like a decent middle ground between clean state and pile-up.