← LimrunCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Limrun
Snapshot Sep 30, 2026 · 23:08 UTC · version 1.1.0
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"name": "limrun-maestro-testing",
"description": "Run Maestro YAML flows against a Limrun cloud iOS simulator with `lim ios maestro`, from any environment (Linux, Windows, macOS, VM, container). Use when the user wants to run, write, or debug Maestro flows or `maestro test` on iOS, migrate an existing Maestro suite to remote simulators, or asks for UI testing with Maestro. iOS simulators only today. For Detox suites use limrun-detox-testing; for driving the simulator without a test framework use limrun-ios-simulator.",
"included_files": [],
"skill_md_contents": "---\nname: limrun-maestro-testing\ndescription: \"Run Maestro YAML flows against a Limrun cloud iOS simulator with `lim ios maestro`, from any environment (Linux, Windows, macOS, VM, container). Use when the user wants to run, write, or debug Maestro flows or `maestro test` on iOS, migrate an existing Maestro suite to remote simulators, or asks for UI testing with Maestro. iOS simulators only today. For Detox suites use limrun-detox-testing; for driving the simulator without a test framework use limrun-ios-simulator.\"\nuser-invocable: true\n---\n\n# Maestro on Limrun iOS\n\nRun the stock upstream Maestro CLI against a remote Limrun iOS simulator.\n`lim ios maestro` wires `maestro test` to the instance transparently: it\ninstalls and launches the Maestro XCTest runner on the simulator when needed,\nthen routes the driver traffic to it. No fork of Maestro, no local simulator,\nno local Xcode.\n\n## Prerequisites\n\n- `lim` CLI 0.22.0 or newer: `npm install --global lim`. Auth is `lim login` or\n `LIM_API_KEY` (it may be set outside the project, so don't ask for it just\n because it's missing from `.env` or the shell).\n- Maestro CLI on PATH: `curl -fsSL https://get.maestro.mobile.dev | bash`.\n Maestro needs Java 17+ (`java -version` to check). Both Maestro 2.5.x and\n 2.6+ work; `lim` adapts to the installed version automatically.\n\nThe CLI is the source of truth: if a flag errors or you need one not shown\nhere, check `lim ios <subcommand> --help` instead of guessing.\n\n## Verify the setup\n\nBefore touching the user's app, prove the whole pipeline with a flow against\nthe built-in Settings app; it needs no app install, tunnel, or build:\n\n```bash\nID=$(lim ios create --install-asset appstore/maestro-ios-runner-2.5.1.tar.gz \\\n --no-open --quiet --json | jq -r .metadata.id)\n\ncat > hello-flow.yaml <<'EOF'\nappId: com.apple.Preferences\n---\n- launchApp\n- assertVisible: General\n- takeScreenshot: settings-check\nEOF\n\nlim ios maestro --id \"$ID\" test hello-flow.yaml\n```\n\nAll three steps reporting `COMPLETED` means Maestro, the runner, and the\nremote wiring all work; anything failing after this point is about the app or\nthe flow, not the setup.\n\n## Run a flow\n\n```bash\nlim ios maestro test flow.yaml\nlim ios maestro test flows/\nlim ios maestro --id <ios-id> test flow.yaml\n```\n\nWithout `--id` this targets the most recently created iOS instance in the\ncurrent workspace (workspaces follow the git repo or worktree you run from);\npass `--id <ios-id>` (before `test`) in scripts, agents, or when running from\na different directory. The first run on an instance takes a few extra seconds\nto launch the runner (plus the install when it wasn't preinstalled); later\nruns skip that. Extra Maestro flags go after\n`--`:\n\n```bash\nlim ios maestro -- test flow.yaml --include-tags smoke --test-output-dir artifacts\n```\n\nDo not pass `--platform`, `--device`, `--udid`, `--no-reinstall-driver`, or\n`--driver-host-port`; `lim` sets those itself and rejects duplicates.\nReal Maestro exit codes and reports are preserved, so CI wiring works as with\nlocal Maestro.\n\n## Instance setup\n\nAny running iOS instance works; the runner is installed on first use. Creating\nthe instance with the runner preinstalled skips that step:\n\n```bash\nlim ios create --install-asset appstore/maestro-ios-runner-2.5.1.tar.gz --no-open\n```\n\n`--no-open` skips opening the stream URL in a browser (important on headless\nand CI machines). The runner asset name above is the only published one and it\nis version-agnostic: the same runner serves Maestro 2.5.x through 2.7.x, so do\nnot look for an asset matching your Maestro version.\n\nInstall the app under test as usual (`lim ios create --install app.ipa`,\n`lim ios install-app`, or a build skill), then reference its bundle id via\n`appId:` in the flow. For Expo Go testing, also preinstall\n`appstore/Expo-Go-54.0.6.tar.gz` and open the project URL with `openLink`\n(env vars must be prefixed `MAESTRO_` to be visible in flows):\n\n```bash\nMAESTRO_EXPO_URL='exp://<tunnel-host>' lim ios maestro test flow.yaml\n```\n\n## Expo dev-client builds\n\nExpo Go is the quickest path, but a dev-client build works too. `launchApp`\nlands on the dev launcher rather than your app, so open the dev-client URL\ninstead: `- stopApp` followed by\n`- openLink: <scheme>://expo-development-client/?url=<url-encoded-metro-url>`.\nUse `limrun-expo-development` for building the dev client, starting Metro, and\nderiving that URL.\n\n## Flow gotchas on Limrun\n\n- `startRecording`/`stopRecording` YAML commands are not supported (the\n simulator is remote). Record around the run instead: `lim ios record start\n --id <ios-id>` returns immediately (recording happens on the instance), and\n after the flow `lim ios record stop --id <ios-id> -o video.mp4` downloads\n the video to the local path.\n- `takeScreenshot` works and saves the PNG locally into the working\n directory (or `--test-output-dir`), like stock Maestro.\n- `addMedia` and flow commands that reference local simulator file paths are\n not supported.\n- HTTP calls from `runScript`/`evalScript` must use `https://` URLs. Plain\n `http://` calls are refused (except to the driver itself), because Maestro's\n plain-HTTP traffic is routed through a local bridge that only forwards to\n the remote simulator.\n- When a flow re-runs against an app that is already open (for example Expo\n Go), start it with `- stopApp` before `openLink`/`launchApp`; deep links\n can be dropped by an app that is mid-foreground, and stale screens fail\n early assertions.\n- Fleet variance: anchor assertions on stable accessibility identifiers and\n text, not on timing. Use `extendedWaitUntil` with a generous timeout for\n first app load.\n- Text selectors match the element's accessibility label, and on iOS a label\n often folds in sibling content (icon names, adjacent text) or non-breaking\n spaces. Read the exact label with `lim ios element-tree` before writing the\n selector instead of guessing from what the screen shows.\n\n## Validation signals\n\n- `Running maestro <version> against <ios-id>...` then\n `Running on Limrun iPhone - iOS ...`: the driver is connected end to end.\n- `Launching the Maestro runner...`: first use on this instance.\n `Installing the Maestro runner...` additionally appears only when the\n instance was created without the runner asset. Subsequent runs skip both.\n- Maestro itself prints several JDK `WARNING` lines (reflection, native\n access) on every run; they are benign upstream noise, not Limrun errors.\n- Flow failures print Maestro's own debug output directory with screenshots\n and the UI hierarchy; `lim ios element-tree --id <ios-id>` shows the live\n screen when debugging selectors.\n\n## Cleanup\n\nDelete the instance when done: `lim ios delete <ios-id>` (`--id` is not valid\nfor delete). The wiring `lim ios maestro` starts is torn down when the command\nexits.\n"
}SHA-256: c8ac52733a157a452d3cc8f76e251c7ed26e96e86c4e5f1aabe26351a12591f2