agent-device 0.17.9 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +4 -0
  2. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.9.apk → agent-device-android-multitouch-helper-0.18.0.apk} +0 -0
  3. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.18.0.apk.sha256 +1 -0
  4. package/android-multitouch-helper/dist/{agent-device-android-multitouch-helper-0.17.9.manifest.json → agent-device-android-multitouch-helper-0.18.0.manifest.json} +4 -4
  5. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.9.apk → agent-device-android-snapshot-helper-0.18.0.apk} +0 -0
  6. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.18.0.apk.sha256 +1 -0
  7. package/android-snapshot-helper/dist/{agent-device-android-snapshot-helper-0.17.9.manifest.json → agent-device-android-snapshot-helper-0.18.0.manifest.json} +6 -6
  8. package/dist/src/1848.js +4 -0
  9. package/dist/src/2577.js +1 -1
  10. package/dist/src/2948.js +20 -20
  11. package/dist/src/4291.js +1 -1
  12. package/dist/src/4723.js +1 -1
  13. package/dist/src/5341.js +1 -0
  14. package/dist/src/5643.js +1 -0
  15. package/dist/src/6918.js +1 -1
  16. package/dist/src/8275.js +2 -2
  17. package/dist/src/8936.js +1 -0
  18. package/dist/src/9414.js +1 -0
  19. package/dist/src/9581.js +4 -4
  20. package/dist/src/9722.js +32 -37
  21. package/dist/src/9919.js +5 -5
  22. package/dist/src/apple.js +1 -1
  23. package/dist/src/apps.js +10 -10
  24. package/dist/src/batch.d.ts +20 -3
  25. package/dist/src/batch.js +1 -1
  26. package/dist/src/cli-help.js +111 -35
  27. package/dist/src/cli.js +22 -25
  28. package/dist/src/contracts.d.ts +14 -0
  29. package/dist/src/device-ready.js +2 -0
  30. package/dist/src/find.js +1 -1
  31. package/dist/src/index.d.ts +67 -16
  32. package/dist/src/interaction.js +1 -1
  33. package/dist/src/internal/bin.js +1 -1
  34. package/dist/src/lease.js +1 -1
  35. package/dist/src/metro.js +1 -1
  36. package/dist/src/react-native.js +1 -1
  37. package/dist/src/record-trace-recording.js +3 -3
  38. package/dist/src/remote-config.d.ts +17 -11
  39. package/dist/src/selector-runtime.js +1 -1
  40. package/dist/src/session.js +11 -8
  41. package/dist/src/simulator.js +2 -0
  42. package/dist/src/snapshot.js +1 -1
  43. package/package.json +1 -1
  44. package/server.json +2 -2
  45. package/skills/agent-device/SKILL.md +1 -0
  46. package/android-multitouch-helper/dist/agent-device-android-multitouch-helper-0.17.9.apk.sha256 +0 -1
  47. package/android-snapshot-helper/dist/agent-device-android-snapshot-helper-0.17.9.apk.sha256 +0 -1
  48. package/dist/src/2133.js +0 -1
  49. package/dist/src/5628.js +0 -1
  50. package/dist/src/8358.js +0 -4
@@ -12,6 +12,20 @@ export declare type BatchRequest = Omit<DaemonRequest, 'flags'> & {
12
12
  flags?: BatchFlags | Record<string, unknown>;
13
13
  };
14
14
 
15
+ export declare type BatchRunResponse = {
16
+ ok: true;
17
+ data: BatchRunResult;
18
+ } | Extract<DaemonResponse, {
19
+ ok: false;
20
+ }>;
21
+
22
+ export declare type BatchRunResult = Record<string, unknown> & {
23
+ total: number;
24
+ executed: number;
25
+ totalDurationMs: number;
26
+ results: BatchStepResult[];
27
+ };
28
+
15
29
  export declare type BatchStepResult = {
16
30
  step: number;
17
31
  command: string;
@@ -36,7 +50,7 @@ export declare type DaemonBatchStep = {
36
50
  command: string;
37
51
  positionals?: string[];
38
52
  flags?: Record<string, unknown>;
39
- runtime?: unknown;
53
+ runtime?: DaemonRequest['runtime'];
40
54
  };
41
55
 
42
56
  declare type DaemonError = {
@@ -90,6 +104,9 @@ declare type DaemonRequestMeta = {
90
104
  leaseId?: string;
91
105
  leaseTtlMs?: number;
92
106
  leaseBackend?: LeaseBackend;
107
+ leaseProvider?: string;
108
+ deviceKey?: string;
109
+ clientId?: string;
93
110
  sessionIsolation?: SessionIsolationMode;
94
111
  uploadedArtifactId?: string;
95
112
  clientArtifactPaths?: Record<string, string>;
@@ -126,14 +143,14 @@ export declare type NormalizedBatchStep = {
126
143
  command: string;
127
144
  positionals: string[];
128
145
  flags: Record<string, unknown>;
129
- runtime?: unknown;
146
+ runtime?: DaemonRequest['runtime'];
130
147
  };
131
148
 
132
149
  declare const PLATFORM_SELECTORS: readonly ["ios", "macos", "android", "linux", "web", "apple"];
133
150
 
134
151
  declare type PlatformSelector = (typeof PLATFORM_SELECTORS)[number];
135
152
 
136
- export declare function runBatch(req: BatchRequest, sessionName: string, invoke: BatchInvoke): Promise<DaemonResponse>;
153
+ export declare function runBatch(req: BatchRequest, sessionName: string, invoke: BatchInvoke): Promise<BatchRunResponse>;
137
154
 
138
155
  declare const SESSION_ISOLATION_MODES: readonly ['none', 'tenant'];
139
156
 
package/dist/src/batch.js CHANGED
@@ -1 +1 @@
1
- var _=100;export{BATCH_BLOCKED_COMMANDS,INHERITED_PARENT_FLAG_KEYS}from"./2133.js";export{buildBatchStepFlags,runBatch,validateAndNormalizeBatchSteps}from"./6918.js";export{_ as DEFAULT_BATCH_MAX_STEPS};
1
+ var _=100;export{BATCH_BLOCKED_COMMANDS,INHERITED_PARENT_FLAG_KEYS}from"./5341.js";export{buildBatchStepFlags,runBatch,validateAndNormalizeBatchSteps}from"./6918.js";export{_ as DEFAULT_BATCH_MAX_STEPS};
@@ -1,4 +1,4 @@
1
- import{listCliCommandNames as e}from"./2133.js";import{getCliCommandSchema as t,getCommandSchema as o}from"./9581.js";import{getFlagDefinitions as a,GLOBAL_FLAG_KEYS as s}from"./2948.js";let n=[{label:"help workflow",description:"Normal bootstrap, exploration, and validation loop"},{label:"help debugging",description:"Logs, network, perf memory, and traces"},{label:"help react-native",description:"React Native app automation hazards, overlays, Metro, and routing"},{label:"help react-devtools",description:"React Native performance, profiling, component tree, and renders"},{label:"help physical-device",description:"Connected phone/tablet setup and iOS signing prerequisites"},{label:"help remote",description:"Remote/cloud config, tenants, leases, and local service tunnels"},{label:"help web",description:"Minimal browser sessions through agent-browser"},{label:"help macos",description:"Desktop, frontmost-app, and menu bar surfaces"},{label:"help dogfood",description:"Exploratory QA report workflow"}],r=["Planning output contract: when asked to plan commands, output command lines only: no prose, numbering, Markdown fences, pipes, or shell helpers.","Default loop: devices/apps -> open -> snapshot -i -> press/fill/get/is/wait/find -> verify -> close.",'Use selectors or refs as positional targets: id="submit", label="Allow", or @e12 from snapshot -i.',"Plain snapshot reads state; snapshot -i refreshes current interactive refs only.","Default snapshot text is an agent-facing, token-efficient view for planning and targeting actions.","Read-only visible/state question: use snapshot/get/is/find; use snapshot -i only when refs are needed.","Anti-pattern: snapshot -i followed by snapshot -i | grep ...; prior refs stay valid until app state changes, and --force-full is the explicit full re-read.","Truncated text/input preview: expand first with snapshot -s @e12, not get text.","React Native apps: read help react-native for Metro, DevTools routing, and RN-specific blockers; use react-native dismiss-overlay for LogBox/RedBox overlays.","Android RN/Expo Metro: direct Android localhost URL opens with a port auto-configure host reachability.",'Expo Go/dev clients: use the provided URL when given; on iOS use open "Expo Go" <url> --platform ios, then snapshot -i --platform ios to verify project UI. Do not use plain snapshot or snapshot --diff for this recovery check. Android URL opens infer the foreground package for logs/perf when possible.',"Install flows: install/install-from-source first, then open the installed id with --relaunch.",'Text: fill \'id="field-email"\' "qa@example.com" replaces; type appends after press.','Clearing text: do not use fill <target> ""; use a visible clear/reset control or report that clearing is unsupported.',"Android IME capture: if fill says input was captured by the keyboard/IME, inspect keyboard state and switch/disable handwriting before retrying; do not loop fill/type.","Implicit default sessions are scoped to the current worktree; if a prompt names a Session, include --session <name> on every command in that flow.","Run mutating commands serially within one session; parallelize only read-only commands or separate sessions/devices.","Clipboard limits: iOS Allow Paste cannot be automated through XCUITest; prefill with clipboard write. Android non-ASCII should use fill/type, not raw adb input.","After mutation: refs are stale. If the next target is known, use its selector directly; otherwise refresh with snapshot -i, scoped with -s when a stable container is known. Do not use tap; use press or click.","Raw coordinates are fallback-only: use snapshot -i --json rects when iOS refs no-op or child refs are missing, then verify the action with diff snapshot -i or snapshot --diff.","Sparse or AX-unavailable snapshot: use screenshot for visual truth, press the visible coordinate to leave the bad screen, then retry AX with snapshot -i.","macOS context menus use click <ref> --button secondary, then snapshot -i. Longpress is for mobile hold gestures, not macOS secondary-click menus.","Remote workflow profiles use --remote-config on operational commands. Do not substitute --config; --config only loads CLI defaults.",'Batch JSON steps use "command" and structured "input"; legacy "positionals"/"flags" steps still run in CLI but are deprecated until the next major version.',"Navigation: app-owned back uses back; system back uses back --system.","Web browser sessions: read help web; first slice is web setup if needed -> web doctor -> open <url> --platform web -> snapshot -i -> click/fill/get/is/find/wait/screenshot -> close.","Verification commands must name the expected text/selector; bare screenshots/snapshots are not enough.","Debug evidence: Session state contains request diagnostics and runner.log; use logs clear --restart/mark/path, trace, and network dump --include headers for app evidence.","Use agent-device commands in final plans; raw platform tools, pseudo commands, and helper prose are wrong.","Full operating guide: agent-device help workflow. Exploratory QA: agent-device help dogfood."],i=["Default config files: ~/.agent-device/config.json, ./agent-device.json","Use --config <path> or AGENT_DEVICE_CONFIG to load one explicit config file."],c=[{label:"AGENT_DEVICE_SESSION",description:"Explicit session name"},{label:"AGENT_DEVICE_PLATFORM",description:"Default platform binding"},{label:"AGENT_DEVICE_SESSION_LOCK",description:"Bound-session conflict mode"},{label:"AGENT_DEVICE_DAEMON_BASE_URL",description:"Connect to remote daemon"},{label:"AGENT_DEVICE_DAEMON_AUTH_TOKEN",description:"Remote daemon service/API token"},{label:"AGENT_DEVICE_CLOUD_BASE_URL",description:"Bridge/control-plane API origin for cloud auth and /api-keys"}],l=["agent-device open Settings --platform ios","agent-device open https://example.com --platform web","agent-device open TextEdit --platform macos","agent-device snapshot -i","agent-device react-devtools get tree --depth 3",'agent-device fill @e3 "test@example.com"',"agent-device replay ./session.ad","agent-device test ./suite --platform android"],d={workflow:{summary:"Normal agent-device bootstrap, exploration, and validation loop",body:`agent-device help workflow
1
+ import{listCliCommandNames as e}from"./5341.js";import{getCliCommandSchema as t,getCommandSchema as a}from"./9581.js";import{getFlagDefinitions as o,GLOBAL_FLAG_KEYS as s}from"./2948.js";let n=[{label:"agent-device help workflow",description:"Start here for the core loop, command shape, refs/selectors, and verification"},{label:"agent-device help debugging",description:"Use when logs, network, perf memory, traces, alerts, or diagnostics matter"},{label:"agent-device help react-native",description:"Use when the target app is React Native, Expo, or a dev client"},{label:"agent-device help react-devtools",description:"Use when inspecting components, props/state/hooks, renders, or profiles"},{label:"agent-device help cdp",description:"Use when investigating JS heap growth, heap snapshots, or retainers"},{label:"agent-device help physical-device",description:"Use when using a connected phone/tablet or iOS signing setup"},{label:"agent-device help remote",description:"Use when working through cloud config, tenants, leases, or local tunnels"},{label:"agent-device help web",description:"Use when automating a browser through agent-device sessions"},{label:"agent-device help macos",description:"Use when targeting desktop, frontmost app, or menu bar surfaces"},{label:"agent-device help dogfood",description:"Use when producing exploratory QA evidence"}],r=["agent-device is the default automation surface for app/device workflows across supported targets.","Default to agent-device for installs, opens, snapshots, interactions, screenshots, logs, network/perf evidence, and verification.","Use raw adb, simctl, xcrun, or platform scripts only when this help calls out a tool gap or platform setup step.","Start with agent-device help workflow to understand the core loop and how to use the tool."],i=["Planning output contract: when asked to plan commands, output command lines only: no prose, numbering, Markdown fences, pipes, or shell helpers.","Default loop: devices/apps -> open -> snapshot -i -> press/fill/get/is/wait/find -> verify -> close.",'Use selectors or refs as positional targets: id="submit", label="Allow", or @e12 from snapshot -i.',"Plain snapshot reads state; snapshot -i refreshes current interactive refs only.","Default snapshot text is an agent-facing, token-efficient view for planning and targeting actions.","Read-only visible/state question: use snapshot/get/is/find; use snapshot -i only when refs are needed.","Anti-pattern: snapshot -i followed by snapshot -i | grep ...; prior refs stay valid until app state changes, and --force-full is the explicit full re-read.","Truncated text/input preview: expand first with snapshot -s @e12, not get text.","React Native apps: read help react-native for Metro, DevTools routing, and RN-specific blockers; use react-native dismiss-overlay for LogBox/RedBox overlays.","React Native JS memory leaks: read help cdp; use heap usage samples for a quick signal, then snapshot diff/leak-triplet for retained object proof.","Android RN/Expo Metro: direct Android localhost URL opens with a port auto-configure host reachability.",'Expo Go/dev clients: use the provided URL when given; on iOS use open "Expo Go" <url> --platform ios, then snapshot -i --platform ios to verify project UI. Do not use plain snapshot or snapshot --diff for this recovery check. Android URL opens infer the foreground package for logs/perf when possible.',"Install flows: install/install-from-source first, then open the installed id with --relaunch.",'Text: fill \'id="field-email"\' "qa@example.com" replaces; type appends after press.','Clearing text: do not use fill <target> ""; use a visible clear/reset control or report that clearing is unsupported.',"Android IME capture: if fill says input was captured by the keyboard/IME, inspect keyboard state and switch/disable handwriting before retrying; do not loop fill/type.","Implicit default sessions are scoped to the current worktree; if a prompt names a Session, include --session <name> on every command in that flow.","Run mutating commands serially within one session; parallelize only read-only commands or separate sessions/devices.","Clipboard limits: iOS Allow Paste cannot be automated through XCUITest; prefill with clipboard write. Android non-ASCII should use fill/type, not raw adb input.","After mutation: refs are stale. If the next target is known, use its selector directly; otherwise refresh with snapshot -i, scoped with -s when a stable container is known. Do not use tap; use press or click.","Raw coordinates are fallback-only: use snapshot -i --json rects when iOS refs no-op or child refs are missing, then verify the action with diff snapshot -i or snapshot --diff.","Sparse or AX-unavailable snapshot: use screenshot for visual truth, press the visible coordinate to leave the bad screen, then retry AX with snapshot -i.","macOS context menus use click <ref> --button secondary, then snapshot -i. Longpress is for mobile hold gestures, not macOS secondary-click menus.","Remote lifecycle: use connect, then open, commands, close, and disconnect. Cloud, remote-config, direct proxy, and limrun use the same flow.","Direct proxy: run agent-device connect proxy --daemon-base-url <proxy-agent-device-url> before using a shared Mac proxy. Device leases are automatic on open and expire after five minutes of inactivity.",'Batch JSON steps use "command" and structured "input"; legacy "positionals"/"flags" steps still run in CLI but are deprecated until the next major version.',"Navigation: app-owned back uses back; system back uses back --system.","Web browser sessions: read help web; first slice is web setup if needed -> web doctor -> open <url> --platform web -> snapshot -i -> click/fill/get/is/find/wait/screenshot -> close.","Verification commands must name the expected text/selector; bare screenshots/snapshots are not enough.","Debug evidence: Session state contains request diagnostics and runner.log; use logs clear --restart/mark/path, trace, and network dump --include headers for app evidence.","Full operating guide: agent-device help workflow. Exploratory QA: agent-device help dogfood."],c=["Default config files: ~/.agent-device/config.json, ./agent-device.json","Use --config <path> or AGENT_DEVICE_CONFIG to load one explicit config file."],d=[{label:"AGENT_DEVICE_SESSION",description:"Explicit session name"},{label:"AGENT_DEVICE_PLATFORM",description:"Default platform binding"},{label:"AGENT_DEVICE_SESSION_LOCK",description:"Bound-session conflict mode"},{label:"AGENT_DEVICE_DAEMON_BASE_URL",description:"Connect to remote daemon"},{label:"AGENT_DEVICE_DAEMON_AUTH_TOKEN",description:"Remote daemon service/API token"},{label:"AGENT_DEVICE_CLOUD_BASE_URL",description:"Bridge/control-plane API origin for cloud auth and /api-keys"}],l=["agent-device open Settings --platform ios","agent-device open https://example.com --platform web","agent-device open TextEdit --platform macos","agent-device snapshot -i","agent-device react-devtools get tree --depth 3","agent-device cdp memory usage sample --gc --label baseline",'agent-device fill @e3 "test@example.com"',"agent-device replay ./session.ad","agent-device test ./suite --platform android"],p={workflow:{summary:"Normal agent-device bootstrap, exploration, and validation loop",body:`agent-device help workflow
2
2
 
3
3
  Version-matched operating guide for normal agent-device work.
4
4
 
@@ -28,7 +28,7 @@ Bootstrap:
28
28
  agent-device prepare ios-runner --platform ios --timeout 240000
29
29
  If app id is unknown, plan devices, apps, then open <discovered-app-id>. Discovery is not enough when the task asks to open/start the app.
30
30
  Install arguments are app/package id then artifact path. If the task says install, use install; use reinstall only when explicitly requested. Fresh runtime state is open --relaunch after install.
31
- In Apple CI, run prepare ios-runner after boot/install and before replay/test. prepare ios-runner builds/reuses the XCTest runner, health-checks it with a lightweight command, and retries one stuck/non-connecting runner launch before the first snapshot pays that setup cost. If the replay/test step starts a separate daemon, run clean:daemon after prepare so the prepared runner does not keep a live lease owned by the prepare daemon.
31
+ In Apple CI, run prepare ios-runner after boot/install and before replay/test. prepare ios-runner builds/reuses the XCTest runner, health-checks it with a lightweight command, and retries one stuck/non-connecting runner launch before the first snapshot pays that setup cost. It is not a recovery step for "runner already owned by another agent-device daemon"; stop or clean the owning daemon on the Mac with simulator access instead. If the replay/test step starts a separate daemon, run clean:daemon after prepare so the prepared runner does not keep a live lease owned by the prepare daemon.
32
32
  CI may cache ~/.agent-device/ios-runner/derived with an exact key that includes the agent-device package and Xcode version. Avoid broad restore-key fallbacks; prepare ios-runner already recovers bad restored runner artifacts and one retryable non-connecting runner launch. Runner build/start output is written to the session's runner.log; daemon.log is for daemon lifecycle/startup issues.
33
33
  Do not open artifact paths or invent package ids. If apps lookup misses the target and no URL/artifact is provided, ask or stop.
34
34
 
@@ -140,7 +140,9 @@ Validation and evidence:
140
140
  Android animations: settings animations off/on, not animations disable/restore.
141
141
  Debug logs: logs clear --restart, logs mark, reproduce, then logs path; do not split clear/restart into separate stop/start commands.
142
142
  Network headers: network dump --include headers; do not write network log headers.
143
- Remote/cloud: connect to discover a cloud profile, or connect --remote-config ./remote-config.json for a local profile; then open, snapshot, disconnect.
143
+ Remote lifecycle: cloud, remote-config, direct proxy, and limrun use the same flow: connect, open, commands, close, disconnect.
144
+ Remote config profile: agent-device connect --remote-config ./remote-config.json; then run normal commands and disconnect.
145
+ Direct proxy to a Mac you control: cloud/Linux clients can use local/proxy iOS devices through the proxied Mac. Run agent-device connect proxy --daemon-base-url <proxy-agent-device-url> first. Device leases are automatic on open and expire after five minutes of inactivity.
144
146
  Web: agent-device uses a managed, pinned agent-browser backend as an implementation detail. Use --platform web when a browser step belongs inside an agent-device session, replay, batch, MCP, or typed-client flow; use agent-browser directly for standalone web automation. Run agent-device web setup before first use, then agent-device web doctor for backend health checks. Web automation requires Node 24+.
145
147
  agent-device web setup
146
148
  agent-device web doctor
@@ -152,12 +154,14 @@ Validation and evidence:
152
154
  agent-device click @e12 --platform web
153
155
  agent-device fill @e13 "qa@example.com" --platform web
154
156
  agent-device wait text "Welcome" 3000 --platform web
157
+ agent-device record start ./artifacts/web-flow.webm --platform web
155
158
  agent-device network dump 25 --include headers --platform web
156
159
  agent-device screenshot ./artifacts/web-home.png --platform web
157
160
  agent-device screenshot ./artifacts/web-full.png --platform web --fullscreen
158
161
  agent-device viewport 1280 900 --platform web
162
+ agent-device record stop --platform web
159
163
  agent-device close --platform web
160
- Minimal web support is for browser sessions with open, snapshot, find, get, is, click/press, fill/type, wait, network dump, screenshot, close, and replay over those commands. Use agent-browser directly for browser-specific features that agent-device does not surface, such as tab/devtools management, advanced page scripting, network routing/HAR, or raw browser debugging.
164
+ Minimal web support is for browser sessions with open, snapshot, find, get, is, click/press, fill/type, wait, network dump, screenshot, record start/stop with WebM output, close, and replay over those commands. Use agent-browser directly for browser-specific features that agent-device does not surface, such as tab/devtools management, advanced page scripting, network routing/HAR, or raw browser debugging.
161
165
  macOS menu bar: open ... --platform macos --surface menubar; snapshot -i --platform macos --surface menubar.
162
166
  Maestro full-suite validation on explicit connected devices uses one test command with a comma-separated --device list and --shard-all. Use --shard-split only when splitting suite entries across devices:
163
167
  agent-device test ./e2e/maestro --maestro --device udid1,emulator-5554 --shard-all 2
@@ -343,7 +347,55 @@ Example:
343
347
  agent-device react-devtools profile report @c5
344
348
  agent-device network dump --include headers
345
349
 
346
- Use snapshot, screenshot, logs, network, and perf metrics for device/app runtime evidence. Use react-devtools only when component internals or React rendering behavior matters.`},"react-native":{summary:"React Native app automation hazards and routing",body:`agent-device help react-native
350
+ Use snapshot, screenshot, logs, network, and perf metrics for device/app runtime evidence. Use react-devtools only when component internals or React rendering behavior matters.`},cdp:{summary:"React Native CDP targets, JS heap snapshots, and leak triage",body:`agent-device help cdp
351
+
352
+ Use this when a React Native or Expo app exposes a CDP target through Metro and
353
+ the task needs JavaScript heap growth checks, heap snapshot diffs, allocation
354
+ hotspots, retained-object leak evidence, or a small runtime eval to confirm JS
355
+ state. Do not use this as the default React Native profiler.
356
+
357
+ Setup:
358
+ Start Metro and open the app first. For Android devices/emulators, make sure Metro is reachable from the app, typically with adb reverse tcp:8081 tcp:8081.
359
+ In remote bridge sessions, omit --url for target list/select after connect; agent-device derives the Metro CDP URL from the prepared remote runtime.
360
+ agent-device cdp target list --url http://127.0.0.1:8081
361
+ agent-device cdp target select <target-id>
362
+
363
+ Quick JS heap signal:
364
+ agent-device cdp memory usage sample --label baseline --gc
365
+ # perform the suspected leaking action with agent-device commands
366
+ agent-device cdp memory usage sample --label after-action --gc
367
+ agent-device cdp memory usage diff --base jm_1 --compare jm_2
368
+ agent-device cdp memory usage leak-signal --since jm_1
369
+
370
+ Retained-object proof:
371
+ agent-device cdp memory snapshot capture --name baseline --gc
372
+ # perform the suspected leaking action
373
+ agent-device cdp memory snapshot capture --name after-action --gc
374
+ # perform cleanup/navigation that should release the objects
375
+ agent-device cdp memory snapshot capture --name cleanup --gc
376
+ agent-device cdp memory snapshot diff --base ms_1 --compare ms_2 --limit 10
377
+ agent-device cdp memory snapshot leak-triplet --baseline ms_1 --action ms_2 --cleanup ms_3 --limit 10
378
+ agent-device cdp memory snapshot retainers --snapshot ms_3 --id <node-id> --depth 8 --limit 10
379
+
380
+ Allocation pressure:
381
+ Use allocation sampling to find where allocations were created, not to prove a leak:
382
+ agent-device cdp memory allocation start --name suspected-flow --interval 32768 --stack-depth 32
383
+ # perform the flow once
384
+ agent-device cdp memory allocation stop
385
+ agent-device cdp memory allocation hotspots --limit 10
386
+ agent-device cdp memory allocation source-maps
387
+
388
+ Recommended subset:
389
+ cdp dynamically runs a pinned CDP helper through npm; the first run may download the pinned package, and later runs can reuse the npm cache.
390
+ Every argument after cdp is passed to the CDP helper. Put agent-device global flags before cdp when you need the outer CLI to consume them.
391
+ Use cdp memory usage, memory snapshot, memory allocation, and targeted runtime eval.
392
+ Avoid cdp profile cpu, trace, network, and console by default because agent-device already has perf cpu, trace, network, logs, and react-devtools guidance for those areas.
393
+
394
+ Output contract:
395
+ Until cdp has a compact leak report command, synthesize one from memory usage diff, snapshot diff, leak-triplet, and retainers. Report heap deltas, top retained classes/shapes, leak-triplet rows that stayed high after cleanup, and the shortest useful retaining paths. Do not paste raw heap snapshots or large allocation profiles into the response; use exported artifacts only when the user asks for raw data.
396
+
397
+ Target caveats:
398
+ React Native/Hermes implements a subset of browser CDP. If a command reports an unsupported method, keep the target selected and switch to heap usage samples plus heap snapshots. Prefer react-devtools for component tree/render causes; prefer perf memory sample or perf memory snapshot for native/process memory.`},"react-native":{summary:"React Native app automation hazards and routing",body:`agent-device help react-native
347
399
 
348
400
  Use this when the target app is React Native, Expo, or a React Native dev client.
349
401
  This topic covers React Native-specific automation hazards and routes deeper
@@ -353,6 +405,7 @@ Choose the next help topic:
353
405
  Generic navigation, selectors, refs, verification, serial commands: help workflow.
354
406
  Logs, network, diagnostics, traces, permission dialogs, or runtime failures: help debugging.
355
407
  Component tree, props/state/hooks, slow renders, rerenders, or render causes: help react-devtools.
408
+ JS heap growth, heap snapshots, allocation hotspots, or retained-object leaks: help cdp.
356
409
  Remote/cloud config, leases, and local service tunnels: help remote.
357
410
 
358
411
  React Native dev loop:
@@ -361,7 +414,7 @@ React Native dev loop:
361
414
  agent-device metro reload
362
415
  agent-device find "Home"
363
416
  Do not use agent-device reload. Use open --relaunch for native startup reset.
364
- Android RN/Expo Metro: direct Android localhost URL opens with a port auto-configure host reachability. For app/package launches, use help react-native if the app cannot reach local Metro.
417
+ Android RN/Expo Metro: direct Android localhost URL opens with a port auto-configure host reachability. For app/package launches, run metro prepare when the app cannot reach local Metro.
365
418
  Verify Metro from the same host context that owns Metro. If a sandboxed shell cannot curl localhost:8081/status but an unrestricted host shell can, Metro is running and the sandbox probe is not authoritative.
366
419
  adb reverse only affects Android device-to-host traffic. It does not prove host-to-Metro reachability, and it does not fix a redbox caused by a stale or wrong Metro/app state.
367
420
  Multiple local worktrees can reuse one native iOS simulator build by running each worktree's Metro on a different port and opening the same installed app on different simulators with explicit runtime hints:
@@ -400,6 +453,11 @@ React DevTools routing:
400
453
  Use help react-devtools for status/wait, component trees, props/state/hooks, profile windows, slow renders, rerenders, and remote bridge rules.
401
454
  If React DevTools cannot connect, report status and continue with logs, network, perf metrics, screenshot, and trace evidence instead of blocking the whole flow.
402
455
 
456
+ CDP memory routing:
457
+ Keep the agent-device cdp prefix on every CDP command.
458
+ Use help cdp for JS heap usage samples, heap snapshots, snapshot diffs, leak-triplet analysis, allocation hotspots, and retained-object paths.
459
+ Use perf memory sample or perf memory snapshot for native/process memory; use cdp only for JavaScript heap evidence.
460
+
403
461
  Slow-flow investigation:
404
462
  Keep one session, open the app first, and snapshot -i before interacting.
405
463
  Start React Native slow-flow plans with this ordered scaffold:
@@ -438,9 +496,27 @@ iOS physical-device prerequisites:
438
496
 
439
497
  Android physical-device prerequisites:
440
498
  Enable USB debugging and confirm the device appears in agent-device devices --platform android.
441
- Android does not need the iOS runner signing setup. For React Native/Expo Metro reachability, read help react-native.`},remote:{summary:"Remote config, tenant, lease, and remote host flow",body:`agent-device help remote
499
+ Android does not need the iOS runner signing setup. For React Native/Expo Metro reachability, read help react-native.`},remote:{summary:"Direct proxy, cloud profiles, and remote config",body:`agent-device help remote
500
+
501
+ Remote connection providers use the same lifecycle:
502
+ connect -> open -> commands -> close -> disconnect
442
503
 
443
- Use remote config or the cloud connection profile when a profile owns daemon URL, auth, tenant, run, lease, device scope, and Metro hints. Do not restate those as individual flags unless overriding intentionally.
504
+ Providers:
505
+ Cloud: agent-device connect discovers the cloud profile.
506
+ Remote config: agent-device connect --remote-config ./remote-config.json uses a local profile.
507
+ Direct proxy: agent-device connect proxy --daemon-base-url <proxy-agent-device-url> stores the shared proxy profile and client identity.
508
+
509
+ Direct proxy flow for a remote Mac/simulator:
510
+ On the Mac with simulator/device access:
511
+ agent-device proxy --port 4310
512
+ cloudflared tunnel --url http://127.0.0.1:4310
513
+ On the remote client:
514
+ agent-device connect proxy --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>
515
+ agent-device devices --platform ios
516
+ agent-device open Maps --platform ios --device "iPhone 17 Pro"
517
+ agent-device snapshot -i --platform ios --device "iPhone 17 Pro"
518
+ agent-device close
519
+ agent-device disconnect
444
520
 
445
521
  Cloud profile flow:
446
522
  agent-device connect
@@ -459,21 +535,17 @@ Script flow, per-command config:
459
535
  agent-device snapshot --remote-config ./remote-config.json
460
536
  agent-device disconnect --remote-config ./remote-config.json
461
537
 
462
- Direct proxy flow for a remote Mac:
463
- On the Mac with simulator/device access:
464
- agent-device proxy --port 4310
465
- cloudflared tunnel --url http://127.0.0.1:4310
466
- On the remote client:
467
- agent-device devices --daemon-base-url https://example.trycloudflare.com/agent-device --daemon-auth-token <token>
468
- agent-device devices
469
-
470
538
  Rules:
471
539
  connect and disconnect are top-level commands. Do not write agent-device remote connect or agent-device remote disconnect.
472
540
  Use connect without --remote-config when the cloud control plane owns the connection profile.
473
- Prefer --remote-config over --daemon-base-url, --tenant, --run-id, and --lease-id when using a local profile.
474
- Use agent-device proxy for direct tunnel access to a Mac you control. Copy the printed daemon base URL and daemon auth token; do not use agent-device auth for this direct proxy flow.
475
- For repeated direct proxy commands, store daemonBaseUrl and daemonAuthToken in normal agent-device.json CLI config. Keep platform selection on each command or workflow. Do not use --remote-config unless you are using the tenant/run/lease remote connection flow.
541
+ Prefer connect --remote-config over --daemon-base-url, --tenant, --run-id, and --lease-id when using a local profile.
542
+ Use agent-device proxy for direct tunnel access to a Mac you control. Expose the printed proxy URL through cloudflared/ngrok, then run agent-device connect proxy with the tunnel URL and printed token before normal commands.
543
+ connect proxy stores the connection profile and client identity. Device leases are acquired on open and expire after five minutes without commands.
544
+ Multiple agents can share one proxy when each uses connect proxy, open, commands, close, and disconnect.
545
+ disconnect releases local connection state; close releases the active session and device lease.
546
+ A busy direct-proxy device error means another agent owns the device until it closes or its inactivity lease expires.
476
547
  Keep the proxy token secret. Anyone with the token can control the proxied daemon.
548
+ If local/proxy iOS reports that the runner is already owned by another agent-device daemon after lease admission, retry after the owning session closes or after lease expiry. If the conflict repeats, clean stale daemon state on the machine with simulator access.
477
549
  Do not use --config as a remote profile flag. --config loads CLI defaults; --remote-config selects remote daemon/profile settings.
478
550
  For self-contained scripts, pass the same --remote-config to every operational command, including disconnect; a preceding connect is optional but not required.
479
551
  For remote artifact installs, use install-from-source <url> or install-from-source --github-actions-artifact org/repo:artifact; do not download CI artifacts locally first.
@@ -533,14 +605,16 @@ First-slice loop:
533
605
  agent-device click @e12 --platform web
534
606
  agent-device fill @e13 "qa@example.com" --platform web
535
607
  agent-device wait text "Welcome" 3000 --platform web
608
+ agent-device record start ./artifacts/web-flow.webm --platform web
536
609
  agent-device network dump 25 --include headers --platform web
537
610
  agent-device screenshot ./artifacts/web-home.png --platform web
538
611
  agent-device screenshot ./artifacts/web-full.png --platform web --fullscreen
539
612
  agent-device viewport 1280 900 --platform web
613
+ agent-device record stop --platform web
540
614
  agent-device close --platform web
541
615
 
542
616
  Supported in agent-device web sessions:
543
- open <url>, snapshot -i, get text/attrs, is visible/exists/text, find text/selector, click/press @ref or selector, fill/type @ref or selector, wait text/selector, network dump, screenshot, close, and replay scripts made from those commands.
617
+ open <url>, snapshot -i, get text/attrs, is visible/exists/text, find text/selector, click/press @ref or selector, fill/type @ref or selector, wait text/selector, network dump, screenshot, record start/stop with WebM output, close, and replay scripts made from those commands.
544
618
 
545
619
  Out of scope for agent-device web support:
546
620
  Browser runtime debugging, tabs/windows/devtools control, network routing/interception/HAR, storage/cookie management, arbitrary page scripting, downloads/uploads, multi-page orchestration, and agent-browser-specific diagnostics. Use agent-browser directly for those browser-specific workflows.
@@ -605,37 +679,39 @@ Rules:
605
679
  Prefer refs for exploration and selectors for deterministic replay.
606
680
  Use logs, network, screenshot --overlay-refs, trace, perf metrics, perf frames, or react-devtools only when they add evidence to a specific issue.
607
681
  Never delete screenshots, videos, traces, or report artifacts during a session.
608
- Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`}};function p(e){let t=e.endsWith("?"),o=t?e.slice(0,-1):e;return t?`[${o}]`:`<${o}>`}function u(){let o,a,d,p,u,v,b,w;return o=`agent-device <command> [args] [--json]
682
+ Escalate to help debugging or help react-devtools when runtime symptoms require those tools.`}};function h(e){let t=e.endsWith("?"),a=t?e.slice(0,-1):e;return t?`[${a}]`:`<${a}>`}function u(){let a,o,p,h,u,b,w,y,k;return a=`agent-device <command> [args] [--json]
683
+
684
+ CLI to automate supported app, device, desktop, and web targets for AI agents.
685
+ `,o=g("Commands:",e().map(e=>{let a=t(e);return{name:e,schema:a,usage:function(e,t){if(t.listUsageOverride)return t.listUsageOverride;let a=(t.positionalArgs??[]).map(a=>{var o,s,n;let r,i,c,d;return o=e,s=t,i=(r=(n=a).endsWith("?"))?n.slice(0,-1):n,d=(c=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i))||void 0!==s.usageOverride&&s.usageOverride.startsWith(`${o} ${i}`),r?c?`[${i}]`:d?i:`[${i}]`:d?i:`<${i}>`});return[e,...a].join(" ")}(e,a)}}).map(e=>({label:e.usage,description:e.schema.summary??e.schema.helpDescription}))),p=f("Global Flags:",m(s)),h=v("Agent Starting Point:",r),u=v("Agent Quickstart:",i),b=g("Agent Workflows:",n),w=v("Configuration:",c),y=g("Environment:",d),k=v("Examples:",l),`${a}
686
+ ${h}
609
687
 
610
- CLI to control iOS and Android devices for AI agents.
611
- `,a=m("Commands:",e().map(e=>{let o=t(e);return{name:e,schema:o,usage:function(e,t){if(t.listUsageOverride)return t.listUsageOverride;let o=(t.positionalArgs??[]).map(o=>{var a,s,n;let r,i,c,l;return a=e,s=t,i=(r=(n=o).endsWith("?"))?n.slice(0,-1):n,l=(c=/^[a-z-]+(?:\|[a-z-]+)+$/i.test(i))||void 0!==s.usageOverride&&s.usageOverride.startsWith(`${a} ${i}`),r?c?`[${i}]`:l?i:`[${i}]`:l?i:`<${i}>`});return[e,...o].join(" ")}(e,o)}}).map(e=>({label:e.usage,description:e.schema.summary??e.schema.helpDescription}))),d=f("Global Flags:",h(s)),p=g("Agent Quickstart:",r),u=m("Agent Workflows:",n),v=g("Configuration:",i),b=m("Environment:",c),w=g("Examples:",l),`${o}
612
- ${a}
688
+ ${b}
613
689
 
614
- ${d}
690
+ ${o}
615
691
 
616
692
  ${p}
617
693
 
618
694
  ${u}
619
695
 
620
- ${v}
696
+ ${w}
621
697
 
622
- ${b}
698
+ ${y}
623
699
 
624
- ${w}
625
- `}function h(e){return a().filter(t=>e.has(t.key)&&void 0!==t.usageLabel&&void 0!==t.usageDescription)}function f(e,t){return m(e,t.map(e=>({label:e.usageLabel??"",description:e.usageDescription??""})))}function m(e,t){if(0===t.length)return`${e}
626
- (none)`;let o=Math.max(...t.map(e=>e.label.length))+2,a=[e];for(let e of t)a.push(` ${e.label.padEnd(o)}${e.description}`);return a.join("\n")}function g(e,t){return 0===t.length?`${e}
627
- (none)`:[e,...t.map(e=>` ${e}`)].join("\n")}function v(e){var t,s;let n,r=(n=d[e])?`${n.body}
700
+ ${k}
701
+ `}function m(e){return o().filter(t=>e.has(t.key)&&void 0!==t.usageLabel&&void 0!==t.usageDescription)}function f(e,t){return g(e,t.map(e=>({label:e.usageLabel??"",description:e.usageDescription??""})))}function g(e,t){if(0===t.length)return`${e}
702
+ (none)`;let a=Math.max(...t.map(e=>e.label.length))+2,o=[e];for(let e of t)o.push(` ${e.label.padEnd(a)}${e.description}`);return o.join("\n")}function v(e,t){return 0===t.length?`${e}
703
+ (none)`:[e,...t.map(e=>` ${e}`)].join("\n")}function b(e){var t,s;let n,r=(n=p[e])?`${n.body}
628
704
 
629
705
  Related:
630
706
  agent-device help command list and global flags
631
707
  agent-device help <command> command-specific flags
632
708
  agent-device help workflow normal app automation loop
633
- `:null;if(r)return r;let i=o(e);if(!i)return null;let c=(t=e,(s=i).usageOverride?s.usageOverride:[t,...(s.positionalArgs??[]).map(p),...(s.allowedFlags??[]).flatMap(e=>{var t;return(t=e,a().filter(e=>e.key===t)).map(e=>e.usageLabel??e.names[0])}).map(e=>`[${e}]`)].join(" ")),l=h(new Set(i.allowedFlags??[])),u=[];l.length>0&&u.push(f("Command flags:",l));let m=u.length>0?`
709
+ `:null;if(r)return r;let i=a(e);if(!i)return null;let c=(t=e,(s=i).usageOverride?s.usageOverride:[t,...(s.positionalArgs??[]).map(h),...(s.allowedFlags??[]).flatMap(e=>{var t;return(t=e,o().filter(e=>e.key===t)).map(e=>e.usageLabel??e.names[0])}).map(e=>`[${e}]`)].join(" ")),d=m(new Set(i.allowedFlags??[])),l=[];d.length>0&&l.push(f("Command flags:",d));let u=l.length>0?`
634
710
 
635
- ${u.join("\n\n")}`:"";return`agent-device ${c}
711
+ ${l.join("\n\n")}`:"";return`agent-device ${c}
636
712
 
637
713
  ${i.helpDescription}
638
714
 
639
715
  Usage:
640
- agent-device ${c}${m}
641
- `}export{v as buildCommandUsageText,u as buildUsageText};
716
+ agent-device ${c}${u}
717
+ `}export{b as buildCommandUsageText,u as buildUsageText};