Commands
This page summarizes the primary command groups.
For persistent defaults and project-scoped CLI settings, see Configuration.
For agent workflow guidance that is matched to the installed CLI, run:
Skills are recommended for auto-routing when your agent runtime supports them, but they are not required. The CLI help topics are the version-matched operating contract.
Navigation
bootensures the selected target is ready without launching an app.bootrequires either an active session or an explicit device selector.--platform appleis an alias for the Apple automation backend (ios,tvOS,macOSselection).- Use
--target mobile|tv|desktopwith--platform(required) to select phone/tablet vs TV-class vs desktop-class targets. bootis mainly needed when starting a new session andopenfails because no booted simulator/emulator is available.- Android:
boot --platform android --device <avd-name>launches that emulator in GUI mode when needed. - Android: add
--headlessto launch without opening a GUI window. open [app|url] [url]already boots/activates the selected target when needed.open <url>deep links are supported on Android and iOS.open <app> <url>opens a deep link on iOS.open --platform macos --surface app|frontmost-app|desktop|menubarselects the macOS session surface explicitly.appis the default when an app argument is provided.backnow defaults to app-owned back navigation. On Apple targets that means visible in-app back UI only. On Android this currently maps to the same back keyevent because Android routes in-app back through that platform event.back --in-appis an explicit alias for the default app-owned behavior.back --systemasks for system back input explicitly. On Android this is the normal back keyevent. On iOS and tvOS it uses the platform back gesture or Siri Remote menu action. On macOS, where there is no generic system back input,back --systemreports unavailable instead of falling back to app-owned navigation.rotate <orientation>forces a mobile device intoportrait,portrait-upside-down,landscape-left, orlandscape-right.rotateis supported on iOS and Android mobile targets. macOS and tvOS do not expose it.- On iOS devices,
http(s)://URLs open in Safari when no app is active. Custom scheme URLs require an active app in the session. AGENT_DEVICE_SESSIONandAGENT_DEVICE_PLATFORMcan pre-bind a default session/platform for CLI automation runs, so normal commands (open,snapshot,press,fill,screenshot,devices, andbatch) do not need those flags repeated on every call.- A configured
AGENT_DEVICE_SESSIONimplies bound-session lock mode by default. The CLI forwards that policy to the daemon, which enforces the same conflict handling for CLI, typed client, and direct RPC requests. --session-lock reject|stripsets the lock policy for a single CLI invocation, including nested batch steps.AGENT_DEVICE_SESSION_LOCK=reject|stripsets the default lock policy for bound-session automation runs. The older--session-locked,--session-lock-conflicts,AGENT_DEVICE_SESSION_LOCKED, andAGENT_DEVICE_SESSION_LOCK_CONFLICTSforms remain supported as compatibility aliases.- Direct RPC callers can pass
meta.lockPolicyand optionalmeta.lockPlatformonagent_device.commandrequests for the same daemon-enforced behavior. - In
batch, steps that omitplatformstill inherit the parent batch--platform; lock-mode defaults do not override that parent setting. - Tenant-scoped daemon runs can pass
--tenant,--session-isolation tenant,--run-id, and--lease-idto enforce lease admission. - Remote daemon clients can pass
--daemon-base-url http(s)://host:port[/base-path]to skip local daemon discovery/startup and call a remote HTTP daemon directly. - Use
--daemon-auth-token <token>(orAGENT_DEVICE_DAEMON_AUTH_TOKEN) for explicit service/API-token automation against non-loopback remote daemon URLs; the client sends it in both the JSON-RPC request token and HTTP auth headers. - For human cloud access,
connectcan discover a cloud connection profile, whileconnect --remote-config ...uses a local profile. Both refresh a stored CLI session into a short-livedadc_agent_...token when needed. If no CLI session exists, interactive shells start login automatically; CI and non-interactive shells fail with API-token setup instructions. Use--no-loginto disable implicit login.AGENT_DEVICE_CLOUD_BASE_URLis the bridge/control-plane API origin; its/api-keysroute may redirect to the dashboard for token creation. - For remote
connectandconnect --remote-configflows, see Remote Metro workflow. - Android React Native relaunch flows require an installed package name for
open --relaunch; install/reinstall the APK first, then relaunch by package.open <apk|aab> --relaunchis rejected because runtime hints are written through the installed app sandbox. - For Metro-backed React Native JS changes, use
metro reloadbeforeopen <app> --relaunch; it mirrors pressingrin the Metro terminal and keeps the native process alive. - Remote daemon screenshots and recordings are downloaded back to the caller path, so
screenshot page.pngandrecord start session.mp4remain usable when the daemon runs on another host.
Device isolation scopes
--ios-simulator-device-set <path>constrains simulator discovery and simulator command execution viaxcrun simctl --set <path> ....--android-device-allowlist <serials>constrains Android discovery/selection to comma or space separated serials.- Scope is applied before selectors (
--device,--udid,--serial), so out-of-scope selectors fail withDEVICE_NOT_FOUND. - With iOS simulator-set scope enabled, iOS physical devices are not enumerated.
- Environment equivalents:
- iOS:
AGENT_DEVICE_IOS_SIMULATOR_DEVICE_SET(compat:IOS_SIMULATOR_DEVICE_SET) - Android:
AGENT_DEVICE_ANDROID_DEVICE_ALLOWLIST(compat:ANDROID_DEVICE_ALLOWLIST)
- iOS:
- CLI scope flags override environment values unless bound-session lock mode is active with
strip, in which case conflicting per-call selectors are ignored.
Device discovery
deviceslists available targets after applying any platform selector or isolation scope flags.- Use
--platformto narrow discovery to Apple-family (ios,tvOS,macOS) or Android targets. - Use
--ios-simulator-device-setand--android-device-allowlistwhen you need tenant- or lab-scoped discovery.
Simulator provisioning
ensure-simulatorensures a named iOS simulator exists inside a device set, creating it viasimctl createif missing.- Requires
--device <name>(the simulator name / device type, e.g."iPhone 16 Pro"). --runtime <id>pins a specific CoreSimulator runtime (e.g.com.apple.CoreSimulator.SimRuntime.iOS-18-4). Omit to use the newest compatible runtime.--bootboots the simulator after ensuring it exists.- Reuse of an existing matching simulator is the default; the command is idempotent.
- JSON output includes
udid,device,runtime,ios_simulator_device_set,created, andbooted. - Does not require an active session — safe to call before
open.
TV targets
- AndroidTV app launch and app listing resolve TV launchable activities via
LEANBACK_LAUNCHER. - TV target selection supports both simulator/emulator and connected physical devices (AppleTV + AndroidTV).
- tvOS supports the same runner-driven interaction/snapshot flow as iOS (
snapshot,wait,press,fill,get,scroll,back,home,app-switcher,record, and related selector flows). - On tvOS, runner
back/home/app-switchermap to Siri Remote actions (menu,home, double-home). - tvOS follows iOS simulator-only command semantics for helpers like
pinch,settings, andpush.
Desktop targets
--platform macosselects the host Mac as adesktoptarget.--platform apple --target desktopselects the same macOS backend through the Apple-family alias.- Use
appsessions for normal app control:open,snapshot,click,fill,press,scroll,back,screenshot,record. - Use
frontmost-app,desktop, andmenubarwhen you need to inspect desktop-global UI before choosing one app. open --platform macos --surface frontmost-appinspects the currently focused app without naming it first.open --platform macos --surface desktopinspects visible windows across the desktop.open --platform macos --surface menubarinspects the active app menu bar and system menu extras.open <app> --platform macos --surface menubartargets one menu bar app's extras bar, which is useful for status-item apps.- Status-item apps often expose little or no useful UI through the default macOS
appsurface. Prefer--surface menubarfor discovery when the app lives in the top menu bar. - Use
frontmost-app,desktop, andmenubarmainly forsnapshot,get,is, andwait. - If you inspect with
desktopormenubarand then need to click or fill inside one app, open that app in a normalappsession. - macOS also supports
clipboard read|write,trigger-app-event,logs,network dump,alert,pinchin app sessions,settings appearance, andsettings permission <grant|reset> <accessibility|screen-recording|input-monitoring>. - In macOS app sessions,
screenshotcaptures the target app window bounds rather than the full desktop. - Prefer selector or
@ref-driven interactions on macOS. Window position can shift between runs, so raw x/y point commands are less stable than snapshot-derived targets. - Use
click --button secondaryfor context menus on macOS, then runsnapshot -iagain. - Mobile-only helpers remain unsupported on macOS:
boot,home,rotate,app-switcher,install,reinstall,install-from-source, andpush.
Recommended loops:
Snapshot and inspect
- iOS snapshots use XCTest on simulators and physical devices.
- Android snapshots use the bundled Android snapshot helper when the npm package includes it. The
first helper-backed snapshot verifies and installs the helper APK if it is missing or outdated;
helper failures fall back to stock UIAutomator and include
androidSnapshot.fallbackReasonin typed results. Source checkouts without a bundled helper use stock UIAutomator. The helper serializes Android interactive window roots when available, so keyboard and system-overlay nodes can appear alongside the app root;androidSnapshot.captureModeandandroidSnapshot.windowCountdescribe the capture. diff snapshotcompares the current snapshot with the previous session baseline and then updates baseline.snapshot --diffis an alias fordiff snapshot.
Wait and alerts
waitaccepts a millisecond duration,text <value>, a snapshot ref (@eN), or a selector.wait <selector> [timeoutMs]polls until the selector resolves or the timeout expires.wait @ref [timeoutMs]requires an existing session snapshot from a priorsnapshotcommand.wait @refresolves the ref to its label/text from that stored snapshot, then polls for that text; it does not track the original node identity.- Because
wait @refis text-based after resolution, duplicate labels can match a different element than the original ref target. waitshares the selector/snapshot resolution flow used byclick,fill,get, andis.alertinspects or handles system alerts on iOS simulator and macOS desktop targets.alertwithout an action is equivalent toalert get.alert wait [timeout]waits for an alert to appear before returning it.- If an iOS permission sheet is visible in
snapshotorscreenshotbutalert acceptreports no alert, fall back to a scopedsnapshot -i -s "<visible label>"pluspress @ref; not every simulator permission surface is exposed as a native XCTest alert.
Interactions
fill clears then types. type does not clear.
type accepts text only. Do not pass @ref to type; use fill @ref "text" to target a field directly, or press @ref then type "text" to append in the focused field.
Use --delay-ms on type or fill for debounced search fields and search-as-you-type inputs that miss characters when text is injected too quickly.
Delayed typing prefers paced character entry over clipboard-style fallbacks so the target field still receives incremental updates.
On Android, fill also verifies text and performs one clear-and-retry pass on mismatch.
Some Android images cannot enter non-ASCII text over shell input; in that case use a trusted ADB keyboard IME and verify APK checksum/signature before install.
click --button secondary is the desktop context-menu flow on macOS.
click --button middle is reserved for future runner support and currently returns an explicit unsupported-operation error on macOS.
swipe accepts an optional durationMs argument (default 250ms, range 16..10000).
On iOS, swipe duration is clamped to a safe range (16..60ms) to avoid longpress side effects.
scroll accepts either a relative amount (0.5 means roughly half of the viewport on that axis) or --pixels <n> for a fixed-distance gesture. Large distances are clamped to the usable drag band so the gesture stays reliable across Android, iOS, and macOS.
Default snapshot text output is visible-first, so off-screen interactive content is summarized instead of shown as tappable refs.
When a target only appears in an off-screen summary, use scroll <direction> and then take a fresh snapshot -i. For repeated checks, a small shell loop is enough:
longpress is supported on iOS and Android.
pinch is supported on Apple simulators and macOS app sessions.
Find (semantic)
Assertions
isevaluates UI predicates against a selector expression and exits non-zero on failure.- Supported predicates are
visible,hidden,exists,editable,selected, andtext. is visiblechecks whether the resolved element is present in the current visible snapshot viewport. A node without its own rect still passes when a visible ancestor within the viewport provides the on-screen geometry.is existsonly checks whether the selector matches in the current snapshot.wait textis a text-presence wait, not a hittability assertion.is text <selector> <value>compares the resolved element text against the expected value.isdoes not accept snapshot refs like@e3; use a selector expression instead.isaccepts the same selector-oriented snapshot flags asclick,fill,get, andwait.
Replay
replayruns deterministic.adscripts.testruns one or more.adscripts as a serial suite from files, directories, or glob inputs.test --platform <platform>filters suite files bycontext platform=...metadata instead of overriding the script target.test --timeout <ms>andtest --retries <n>apply per script attempt;context timeout=...andcontext retries=...can be declared inside the.adheader. Retries are capped at3, duplicate metadata keys are rejected, and timeouts are cooperative.test --artifacts-dir <path>overrides the default suite artifact root at.agent-device/test-artifacts.testprints failures and flaky passed-on-retry tests by default, and prints a shortRunning replay suite...line before dispatch; add--verboseto print pass and skip lines too.replay -uupdates stale recorded actions and rewrites the same script.--save-scriptrecords a replay script onclose; optional path is a file path and parent directories are created.
See Replay & E2E (Experimental) for recording and CI workflow details.
Batch
batchruns a JSON array of steps in a single daemon request.- Each step has
command, optionalpositionals, optionalflags, and optionalruntime. - Unknown top-level step fields are rejected.
- Stop-on-first-error is the supported behavior (
--on-error stop). - Use
--max-steps <n>to tighten per-request safety limits. - Batch requests inherit the same daemon lock policy and session binding metadata as the parent command.
- In non-JSON mode, successful batches print a short per-step summary.
See Batching for payload format, response shape, and usage guidelines.
App install (in-place)
install <app> <path>installs from binary path without uninstalling first.- Supports Android devices/emulators, iOS simulators, and iOS physical devices.
- Useful for upgrade flows where you want to keep existing app data when supported by the platform.
- Remote daemons automatically upload local app artifacts for
install; prefix the path withremote:to use a daemon-side path verbatim. - Supported binary formats: Android
.apk/.aab, iOS.app/.ipa. .aabrequiresbundletoolinPATH, orAGENT_DEVICE_BUNDLETOOL_JAR=<absolute-path-to-bundletool-all.jar>withjavainPATH.- Optional:
AGENT_DEVICE_ANDROID_BUNDLETOOL_MODE=<mode>overrides bundletoolbuild-apks --mode(default:universal). .ipainstalls by extractingPayload/*.app; if multiple app bundles exist,<app>is used as a bundle id/name hint to select one.
App reinstall (fresh state)
reinstall <app> <path>uninstalls and installs in one command.- Supports Android devices/emulators, iOS simulators, and iOS physical devices.
- Useful for login/logout reset flows and deterministic test setup.
- Remote daemons automatically upload local app artifacts for
reinstall; prefix the path withremote:to use a daemon-side path verbatim. - Supported binary formats: Android
.apk/.aab, iOS.app/.ipa. .aabaccepts the same bundletool requirements and optionalAGENT_DEVICE_ANDROID_BUNDLETOOL_MODEoverride asinstall..ipauses<app>as the selection hint when multiplePayload/*.appbundles are present.
App install from source URL
install-from-source <url>installs from a URL source through the normal daemon artifact flow.install-from-source --github-actions-artifact <owner/repo:artifact>passes a typed GitHub Actions artifact source through to a compatible remote daemon. Numeric artifacts are sent asartifactId; non-numeric artifacts are sent asartifactName.- Repeat
--header <name:value>for authenticated or signed artifact requests. - Supports the same device coverage as
install: Android devices/emulators, iOS simulators, and iOS physical devices. - Use
installorreinstallfor local.apk,.aab,.app, and.ipapaths; useinstall-from-sourcewhen the artifact already exists at a URL reachable by the daemon. - Direct Android URL sources may be
.apkor.aab. - Trusted artifact service URLs may resolve to archives containing one installable
.apk,.aab,.ipa, or iOS.apptar archive. Prefer--github-actions-artifactfor GitHub Actions artifacts that a compatible remote daemon can resolve with its own credentials. --retain-pathskeeps retained materialized artifact paths after install, and--retention-ms <ms>sets their TTL.- URL downloads follow the same
installFromSource()safety checks and host restrictions as the JS client API.
Push notification simulation
push <bundle|package> <payload.json|inline-json>simulates push notification delivery.- iOS push simulation is simulator-only (
xcrun simctl push) and requires an APNs-style JSON object payload. - Android uses
adb shell am broadcastand accepts payload shape:{"action":"<intent-action>","receiver":"<optional component>","extras":{"key":"value","flag":true,"count":3}}. - Android extras support
string,boolean, andnumbervalues. pushworks with the active session device, or with explicit selectors (--platform,--device,--udid,--serial).
App event triggers (app hook)
trigger-app-event <event> [payloadJson]dispatches app-defined events via deep link.trigger-app-eventrequires either an active session or explicit device selectors (--platform,--device,--udid,--serial).- On macOS, use
AGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATEto override the desktop deep-link template. - On iOS physical devices, custom-scheme deep links require active app context (open app first in the session).
- Configure one of:
AGENT_DEVICE_APP_EVENT_URL_TEMPLATEAGENT_DEVICE_IOS_APP_EVENT_URL_TEMPLATEAGENT_DEVICE_MACOS_APP_EVENT_URL_TEMPLATEAGENT_DEVICE_ANDROID_APP_EVENT_URL_TEMPLATE
- Template placeholders:
{event},{payload},{platform}. - Example template:
myapp://agent-device/event?name={event}&payload={payload}. payloadJsonmust be a JSON object.- This is app-hook-based simulation and does not inject OS-global notifications.
Settings helpers
- iOS
settingssupport is simulator-only except forsettings appearanceand the macOS permission subset on macOS. - macOS supports only
settings appearance <light|dark|toggle>andsettings permission <grant|reset> <accessibility|screen-recording|input-monitoring>. settings wifi|airplane|location|animationsremain intentionally unsupported on macOS.- Android
settings animations off|ontoggles the globalwindow_animation_scale,transition_animation_scale, andanimator_duration_scalevalues. Use it as an opt-in stabilizer for automation runs with heavy system or app animations, then restore withsettings animations onwhen needed. settings appearancemaps to macOS appearance, iOS simulator appearance, and Android night mode.- Face ID and Touch ID controls are iOS simulator-only.
- Fingerprint simulation is supported on Android targets where
cmd fingerprintoradb emu fingeris available. On physical Android devices, onlycmd fingerprintis attempted. - Permission actions are scoped to the active session app.
- iOS permission targets:
camera,microphone,photos(fullorlimited),contacts,notifications. - Android permission targets:
camera,microphone,photos,contacts,notifications. - macOS permission targets:
accessibility,screen-recording,input-monitoring. - On macOS,
settings permission grant ...checks/request access and opens System Settings guidance when needed; it does not silently grant TCC permissions. - On macOS,
settings permission deny ...is intentionally unsupported. - Android uses
pm grant|revokefor runtime permissions (resetmaps to revoke) andappopsfor notifications. full|limitedmode is supported only for iOSphotos; other targets reject mode.- Use
match/nonmatchto simulate valid/invalid Face ID, Touch ID, and Android fingerprint outcomes.
App state and app lists
- Android
appstatereports live foreground package/activity. - iOS
appstateis session-scoped and reports the app tracked by the active session on the target device. appsincludes default/system apps by default (use--user-installedto filter).
Clipboard
clipboard readreturns clipboard text for the selected target.- Treat
clipboard readoutput as sensitive data; it can include secrets copied by the user or app. clipboard write <text>updates clipboard text on the selected target.- Works with an active session device or explicit selectors (
--platform,--device,--udid,--serial). - Supported on macOS, Android emulator/device, and iOS simulator.
- iOS physical devices currently return
UNSUPPORTED_OPERATIONfor clipboard commands.
Keyboard
keyboard status(orkeyboard get) returns keyboard visibility and best-effort input type classification on Android.keyboard dismissattempts a non-navigation keyboard dismissal on Android and a native dismiss gesture/control on iOS, including common safe controls such as a keyboard toolbarDonebutton, then confirms the keyboard is hidden.- If the keyboard remains visible after the platform-native dismiss path, the command returns an explicit
UNSUPPORTED_OPERATIONerror instead of falling back to back navigation. - On iOS,
keyboard dismissis best-effort and can fail when the active app exposes no native dismiss gesture/control. Prefer a visible app dismiss control, or useback --systemonly when system navigation is an acceptable side effect. - Works with active sessions and explicit selectors (
--platform,--device,--udid,--serial). keyboard status|getis supported on Android emulator/device.keyboard dismissis supported on Android emulator/device and best-effort on iOS simulator/device.
Performance metrics
perf(alias:metrics) returns a session-scoped metrics JSON blob.- Without
--json,perfprints a compact summary: frame health when reliable frame data is available, otherwise CPU/memory when those samples are available. startupis sampled fromopen-command-roundtrip: elapsed wall-clock time around eachopencommand dispatch for the active session app target.- Android app sessions with an active package also sample:
fpsframe health fromadb shell dumpsys gfxinfo <package> framestats, withdroppedFramePercentas the primary value andworstWindowsfor dropped-frame clustersmemoryfromadb shell dumpsys meminfo <package>with values reported in kilobytes (kB)cpufromadb shell dumpsys cpuinfo, aggregated across matching package processes and reported as a recent percentage snapshot
- Apple app sessions with an active bundle ID also sample:
fpsframe health fromxcrun xctraceAnimation Hitches on connected iOS devices, withdroppedFramePercentas the primary value andworstWindowsfor hitch clustersmemoryfrom process RSS snapshots reported in kilobytes (kB)cpufrom process CPU usage snapshots reported as a recent percentage
- Platform support:
startup: iOS simulator, iOS physical device, Android emulator/devicememoryandcpu: Android emulator/device, macOS app sessions, iOS simulators with an active app session (open <app>first), and iOS physical devices with an active app sessionfps: Android emulator/device app sessions and connected iOS device app sessions. iOS simulator and macOS frame health is reported unavailable because Apple tooling does not expose trustworthy app hitch data there.
- If no startup sample exists yet for the session, run
open <app|url>first and retryperf. - Android URL/deep-link opens infer the foreground package after launch when possible, including Expo Go/dev-client shells. If the session still has no app package/bundle ID, package-bound metrics remain unavailable until you
open <app>. - Android frame health is reset after each successful
perfread and afteropen <app>, so runperf, perform the interaction, then runperfagain for a focused window. - On physical iOS devices,
perfrecords shortxcrun xctraceActivity Monitor and Animation Hitches samples. Keep the device unlocked, connected, and the app active in the foreground while sampling. - Interpretation note: this startup metric is command round-trip timing and does not represent true first frame / first interactive app instrumentation.
- CPU data is a lightweight process snapshot, so an idle app may legitimately read as
0.
React Native component internals
react-devtoolsdynamically runs pinned[email protected]through npm and passes arguments through 1:1.- The first run may download the pinned package from npm; later runs can reuse the npm cache.
agent-deviceglobal flags work before or afterreact-devtools. Use--before downstream flags only when they intentionally share anagent-deviceglobal flag name.- Use it when a React Native workflow needs component hierarchy, props, state, hooks, render causes, slow components, or re-render counts.
- Keep using
snapshot,press,fill,logs,network, andperffor device/app runtime evidence. Usereact-devtoolsfor React internals. - React Native development builds can connect to the DevTools daemon on port 8097. For Android emulators or physical devices, run
adb reverse tcp:8097 tcp:8097if the app cannot reach the host. If Metro is local, also runadb reverse tcp:8081 tcp:8081. - For Android and iOS sessions connected through a remote bridge profile,
react-devtoolsregisters a lease-scoped companion tunnel to the sandbox-local DevTools daemon at127.0.0.1:8097. Android bridge profiles use the bridge-owned remoteadb reversemapping; iOS bridge profiles use the bridge-owned wildcard Metro host tunnel. The CLI keeps the companion alive untilagent-device react-devtools stoporagent-device disconnect. - For remote iOS bridge sessions, open the app once to create the bridge session, run
agent-device react-devtools start, then relaunch the same bundle id withagent-device open <bundle-id> --platform ios --relaunchbeforewait --connected. React Native attempts the legacy DevTools websocket during JavaScript startup, so starting DevTools after the first launch can miss that connection attempt. - Remote bridge React DevTools assumes the React Native-bundled DevTools behavior in React Native 0.83+. Older browser/Chromium DevTools workflows are not assumed to exist inside remote sandboxes. Expo projects should be verified against the SDK's bundled React Native version before relying on this path; this release does not claim a separately verified Expo SDK version.
- For cross-platform validation with explicit target selectors, prefer an isolated
--state-dirover separate named sessions. Named sessions enable bound-session locks during setup. Restartreact-devtoolsbetween iOS and Android runs.
Metro reload
metro reloadcalls Metro's/reloadendpoint, the same mechanism used by pressingrin the Metro terminal.- Use it for React Native dev builds that are already connected to Metro when JS changes should be loaded without restarting the native app process.
- If an active remote connection has Metro runtime hints,
metro reloaduses those saved hints. Otherwise it defaults tohttp://localhost:8081/reload. - Pass
--metro-host,--metro-port, or--bundle-urlwhen you need to target a specific Metro instance. - Fall back to
open <app> --relaunchwhen the app is not connected to Metro, reload fails, or the native process itself must restart.
Media and logs
- Recordings always produce a video artifact. When touch visualization is enabled, they also produce a gesture telemetry sidecar that can be used for post-processing or inspection.
screenshot --max-size <px>preserves aspect ratio and only downscales when the saved PNG's longest edge is larger than the requested size.screenshot --overlay-refscaptures a fresh full snapshot and burns visible@eNrefs plus their target rectangles into the saved PNG.screenshot --max-size <px> --overlay-refswrites a smaller image and draws refs for that final image size; avoid very small max sizes when text, icons, or labels need to remain readable.diff screenshotcompares the current live screenshot to--baseline, or compares--baselineto an optional savedcurrent.pngpath without requiring an active session, then prints ranked changed regions with screen-space rectangles, shape, size, density, average color, and luminance, and writes a diff PNG with a light grayscale current-screen context, red-tinted changed pixels, and outlined changed regions when--outis provided. JSON also includes normalized bounds.- If
tesseractis installed,diff screenshotalso adds best-effort OCR text deltas, movement clusters, and bbox size-change hints to the text and JSON output. OCR improves descriptions only; it does not change the pixel comparison or the diff PNG. - When OCR is available,
diff screenshotalso reports best-effort non-text visual deltas by masking OCR text boxes out of the diff and clustering remaining residuals. These are hints for icons, controls, and separators, not semantic icon recognition. diff screenshot --overlay-refsadditionally writes a separate current-screen overlay guide for live captures without using that annotated image for the pixel comparison. If current-screen refs intersect changed regions, the output lists the best ref matches under those regions. Saved-image comparisons do not have live accessibility refs, so--overlay-refsis unavailable when acurrent.pngpath is provided.- In
--jsonmode, each overlay ref also includes a screenshot-spacecenterpoint for coordinate fallback likepress <x> <y>. - Burned-in touch overlays are exported only on macOS hosts, because the overlay pipeline depends on Swift + AVFoundation helpers.
- On Linux or other non-macOS hosts,
record stopstill succeeds and returns the raw video plus telemetry sidecar, and includesoverlayWarningwhen burn-in overlays were skipped.
Session app logs (token-efficient debugging): Logging is off by default in normal flows. Enable it on demand for debugging. Logs are written to a file so agents can grep instead of loading full output into context.
- Supported on iOS simulator, iOS physical device, and Android.
- Preferred debug entrypoint:
logs clear --restartfor clean-window repro loops. logs startappends toapp.logand rotates toapp.log.1when the file exceeds 5 MB.network dump [limit] [summary|headers|body|all]parses recent HTTP(s) entries fromapp.log;network log ...is an alias.- Prefer
--include headers|body|allwhen you want explicit detail level without relying on positional ordering. - On macOS,
logsandnetwork dumpare app-scoped and parse Unified Logging output associated with the active session app. - Network dump limits: scans up to 4000 recent log lines, returns up to 200 entries, and truncates payload/header fields at 2048 characters.
- Android
network dumpalso surfaces logcat timestamps and can backfill status and duration from adjacent GIBSDK packet lines when the URL is logged separately. - Android log streaming automatically rebinds to the app PID after process restarts.
- iOS simulator log capture now streams from inside the simulator with
simctl spawn <udid> log ..., andnetwork dumpcan recover recent simulator log history withsimctl log showwhen the live app-log window is sparse. - iOS log capture still relies on Unified Logging signals (for example
os_log); plain stdout/stderr output may be limited depending on app/runtime. - On iOS,
network dumpcan return zero HTTP entries for real app activity when the app does not emit request metadata into Unified Logging. The response notes now distinguish between an empty repro window and a non-network app log window. - Retention knobs: set
AGENT_DEVICE_APP_LOG_MAX_BYTESandAGENT_DEVICE_APP_LOG_MAX_FILESto override rotation limits. - Optional write-time redaction patterns: set
AGENT_DEVICE_APP_LOG_REDACT_PATTERNSto a comma-separated regex list.
Grepping app logs: Use logs path to get the file path, then run grep (or grep -E) on that path so only matching lines enter context—keeping token use low.
-
Use
-nto include line numbers. Use-Efor extended regex and|without escaping in the pattern. -
Prefer targeted patterns (e.g.
Error,Exception, your log tags) over reading the whole file. -
logs mark "before submit"lines are prefixed with[agent-device][mark][...], so grep foragent-device.*markwhen you need timing markers back quickly. -
iOS
recordworks on simulators and physical devices. -
iOS simulator recording uses native
simctl io ... recordVideo. -
Physical iOS device capture is runner-based and built from repeated
XCUIScreen.main.screenshot()frames (no native video stream/audio capture). -
Physical iOS device recording requires an active app session context (
open <app>first). -
Physical iOS device capture is best-effort: dropped frames are expected and true 60 FPS is not guaranteed even with
--fps 60. -
Physical-device capture defaults to 15 FPS.
-
--fps <n>(1-120) applies to physical iOS device recording as an explicit FPS cap. -
--quality <5-10>scales recording resolution from 50% through native resolution without changing FPS. Omitting it preserves the platform's current/native recording resolution.
Tracing
trace start [path]begins trace-log capture for the active session.trace stop [path]stops capture and optionally writes or finalizes the trace artifact at the provided path.traceis intended for lower-level session diagnostics thanrecordorlogs.
Remote Metro workflow
When the cloud control plane owns the connection profile, connect can discover it directly:
For local profile files, create an agent-device.remote.json:
For self-contained scripts, pass the same profile to each step:
connectwithout--remote-configauthenticates to cloud when needed, fetches the connection profile, writes a generated local profile, stores the remote scope locally, and defers tenant lease allocation plus Metro preparation until a later command needs them.- Cloud connection profile responses must return a JSON object at
connection.remoteConfigProfile. The olderconnection.remoteConfigJSON string shape is no longer accepted. --remote-config <path>points to a local remote workflow profile that captures stable host, tenant/run, and any optional session, platform, lease backend, or Metro overrides forconnect.connect --remote-config ...follows the same state and deferred-preparation flow using the local profile instead of cloud discovery.- Auth management commands are available for inspection and recovery:
agent-device auth status,agent-device auth login, andagent-device auth logout. Human login stores a revocable CLI session locally; it does not create or persist anadc_live_...service token. - Cloud auth uses three credential classes:
adc_agent_...short-lived command tokens, revocable CLI session refresh credentials, and explicitadc_live_...service/API tokens for CI. The CLI implements credential selection, CI refusal, local storage permissions, logout, and output redaction; the cloud API must enforce token expiry, tenant/run scope, revocation, one-time device approval, polling rate limits, and dashboard/API separation. AGENT_DEVICE_CLOUD_BASE_URLshould point at the bridge/control-plane API origin, not necessarily the dashboard origin. API-token setup links use/api-keyson that origin so the bridge can redirect users to the right dashboard page.- Deferred Metro preparation also applies to
batchwhen any step opens an app and the batch does not provide its own per-step runtime. - After
connect,install-from-source,open,snapshot,devices,press,fill,screenshot, and other normal commands reuse active connection state so agents do not repeat remote host/session/lease selectors inline. Ifconnection statusshowsleaseId=pending, the first platform-bound command allocates or refreshes the lease. Passing the same--remote-configto a normal command is also supported for self-contained scripts; the CLI reuses matching saved state or creates it before dispatch. - Self-contained remote scripts should end with
disconnect --remote-config <path>ordisconnectto release the lease and stop the owned Metro companion. - Explicit command-line flags override connected defaults. When
openuses explicit remote daemon or tenant flags without saved runtime hints, the CLI warns because React Native apps may launch without Metro bundle/runtime hints. metroProxyBaseUrlis the bridge origin. Do not prebuild/api/metro/...paths in the client profile; the CLI calls the bridge endpoints itself.- For cloud stock React Native iOS, the bridge descriptor supplies direct wildcard HTTPS Metro hints such as
<runtime>.metro.agent-device.dev:443. The XCTest runner package is still used for runner-backed device commands, not for Metro reachability. - Android keeps using bridge-provided runtime routes such as
/api/metro/runtimes/<runtimeId>/.... metroPublicBaseUrlis only needed for direct/non-bridge bundle hints. Bridged profiles can omit it and rely onmetroProxyBaseUrl.metro prepare --remote-config ...remains an advanced inspection/debug path and can still write a--runtime-file <path>artifact when needed.- The local Metro companion runs on the same machine as the React Native project and Metro.
disconnectstops the companion owned by the connection, but it does not stop the user’s Metro server.
Cloud profile response migration
/api/control-plane/connection-profile must return an object at connection.remoteConfigProfile, for example {"connection":{"remoteConfigProfile":{"daemonBaseUrl":"https://bridge.example.com/agent-device","daemonTransport":"http","tenant":"acme","runId":"run-123"}}}. The old connection.remoteConfig JSON-string wrapper is rejected.
Session inspection
session listshows active daemon sessions and their tracked device/app context.- Use
--jsonwhen you want to inspect or script against the raw session metadata.
iOS device prerequisites
- Xcode +
xcrun devicectlavailable. - Paired physical device with Developer Mode enabled.
- Use Automatic Signing in Xcode, or pass optional env overrides:
AGENT_DEVICE_IOS_TEAM_IDAGENT_DEVICE_IOS_SIGNING_IDENTITY(optional)AGENT_DEVICE_IOS_PROVISIONING_PROFILEAGENT_DEVICE_IOS_BUNDLE_ID(runner bundle-id base; tests use<id>.uitests)
- Free Apple Developer (Personal Team) accounts can fail on unavailable generic bundle IDs; set
AGENT_DEVICE_IOS_BUNDLE_IDto a unique reverse-DNS value. - If first-run XCTest setup/build is slow, increase daemon request timeout:
AGENT_DEVICE_DAEMON_TIMEOUT_MS=120000(default is90000)
- For daemon startup troubleshooting:
- follow stale metadata hints for
<state-dir>/daemon.jsonand<state-dir>/daemon.lock(state-dirdefaults to~/.agent-device)
- follow stale metadata hints for
