Munyon-Canyon

ios-simslim-fast-qa

Provides a fast iOS simulator QA loop using SimSlim (RAM-thin simulators) and MobAI automation for smoke tests, app builds, and agent-driven tap-through testing. Use for quick iOS QA after features, not full regression or multi-sim scale.

Munyon-Canyon 0 Updated 2w ago
GitHub

Install

npx skillscat add munyon-canyon/monaco/ios-simslim-fast-qa

Install via the SkillsCat registry.

About this skill

Provides a fast iOS simulator QA loop using SimSlim (RAM-thin simulators) and MobAI automation for smoke tests, app builds, and agent-driven tap-through testing. Use for quick iOS QA after features, not full regression or multi-sim scale.

SKILL.md

iOS SimSlim Fast QA

Repo-agnostic fast smoke loop: one slim simulator, one MobAI claim, tight iterate cycle.

Layer Job Not its job
SimSlim Disable unused sim daemons; verify/doctor Tap UI, build, screenshot
MobAI + mobai-mcp claim, start_bridge, execute_dsl, install_app Compile Swift; slim RAM
xcodebuild / MobileBuildMCP Build, install, optional snapshot-ui Cut sim RAM or manage fleet
Agent discover → profile → build → drive → fix Stock sim forever; drive another lane's sim

Default: 1 sim (~0.9 GB slim vs ~4 GB stock). Rare: 2–3 sims (clone gold after slim-once). No 12-sim farm.


When to use

  • User asks for fast iOS QA, sim smoke, agent tap-through, SimSlim, or MobAI.
  • Day-1 smoke after a feature: launch, primary nav, one critical path — not full regression.
  • Unit tests first (no sim). Expand tiers only after smoke is green.

Skip this skill for web automation (not available on iOS sim). Parallel agents in separate worktrees each run this loop on their own lane simulator: scripted taps go through the XCUITest journeys (scripts/qa/journey.py), ad-hoc taps through an MCP that takes a simulator id per call, with the lane UDID from scripts/gold-sim-udid.sh.


Machine setup (once)

SimSlim

brew install mobai-app/tap/simslim

MobAI desktop

Run MobAI desktop app. API at 127.0.0.1:8686.

MCP (user or repo .cursor/mcp.json)

{
  "mcpServers": {
    "mobai": {
      "command": "npx",
      "args": ["-y", "mobai-mcp"]
    }
  }
}

Add MobileBuildMCP only if the repo already wires it — optional, not required.

Gold simulator (once per machine, slow)

Pick one iOS 18.5+ runtime (slim persist minimum). Boot it, note UDID:

xcrun simctl list devices available

Slim it once with base profile:

simslim on <GOLD_UDID> --profile ci/profiles/base-slim.json --json

Keep gold booted between agent sessions when possible. For 2–3 sims: clone gold after slim-once (clone inherits slim + apps).

Monaco: UDID is per machine. Never copy a UUID from this repo or another laptop. After slim-once, export SIMSLIM_UDID=<udid> (shell rc and/or plain .env). In the primary checkout scripts/gold-sim-udid.sh prints it or exits 1. In a linked worktree it prints the worktree's own lane simulator, Monaco <lane>, created on first use (docs/how-to/local-simulator.md#parallel-agents-one-simulator-per-worktree). just build mobile / just reset mobile / ./scripts/ios-sim use scripts/resolve-ios-sim.sh (stock fallback in primary). scripts/stop-mobile.sh uninstalls com.monaco.app on the lane's sims in a worktree, and on every sim except live lanes' in the primary checkout. MobileBuildMCP: --simulator-id "$(scripts/gold-sim-udid.sh)". Stock Simulator without slim: README Without slim sim.

Every session before driving UI:

simslim verify <UDID> --profile ci/profiles/<profile>.json \
  || simslim on <UDID> --profile ci/profiles/<profile>.json
simslim doctor --requires ci/profiles/<profile>.json

except in profile = KEEP that daemon category ON (less slim, more capability).


Repo discovery

Run before first build. Works on any Swift/UIKit/SwiftUI app.

Target How Why
Scheme xcodebuild -list -json — pick app scheme, not test-only Build target
Bundle ID xcodebuild -showBuildSettings -scheme <SCHEME> | grep PRODUCT_BUNDLE_IDENTIFIER or Info.plist open_app / install_app
Deploy target IPHONEOS_DEPLOYMENT_TARGET in pbxproj or build settings Must fit sim runtime; slim persist needs iOS 18.5+
Entitlements *.entitlements, Signing & Capabilities in pbxproj Profile except/keep map
Info.plist *UsageDescription*, URL schemes, SKAdNetwork Photos, camera, location, tracking
Backends README, .env.example, localhost URLs in code Start sidecar before UI tier
xcodebuild -list -json
xcodebuild -scheme <SCHEME> -showBuildSettings 2>/dev/null | grep -E 'PRODUCT_BUNDLE_IDENTIFIER|IPHONEOS_DEPLOYMENT_TARGET'

Capability → profile map

Start from base-slim (maximum cut). Add except / keep only for QA paths that touch that subsystem.

Rule: except: ["photos"] means keep the photos category ON.

Signal in repo Profile tweak Category
SwiftUI tabs only, no system pickers except: [] Full slim
PHPicker / Photos / camera except: ["photos"] photos
Push notifications QA keep: ["apsd"] or except: ["push"] push
StoreKit / IAP keep: ["storekitd"] storekit
Universal links / handoff keep: ["swcd"] links
HealthKit except: ["health"] health
Location / maps except: ["location"] location
iCloud / CloudKit except: ["icloud"] icloud

Example ci/profiles/base-slim.json (keeps siri: slimmed away, the keyboard's dictation handler spins the app's main thread):

{
  "except": ["siri"]
}

Example ci/profiles/photos-qa.json:

{
  "except": ["photos"]
}

Re-pick profile when entitlements or smoke scope changes.


Inner loop

discover → profile → verify||on → build → install → claim → start_bridge → drive → report → (fix) → loop

Checklist (copy per iteration)

- [ ] Discover scheme, bundle ID, entitlements, deploy target
- [ ] Pick slim profile; verify || on; doctor
- [ ] Build .app
- [ ] Install on claimed sim UDID
- [ ] MobAI: claim → start_bridge → open_app → execute_dsl
- [ ] On fail: save_screenshot + ui_tree; fix code; loop
- [ ] release_device when done

Build + install (xcodebuild — always available)

xcodebuild -scheme <SCHEME> \
  -destination 'platform=iOS Simulator,id=<UDID>' \
  -derivedDataPath /tmp/dd-<SCHEME> \
  build

xcrun simctl install <UDID> \
  /tmp/dd-<SCHEME>/Build/Products/Debug-iphonesimulator/<App>.app

Build + install (MobileBuildMCP — if present)

Use same UDID MobAI will claim. build-and-run, snapshot-ui, screenshot — optional shortcuts, not assumed.


MobAI protocol

Read first: fetch MCP resource mobai://reference/device-automation (and testing docs if driving flows).

Step Action
Reserve list_devices → claim_device(holder=<task-id>)
Bridge start_bridge — iOS cold start ~60s; wait for ready
Fresh launch open_app with bundleId, fresh=true
Drive execute_dsl batch or replay mobai/flows/*.mob if repo has them
Fail save_screenshot + ui_tree; debug_attach if crash
Done release_device

Concurrency: MobAI Free = 1 concurrent device — enough for one agent's loop. Parallel agents in separate worktrees do not share MobAI: each drives its own lane simulator with the XCUITest journeys or an MCP that takes a simulator id per call.

Example DSL sketch (adapt to actual MobAI schema):

{
  "steps": [
    { "action": "tap", "label": "Home" },
    { "action": "wait", "ms": 500 },
    { "action": "assert_visible", "label": "Settings" }
  ]
}

Day-1 smoke (not full suite)

Three checks on the one slim sim:

Check Pass
Launch App opens, splash dismisses, no crash
Primary nav Tabs / sidebar / root flows reachable
One critical path Single highest-risk user flow end-to-end

Write or replay flows under mobai/flows/*.mob only when the repo already uses them — do not require per-repo artifacts to run this skill.


Per-repo artifacts (optional)

Path Purpose
ci/profiles/*.json Capability-specific slim profiles
.cursor/mcp.json mobai-mcp (+ optional MobileBuildMCP)
mobai/flows/*.mob Replayable smokes for this app
.cursor/skills/<app>-qa/SKILL.md App-specific scheme, bundle, backends, smoke tiers

Skill is global. Per-repo files speed repeat runs; absence is fine — discover each time.


Gotchas

Issue Mitigation
simslim erase / recreate sim Wipes slim; re-run simslim on on gold
Runtime below iOS 18.5 Slim does not persist across reboot
start_bridge cold Budget ~60s before first tap
No launch args for test state Seed data via backend or debug menu; document blocker
Missing accessibility ids Add ids or use label/text taps; fragile
PHPicker / system pickers Use except: ["photos"]; PhotosPicker hard to automate
Backend not running Start sidecar before UI smoke
Web automation on iOS sim Not supported — native MobAI DSL only

Agent output format

After a smoke pass, report:

## iOS fast QA — <scheme>

- Sim: <name> (<UDID>), profile: <profile>.json
- Build: pass | fail
- Smoke: launch / nav / critical path — pass | fail | blocked
- Blockers: [list or none]
- Screenshot: [MobAI save path or upload if user needs link]

On fail: screenshot + ui_tree summary, one concrete fix, then re-loop — do not claim a second sim on Free tier.