Skip to main content

engineering

Reproduce iOS bugs in 60 seconds with Claude

Maurice Carrier ·

Your QA filed a P1 sign-in crash on iPhone 17, iOS 26.3. You’re on a M2 MacBook running a 17 Pro sim. You tap through the flow. It doesn’t crash. You read the stack trace again. You try a fresh boot. Nothing.

This is the part of the job that nobody talks about: the bug isn’t hard to fix, it’s hard to see. Most of the hour is spent re-walking somebody else’s footsteps until the failure shows up on your screen.

SimDrive exists for that hour.

The flow

You install SimDrive, register the MCP server with Claude Code (or Cursor, or Continue — same server, same config), then paste the ticket into the chat. Claude opens your simulator, walks the reported steps, observes the screen with a vision model, and either reproduces the crash or tells you why it can’t. If it reproduces, you get back: the exact sequence, a screenshot at the failure frame, the device logs around the crash, and a replay file you can re-run on every PR after you ship the fix.

Terminal window
pip install simdrive
simdrive trial start --email you@example.com

That’s the whole install. The trial unlocks every tool for 14 days. After that, simdrive auth <key> flips you to Pro for $29/mo.

Wiring Claude Code

Add SimDrive to your MCP config. In Claude Code this lives at ~/.claude/mcp.json:

{
"mcpServers": {
"simdrive": {
"command": "simdrive",
"args": ["mcp", "serve"]
}
}
}

Restart Claude Code. The 32 SimDrive tools show up under the MCP menu — ios_observe, ios_act, ios_record_start, ios_replay, ios_device_select, ios_perf_capture, and so on.

Reproducing the ticket

Open the project. Paste the ticket. The prompt looks like this:

QA filed Linear ticket SIM-1421:
"Sign-in crashes on iPhone 17 (iOS 26.3) when the user submits
an empty password field. Repro: open app → tap Sign In → leave
password blank → tap Continue → crash."
Reproduce this on the iPhone 17 sim against the dev scheme.
Capture device logs at the crash frame. Save a replay.

Claude calls ios_device_select to target the iPhone 17 sim. It calls ios_observe to read the current screen. It calls ios_act to tap Sign In, types an email, leaves the password blank, taps Continue. If the app crashes, ios_observe returns the springboard with the previous app’s icon dimmed — Claude recognizes it, calls ios_device_logs --since 30s --filter <bundle-id>, and surfaces the stack trace.

You get back something like:

Reproduced SIM-1421 on iPhone 17 sim (iOS 26.3, build 23B5044l).
Crash at AuthViewController.swift:142 — force-unwrap on
passwordField.text when the field is empty.
Steps that triggered it (replay saved to .simdrive/replays/sim-1421.json):
1. Launch com.example.app
2. Tap "Sign In" (accessibility-id sign-in-button)
3. Type "user@example.com" into email field
4. Tap "Continue" without entering a password
5. Crash within 200ms
Device log excerpt:
AuthViewController.swift:142: Fatal error: Unexpectedly found nil
while unwrapping an Optional value
Replay available at .simdrive/replays/sim-1421.json — re-run with
`simdrive replay run .simdrive/replays/sim-1421.json` after the fix.

Total elapsed time on a warm sim: roughly 45 to 90 seconds depending on app launch.

Fix → validate

You fix the force-unwrap. Push a branch. Before opening the PR, you re-run the replay:

Terminal window
simdrive replay run .simdrive/replays/sim-1421.json

The replay walks the same five steps against your fixed build. If it passes — meaning the app stays foregrounded and the SSIM at the final frame matches the expected “validation error shown” screen — you get a green exit code and a fingerprint to attach to the PR. If it doesn’t, the replay tells you which step diverged and shows you both frames side by side.

This is the part that converts a one-time bug repro into something durable. Every replay you save becomes a CI artifact. You can run the whole replay library on every PR for $0 of AI cost — the replay path doesn’t call the VLM, it diffs frames against the recorded baseline. A dedicated GitHub Action wrapper is on the W3 roadmap; until then, the simdrive CLI runs cleanly inside any macos-14-or-newer runner.

A real example you can fork

We keep a working demo app at github.com/SyncTek-LLC/simdrive-demo-app. It’s an intentionally-buggy iOS app with three real bugs planted in it — a force-unwrap on empty input, a navigation stack leak, and a memory spike on the photo picker — plus the Claude prompts and saved replays for reproducing each one. Clone it, run pip install simdrive, point Claude at the prompts directory, and watch it work.

What ships in 1.0.0b1

This is what you actually get on pip install simdrive today:

  • 32 MCP tools across observe, act, record, replay, journey, device, perf, doctor
  • Simulator support (iPhone 15/16/17, iOS 17/18/26) and real-device support via WDA
  • Vision-first observation — no need to maintain accessibility-id selectors for every screen
  • Trial CLI (simdrive trial start --email <addr>) and auth (simdrive auth <key>)
  • Replay runner with SSIM-based parity gates and JSON state contracts
  • Journey scripts (multi-step recorded flows) with assertion checkpoints

What ships isn’t experimental. It’s what we use ourselves on PRs in this repo and in the demo app.

Try it

Terminal window
pip install simdrive
simdrive trial start --email you@example.com
simdrive doctor

simdrive doctor checks your Xcode, sim runtime, and MCP wiring. If it’s green, you’re a paste away from your first repro.

Pricing lives at simdrive.dev/pricing. Pro is $29/mo for a single dev. Team is $99/seat/mo with a 3-seat minimum, shared replay registry, SSO, and audit logs. Enterprise starts at $50K/yr with on-prem, RBAC, and SAML.

The trial is 14 days. No card required to start. The 60-second number is a real measurement against the demo app on a warm sim — your first repro on a cold project will take a couple of minutes longer while Claude reads your codebase and finds the entry point. After that, it stays in the 60-second range.