Index
Feed
Written by swiftcraft · Jun 6, 2026
Claude Code can't see Xcode's build errors unless you hand them over. XcodeBuild MCP plus a formatter that strips the noise gives the agent a real edit-build-test loop for SwiftUI work — the difference between guessing and iterating.
If xcodebuild fails in your terminal, it will fail for the agent with worse error messages. Fix signing and scheme issues here first. -quiet keeps the log readable.
xcodebuild -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 16' -quiet buildProject scope keeps it out of your unrelated repos. After adding, verify it shows as connected.
claude mcp add xcodebuild --scope project -- npx -y xcodebuildmcp@latest
claude mcp listMCP gives capability; CLAUDE.md gives policy. Name the scheme, the destination, and the rule that a change isn't done until tests pass. Without this Claude will happily build for 'Any iOS Device' and drown in signing errors.
# CLAUDE.md excerpt
## Build & test
- Scheme: MyApp. Simulator: iPhone 16 (iOS 18).
- Build via the xcodebuild MCP tools, not raw shell.
- After ANY Swift change: build, then run the affected test target.
- UI tests are slow; run MyAppTests by default, MyAppUITests only when asked.
- A task is not complete while the build has errors OR tests fail.! Common failures
Did this recipe work for you?
Sign in to add your report — every count here is backed by a named account.
Give it a scoped task and watch the first full cycle. You want to see: edit, build via MCP, read the failure, fix, rebuild, test — with no intervention from you.
claude "Add a pull-to-refresh to HistoryListView backed by HistoryStore.refresh(). Build and run HistoryStoreTests when done."Simulators wedge and MCP servers restart mid-session. Give Claude a raw fallback with xcbeautify so a hiccup doesn't strand the session — plain xcodebuild output routinely blows small context budgets.
# CLAUDE.md excerpt
## Fallback (if MCP build tools are unavailable)
set -o pipefail
xcodebuild -scheme MyApp \
-destination 'platform=iOS Simulator,name=iPhone 16' \
test 2>&1 | xcbeautify --quietClaude declaring victory on a red build is the failure mode this whole setup exists to prevent. A Stop hook that runs the test target makes 'done' mean 'tests pass'.
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "xcodebuild -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 16' test -quiet 2>&1 | tail -20"
}
]
}
]
}
}Related records
Strong evidence gets promoted into the record above.
Anyone made this work for React Native's iOS side? The scheme exists but the Metro dependency confuses the loop.
Partially. Start Metro yourself outside the agent session, then the xcodebuild loop works for native-side changes. Don't let the agent manage Metro's lifecycle — it kills and restarts it at the worst times.
Note for anyone on Xcode 16.3 beta: xcodebuild changed the -quiet output format slightly and the tail -20 in the Stop hook can miss the failure summary. tail -40 is the lazy fix.
Sign in to join the discussion, vote, and verify fixes.
The xcbeautify fallback deserves top billing. Raw xcodebuild output for one failing test was ~4k lines in my project; xcbeautify gets it to 30. That's the difference between the agent reading the failure and the agent compacting it away.