Earn 14 free days when your bug report or suggestion is accepted — how it works

macOS + iOS Simulator setup

This is the toolchain checklist for the strongest CodeLoop mobile path: a macOS host driving the iOS Simulator (and optionally the Android emulator from the same machine). Once it is in place, a full codeloop_verify builds the app, boots a simulator, launches the app, drives it, and captures screenshots + video + logs with no manual steps.

One command tells you what is missing: npx codeloop doctor checks every item on this page (Xcode, simulator runtimes, CocoaPods, Java, Maestro, idb, adb, AVDs) and prints the exact install command for anything absent.

1. Xcode + iOS Simulator runtime

# Full Xcode from the Mac App Store (Command Line Tools alone don't ship simctl)
xcode-select --install
sudo xcodebuild -license accept

# Download an iOS Simulator runtime (Xcode 15+)
xcodebuild -downloadPlatform iOS

# Confirm: at least one iOS runtime and one iPhone device should appear
xcrun simctl list runtimes
xcrun simctl list devices

A fresh Xcode install can have zeroiOS runtimes downloaded — simulators then fail to boot with “no runtime available”. codeloop doctor flags this case explicitly.

2. CocoaPods (Flutter plugins / native pods)

brew install cocoapods
# Then, inside a Flutter project that uses plugins:
cd ios && pod install

Any project with an ios/Podfile needs CocoaPods or the build fails at the pod-integration phase. CodeLoop builds Flutter iOS apps through flutter build ios --simulator --no-codesign (the Flutter toolchain handles pod integration), so a working pod binary is all you need.

3. Maestro (label-based mobile driving) + Java

# Maestro is a JVM CLI — install Java first
brew install --cask temurin

curl -Ls "https://get.maestro.mobile.dev" | bash

Maestro is CodeLoop’s primary mobile interaction engine: the journey generates a Maestro flow from your app’s real labels and drives it. Without Maestro, CodeLoop falls back to the coordinate engine (real CGEvent input into the Simulator window) — it works, but label-based driving is more reliable on labeled UIs. The first iOS run installs Maestro’s XCTest driver and can take a couple of minutes; CodeLoop raises the driver-startup timeout automatically.

4. Optional: idb (precision input + accessibility tree)

brew tap facebook/fb
brew install idb-companion
pipx install fb-idb   # or: pip install fb-idb

When idb is on PATH, CodeLoop uses it for HID-precise taps/swipes that need no window focus, and unlocks real get_texton iOS via the accessibility tree. Auto-detected — never required.

5. macOS permissions (the step everyone forgets)

CodeLoop’s capture and input paths use macOS system APIs that require one-time consent. Grant both to the app that hosts the MCP server process — that is Cursor (or your terminal app when using Claude Code from a terminal):

  • Screen Recording— System Settings → Privacy & Security → Screen Recording. Without it, screenshots and ffmpeg/avfoundation video come out black.
  • Accessibility— System Settings → Privacy & Security → Accessibility. Without it, CGEvent clicks and keystrokes (desktop apps and the Simulator fallback path) are silently discarded by macOS.

macOS prompts on first use; if a capture ever comes back black or a click lands nowhere, these two panes are the first place to look. Restart Cursor after granting.

6. Wire it into the project

npx codeloop init
npx codeloop doctor   # everything green?

Useful .codeloop/config.jsonkeys for this host (all optional — see the e2e reference):

{
  "e2e": {
    "ios_device": "iPhone 16 Pro",        // pin a simulator
    "platforms": ["ios", "android"],      // drive BOTH apps in one verify
    "launch_stall_seconds": 180,           // raise for quiet toolchains
    "ios_scheme": "MyApp-Staging"          // native multi-scheme workspaces
  }
}

From here, a plain codeloop_verify(or “verify the app” to your agent) runs the full loop. To test the Android app on the same Mac: codeloop_run_journey with target_type: "android_emulator", or set e2e.platformsas above — the gate then requires driven evidence from both platforms.

Physical devices

Physical Android phones work over USB (adb). Physical iPhones are detected and get a best-effort flutter runlaunch, but Apple provides no supported CLI path for screenshots/video/input on hardware — visual evidence requires the Simulator. The compatibility matrix spells out every boundary.

Next steps