Install
openclaw skills install skills-sh:limrun-inc/skills/limrun-maestro-testingMaestro on Limrun iOS Run the stock upstream Maestro CLI against a remote Limrun iOS simulator. lim ios maestro wires maestro test to the instance transparently: it installs and launches the Maestro XCTest runner on the simulator when needed, then routes the driver traffic to…
openclaw skills install skills-sh:limrun-inc/skills/limrun-maestro-testingRun the stock upstream Maestro CLI against a remote Limrun iOS simulator.
lim ios maestro wires maestro test to the instance transparently: it
installs and launches the Maestro XCTest runner on the simulator when needed,
then routes the driver traffic to it. No fork of Maestro, no local simulator,
no local Xcode.
lim CLI 0.22.0 or newer: npm install --global lim. Auth is lim login or
LIM_API_KEY (it may be set outside the project, so don't ask for it just
because it's missing from .env or the shell).curl -fsSL https://get.maestro.mobile.dev | bash.
Maestro needs Java 17+ (java -version to check). Both Maestro 2.5.x and
2.6+ work; lim adapts to the installed version automatically.The CLI is the source of truth: if a flag errors or you need one not shown
here, check lim ios <subcommand> --help instead of guessing.
Before touching the user's app, prove the whole pipeline with a flow against the built-in Settings app; it needs no app install, tunnel, or build:
ID=$(lim ios create --install-asset appstore/maestro-ios-runner-2.5.1.tar.gz \
--no-open --quiet --json | jq -r .metadata.id)
cat > hello-flow.yaml <<'EOF'
appId: com.apple.Preferences
---
- launchApp
- assertVisible: General
- takeScreenshot: settings-check
EOF
lim ios maestro --id "$ID" test hello-flow.yaml
All three steps reporting COMPLETED means Maestro, the runner, and the
remote wiring all work; anything failing after this point is about the app or
the flow, not the setup.
lim ios maestro test flow.yaml
lim ios maestro test flows/
lim ios maestro --id <ios-id> test flow.yaml
Without --id this targets the most recently created iOS instance in the
current workspace (workspaces follow the git repo or worktree you run from);
pass --id <ios-id> (before test) in scripts, agents, or when running from
a different directory. The first run on an instance takes a few extra seconds
to launch the runner (plus the install when it wasn't preinstalled); later
runs skip that. Extra Maestro flags go after
--:
lim ios maestro -- test flow.yaml --include-tags smoke --test-output-dir artifacts
Do not pass --platform, --device, --udid, --no-reinstall-driver, or
--driver-host-port; lim sets those itself and rejects duplicates.
Real Maestro exit codes and reports are preserved, so CI wiring works as with
local Maestro.
Any running iOS instance works; the runner is installed on first use. Creating the instance with the runner preinstalled skips that step:
lim ios create --install-asset appstore/maestro-ios-runner-2.5.1.tar.gz --no-open
--no-open skips opening the stream URL in a browser (important on headless
and CI machines). The runner asset name above is the only published one and it
is version-agnostic: the same runner serves Maestro 2.5.x through 2.7.x, so do
not look for an asset matching your Maestro version.
Install the app under test as usual (lim ios create --install app.ipa,
lim ios install-app, or a build skill), then reference its bundle id via
appId: in the flow. For Expo Go testing, also preinstall
appstore/Expo-Go-54.0.6.tar.gz and open the project URL with openLink
(env vars must be prefixed MAESTRO_ to be visible in flows):
MAESTRO_EXPO_URL='exp://<tunnel-host>' lim ios maestro test flow.yaml
Expo Go is the quickest path, but a dev-client build works too. launchApp
lands on the dev launcher rather than your app, so open the dev-client URL
instead: - stopApp followed by
- openLink: <scheme>://expo-development-client/?url=<url-encoded-metro-url>.
Use limrun-expo-development for building the dev client, starting Metro, and
deriving that URL.
startRecording/stopRecording YAML commands are not supported (the
simulator is remote). Record around the run instead: lim ios record start --id <ios-id> returns immediately (recording happens on the instance), and
after the flow lim ios record stop --id <ios-id> -o video.mp4 downloads
the video to the local path.takeScreenshot works and saves the PNG locally into the working
directory (or --test-output-dir), like stock Maestro.addMedia and flow commands that reference local simulator file paths are
not supported.runScript/evalScript must use https:// URLs. Plain
http:// calls are refused (except to the driver itself), because Maestro's
plain-HTTP traffic is routed through a local bridge that only forwards to
the remote simulator.- stopApp before openLink/launchApp; deep links
can be dropped by an app that is mid-foreground, and stale screens fail
early assertions.extendedWaitUntil with a generous timeout for
first app load.lim ios element-tree before writing the
selector instead of guessing from what the screen shows.Running maestro <version> against <ios-id>... then
Running on Limrun iPhone - iOS ...: the driver is connected end to end.Launching the Maestro runner...: first use on this instance.
Installing the Maestro runner... additionally appears only when the
instance was created without the runner asset. Subsequent runs skip both.WARNING lines (reflection, native
access) on every run; they are benign upstream noise, not Limrun errors.lim ios element-tree --id <ios-id> shows the live
screen when debugging selectors.Delete the instance when done: lim ios delete <ios-id> (--id is not valid
for delete). The wiring lim ios maestro starts is torn down when the command
exits.
96e256e536df