ADE iOS Simulator and Preview Lab
SkillMediaThis skill lets your AI run an iOS or SwiftUI app on a simulator so you can see a change actually working instead of just reading about it. Your AI can launch the app, interact with it, and capture or show what appears on screen.
Available today. Use it from your connected AI after setup.
No other account needed.
After adding it, ask your AI to launch your app on an iOS simulator and show you the change you want to check in action.
Then ask your AI: use the ADE iOS Simulator and Preview Lab skill
What your AI can do with it
- Launch an iOS app on a simulator
- Tap, drag, and type in the running app
- Take screenshots of what is on screen
- Stream the simulator screen while the app runs
- Inspect the elements shown on screen
- Render SwiftUI previews through Preview Lab
What this skill tells your AI
The instructions your AI receives, as published by arul28/ade in apps/desktop/resources/agent-skills/ade-ios-simulator/SKILL.md and read by ahel’s review.
Quick verify
The default path: check support, launch, screenshot, attach proof. Use --socket so CLI actions and the desktop drawer share one session.
ade --socket ios-sim status --text
ade --socket ios-sim apps --text
ade --socket ios-sim launch --target <id> --text
ade --socket ios-sim screenshot --out .ade/tmp/sim.png --text
ade --socket ios-sim proof --caption "Settings row renders" --text
statusis the gate. Ifsupportedis false the runtime is not a Mac — stop and say so. Do not probe further: the commands that touch a real simulator (launch,screenshot,snapshot,inspect,tap,type,drag,select) fail with the macOS-only error, and the rest answer with empty or inert results that look like success.launchbuilds from your lane worktree by default. Pass--project-root <path>only to override.launchruns in the background: Simulator.app is not brought forward and the drawer does not take over the user's screen. Add--foregroundwhen the user asked to watch it.screenshotalways returns afilePathyou can Read.--out <path>picks where it lands; without it the PNG goes to<buildRoot>/.ade/cache/ios-simulator/screenshots/and only the newest 20 survive, so--outanything you need to keep.proofcaptures a screenshot and attaches it to the proof drawer. Use it for reviewer-facing evidence, not for every check.launch --followwaits out a cold build on a real budget (17 min) and prints the full launch summary — build root, device, capabilities, prebuilt warning — when it completes. It announces the wait up front; it does not stream per-step progress.- Release when done:
ade --socket ios-sim shutdown --text.
Interact
launch returns capabilities (canTap / canType / canDrag / canInspect). Check them before acting. Tap, type, and drag are false unless both idb and idb_companion are installed. Snapshots and inspection can still work when xcrun is available even if those idb tools are missing.
ade --socket ios-sim snapshot --text
ade --socket ios-sim tap --x <x> --y <y> --text
ade --socket ios-sim type --value "text" --text
ade --socket ios-sim drag --start-x <x> --start-y <y> --end-x <x> --end-y <y> --text
ade --socket ios-sim select --x <x> --y <y> --text
snapshot returns the screenshot plus selectable elements. select also emits a drawer selection and feeds Preview Lab.
A drag takes 180ms unless you pass --duration-ms. Raise it for a slow scroll; an instant swipe reads as a flick and often does nothing.
Drawer and live view
Only when the user should watch the app run:
ade --socket ios-sim launch --target <id> --foreground --text
ade --socket ios-sim live-start --fps 60 --text
ade --socket ios-sim stream-status --text
ade --socket ios-sim stream-stop --text
live-start and window-start are the same path: ADE mirrors the real Simulator.app window into the drawer. Agent launches do not open the drawer; the user gets a "Simulator running" pill with an Open action instead. Use stream-status to explain a blank live view.
Preview Lab
ade --socket ios-sim preview-status --text
ade --socket ios-sim previews --source <swift-file> --text
ade --socket ios-sim preview-match --source <swift-file> --line <n> --text
ade --socket ios-sim preview-ensure --source <swift-file> --line <n> --text
ade --socket ios-sim preview-current --text
ade --socket ios-sim preview-render --source <swift-file> --index <n> --text
To bridge the current screen into Preview Lab, select a source-backed element (or pass --source / --line), then run preview-current. That one command resolves the best nearby preview, opens/waits for Xcode, renders through Xcode MCP, and brings the Preview drawer forward.
Use preview-match when you only need the target decision without rendering. The selected element's sourceFile / sourceLine bias matching; --label / --component-id only name a missing-preview suggestion. preview-ensure opens this lane's iOS project in Xcode and waits for MCP readiness.
Preview fixtures must not require live sync, keychain, network, push, sockets, or production databases. Add a preview only when no useful nearby one exists.
Ownership and recovery
One chat owns a simulator session at a time. A second launch fails with IOS_SIMULATOR_OWNED_BY_OTHER_SESSION, naming the owning chat and lane and how long ago it claimed. Service errors state the fact and the code only; the CLI adds the command to run next.
- Ownership releases automatically only when the owning chat is deleted or archived. Merely closing or navigating away from it does not free the simulator. Once released, re-run
launch. - If the owner is still live and the user wants it taken over:
ade --socket ios-sim shutdown --force --text, orlaunch --force. - A plain
shutdownfrom a chat that does not own the session is refused withIOS_SIMULATOR_OWNED_BY_OTHER_SESSION. The guard is cooperative, not a lock: it exists so an honest caller cannot end someone else's session by accident. Anything that states the intent gets through —shutdown --force,shutdown --ignore-ownership(the bypass without the hard reset),launch --force,claim --ignore-ownership,attachToChatSessioncalled with a null caller chat id (the guard only runs when the caller names itself, so that form transfers or detaches the session with no flag at all), and equally a caller that passes the owner's own chat session id, whichstatushands to anyone who asks. So the restraint is yours to keep, not the service's to enforce: don't evict another chat on your own initiative, ask. Waiting only pays off if the owner is actively finishing; an idle chat holds the session indefinitely, so don't sit in a retry loop. claim --lane <lane-id>attaches an already-running session to a lane. It is not a step in a normal launch. It is also an ownership call, not just a label: the CLI sends your own$ADE_CHAT_SESSION_IDwith it, so claiming a session another chat owns is a takeover and is refused withIOS_SIMULATOR_OWNED_BY_OTHER_SESSIONunless you add--ignore-ownership(--forceis the same bypass; neither tears the session down, unlikeshutdown --force). Ask before you do.
Gotchas
IOS_SIMULATOR_TARGET_ROOT_MISMATCHmeans the target id came from a different build root than the one now resolved. Re-runade --socket ios-sim apps --textand use a fresh id.IOS_SIMULATOR_NO_BUILDABLE_TARGETmeans nothing buildable resolved under the root and you named no target, so the only candidates were preinstalled apps that would run stale code. The message lists the buildable targets when there are any. Pass--target-id/--bundle-idonly if you deliberately want the installed app.IOS_SIMULATOR_LAUNCH_IN_PROGRESSmeans a launch is already running; the message carries itslaunchId. Wait for it — don't retry in a loop.shutdown --forceis the escape hatch if it is genuinely wedged: it releases the launch lock as well as the session.IOS_SIMULATOR_LANE_NOT_RESOLVEDmeans the lane you named has no worktree on this machine. It is a hard failure on purpose — the alternative is silently building the primary checkout and reporting someone else's code as verified. Pass--project-rootwith the checkout you want.screenshot --outresolves relative paths against the build root — for a lane launch that is your lane worktree, not the primary checkout. The path must stay inside that root;../tails and absolute paths elsewhere are rejected. The returnedfilePathis absolute either way, so Read that rather than reconstructing the path.appsdrives project/scheme detection. If it does not find your app, re-run it and report the selected project, scheme, and build output — do not work around it with symlink projects, fake schemes, or repo-layout shims.preview-current/preview-matchreturningno-contextmeans nothing on screen is source-backed. Runsnapshot,selecta source-backed element, or pass--source/--line.- On a remote Mac runtime, control and screenshots work; the drawer live view does not — it captures a local desktop window.
- Tap/drag/type failing usually means
idbandidb_companionare missing. Inspection and snapshots can still work withxcrunalone.
Signals
- GitHub stars
- 104
- Forks
- 12
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
ade-ios-simulator- Source
- github.com/arul28/ade