with one click
test-loop
// Build, launch, and test an iOS Swift app on the simulator in an automated loop. Inspects the UI, finds issues, fixes the Swift code, rebuilds, and retests until the app works correctly.
// Build, launch, and test an iOS Swift app on the simulator in an automated loop. Inspects the UI, finds issues, fixes the Swift code, rebuilds, and retests until the app works correctly.
| name | test-loop |
| description | Build, launch, and test an iOS Swift app on the simulator in an automated loop. Inspects the UI, finds issues, fixes the Swift code, rebuilds, and retests until the app works correctly. |
| disable-model-invocation | true |
| allowed-tools | Bash(*) Read Write Edit Glob Grep mcp__iosef__describe mcp__iosef__tap mcp__iosef__type mcp__iosef__swipe mcp__iosef__view mcp__iosef__find mcp__iosef__exists mcp__iosef__text mcp__iosef__wait mcp__iosef__install_app mcp__iosef__launch_app mcp__iosef__get_booted_sim_id mcp__iosef__log_show |
| argument-hint | <build-command> [test-description] |
Build an iOS app, launch it on the simulator, inspect and test the UI, fix issues, and repeat until it works.
First argument: build command (required). Remaining text: test description (optional).
If no test description, do a general inspection: build, launch, screenshot, read the accessibility tree, report what you see.
If the build command is a custom script, read it first to understand what it handles (compile only? install/launch too?). This determines which later steps you can skip.
Run the build command. On failure, don't dump the full log โ scan for lines containing error: and the few lines around them. Read the referenced source file, fix the issue, and rebuild. Common patterns:
CODE_SIGNING_ALLOWED=NO in the build command for simulator buildsxcodebuild -resolvePackageDependencies)Skip if the build script already installed and launched the app.
Locate the built .app bundle:
find ~/Library/Developer/Xcode/DerivedData -name "*.app" -path "*/Debug-iphonesimulator/*" -newer /tmp/.build_start_marker -maxdepth 6 2>/dev/null
(Create /tmp/.build_start_marker with touch before the first build to filter stale bundles.)find . build/ output/ -name "*.app" -maxdepth 4 2>/dev/nullIf multiple results, pick the newest by modification time.
Skip if the build script already handled this.
xcrun simctl boot "iPhone 16" 2>/dev/null || true
open -a Simulator
Extract the bundle ID from the app:
/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" /path/to/Built.app/Info.plist
Install with mcp__iosef__install_app, then launch with mcp__iosef__launch_app (set terminate_running: true to ensure a clean start).
Wait for the app to render. After launch, pause 2-3 seconds before inspecting โ SwiftUI apps often show a blank frame initially while the view hierarchy loads. If the first screenshot is blank or shows only a launch screen, wait another 2 seconds and retry once before treating it as a bug.
Take a screenshot (mcp__iosef__view) and read the accessibility tree (mcp__iosef__describe).
If there's a test description: plan the interaction sequence, then execute step by step using iosef tools โ tap, type, swipe, find, wait, exists. Screenshot after each significant action so you can trace what happened if something goes wrong.
If no test description: do a general walkthrough โ screenshot the initial state, tap the main interactive elements, verify the app responds sensibly, and report what you find.
Handling permission dialogs: iOS may show system alerts (location, notifications, camera, etc.) that block your app's UI. If mcp__iosef__describe shows a system alert, either tap "Allow" / "Don't Allow" as appropriate for the test, or dismiss it. Don't mistake a permission dialog for a bug in the app.
mcp__iosef__log_show for crash logs or assertion failures โ filter by the app's bundle ID or process name to cut through noise..accessibilityIdentifier("descriptive-id") to key views โ this is a legitimate fix, not a refactor.Iteration limits: You have up to 5 build-test-fix cycles. If you're not making progress by iteration 3, step back and reconsider โ are you fixing symptoms instead of the root cause? On iteration 5, if the issue persists, stop and report to the user: what you've tried, what the current state is, and your best theory on what's wrong.
Take a final screenshot as evidence. Report: