agent-device 0.12.8 → 0.13.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.
- package/README.md +20 -1
- package/dist/src/1974.js +2 -2
- package/dist/src/3883.js +1 -1
- package/dist/src/3918.js +28 -28
- package/dist/src/4829.js +1 -0
- package/dist/src/7847.js +1 -1
- package/dist/src/9076.js +1 -1
- package/dist/src/9152.js +1 -1
- package/dist/src/9323.js +5 -5
- package/dist/src/9542.js +2 -2
- package/dist/src/989.js +1 -1
- package/dist/src/bin.js +33 -33
- package/dist/src/commands/index.d.ts +4 -1
- package/dist/src/contracts.d.ts +3 -1
- package/dist/src/daemon.js +13 -13
- package/dist/src/index.d.ts +22 -11
- package/dist/src/metro.d.ts +9 -11
- package/package.json +20 -3
- package/skills/agent-device/SKILL.md +2 -1
- package/skills/agent-device/references/debugging.md +3 -1
- package/skills/agent-device/references/exploration.md +5 -2
- package/skills/agent-device/references/remote-tenancy.md +9 -6
- package/skills/agent-device/references/verification.md +6 -2
- package/skills/dogfood/SKILL.md +1 -0
- package/skills/react-devtools/SKILL.md +53 -0
- package/skills/react-devtools/references/commands.md +91 -0
- package/skills/react-devtools/references/profiling.md +74 -0
package/dist/src/index.d.ts
CHANGED
|
@@ -414,7 +414,7 @@ export declare class AppError extends Error {
|
|
|
414
414
|
constructor(code: AppErrorCode, message: string, details?: AppErrorDetails, cause?: unknown);
|
|
415
415
|
}
|
|
416
416
|
|
|
417
|
-
export declare type AppErrorCode =
|
|
417
|
+
export declare type AppErrorCode = KnownAppErrorCode | (string & {});
|
|
418
418
|
|
|
419
419
|
declare type AppErrorDetails = Record<string, unknown> & {
|
|
420
420
|
hint?: string;
|
|
@@ -1053,6 +1053,7 @@ export declare type CaptureScreenshotOptions = AgentDeviceRequestOverrides & {
|
|
|
1053
1053
|
path?: string;
|
|
1054
1054
|
overlayRefs?: boolean;
|
|
1055
1055
|
fullscreen?: boolean;
|
|
1056
|
+
maxSize?: number;
|
|
1056
1057
|
surface?: 'app' | 'frontmost-app' | 'desktop' | 'menubar';
|
|
1057
1058
|
};
|
|
1058
1059
|
|
|
@@ -1082,6 +1083,8 @@ export declare type CaptureSnapshotResult = {
|
|
|
1082
1083
|
|
|
1083
1084
|
export declare function centerOfRect(rect: Rect): Point;
|
|
1084
1085
|
|
|
1086
|
+
declare type ClickButton = 'primary' | 'secondary' | 'middle';
|
|
1087
|
+
|
|
1085
1088
|
declare type ClickCommandOptions = PressCommandOptions;
|
|
1086
1089
|
|
|
1087
1090
|
export declare type ClickOptions = ClientCommandBaseOptions & SelectorSnapshotCommandOptions & InteractionTarget & RepeatedPressOptions & {
|
|
@@ -1645,8 +1648,6 @@ declare type FindBaseOptions = ClientCommandBaseOptions & FindSnapshotCommandOpt
|
|
|
1645
1648
|
|
|
1646
1649
|
export declare type FindLocator = 'any' | 'text' | 'label' | 'value' | 'role' | 'id';
|
|
1647
1650
|
|
|
1648
|
-
declare type FindLocator_2 = 'any' | 'text' | 'label' | 'value' | 'role' | 'id';
|
|
1649
|
-
|
|
1650
1651
|
export declare type FindOptions = (FindBaseOptions & {
|
|
1651
1652
|
action?: 'click' | 'focus' | 'exists' | 'getText' | 'getAttrs';
|
|
1652
1653
|
}) | (FindBaseOptions & {
|
|
@@ -1658,7 +1659,7 @@ export declare type FindOptions = (FindBaseOptions & {
|
|
|
1658
1659
|
});
|
|
1659
1660
|
|
|
1660
1661
|
declare type FindReadCommandOptions = CommandContext & {
|
|
1661
|
-
locator?:
|
|
1662
|
+
locator?: FindLocator;
|
|
1662
1663
|
query: string;
|
|
1663
1664
|
action: Extract<FindAction['kind'], 'exists' | 'wait' | 'get_text' | 'get_attrs'>;
|
|
1664
1665
|
timeoutMs?: number;
|
|
@@ -1796,6 +1797,8 @@ export declare type KeyboardCommandResult = DaemonResponseData & {
|
|
|
1796
1797
|
attempts?: number;
|
|
1797
1798
|
};
|
|
1798
1799
|
|
|
1800
|
+
declare type KnownAppErrorCode = 'INVALID_ARGS' | 'DEVICE_NOT_FOUND' | 'DEVICE_IN_USE' | 'TOOL_MISSING' | 'APP_NOT_INSTALLED' | 'UNSUPPORTED_PLATFORM' | 'UNSUPPORTED_OPERATION' | 'NOT_IMPLEMENTED' | 'COMMAND_FAILED' | 'SESSION_NOT_FOUND' | 'UNAUTHORIZED' | 'AMBIGUOUS_MATCH' | 'UNKNOWN';
|
|
1801
|
+
|
|
1799
1802
|
declare type Lease = {
|
|
1800
1803
|
leaseId: string;
|
|
1801
1804
|
tenantId: string;
|
|
@@ -1899,19 +1902,21 @@ declare type MetroBridgeResult = {
|
|
|
1899
1902
|
};
|
|
1900
1903
|
};
|
|
1901
1904
|
|
|
1905
|
+
declare type MetroBridgeScope = {
|
|
1906
|
+
tenantId: string;
|
|
1907
|
+
runId: string;
|
|
1908
|
+
leaseId: string;
|
|
1909
|
+
};
|
|
1910
|
+
|
|
1902
1911
|
declare type MetroPrepareKind = 'auto' | 'react-native' | 'expo';
|
|
1903
1912
|
|
|
1904
1913
|
export declare type MetroPrepareOptions = {
|
|
1905
1914
|
projectRoot?: string;
|
|
1906
1915
|
kind?: MetroPrepareKind;
|
|
1907
|
-
publicBaseUrl
|
|
1916
|
+
publicBaseUrl?: string;
|
|
1908
1917
|
proxyBaseUrl?: string;
|
|
1909
1918
|
bearerToken?: string;
|
|
1910
|
-
bridgeScope?:
|
|
1911
|
-
tenantId: string;
|
|
1912
|
-
runId: string;
|
|
1913
|
-
leaseId: string;
|
|
1914
|
-
};
|
|
1919
|
+
bridgeScope?: MetroBridgeScope;
|
|
1915
1920
|
launchUrl?: string;
|
|
1916
1921
|
companionProfileKey?: string;
|
|
1917
1922
|
companionConsumerKey?: string;
|
|
@@ -2030,7 +2035,7 @@ declare type PrepareMetroRuntimeResult = {
|
|
|
2030
2035
|
|
|
2031
2036
|
declare type PressCommandOptions = CommandContext & {
|
|
2032
2037
|
target: InteractionTarget_2;
|
|
2033
|
-
button?:
|
|
2038
|
+
button?: ClickButton;
|
|
2034
2039
|
count?: number;
|
|
2035
2040
|
intervalMs?: number;
|
|
2036
2041
|
holdMs?: number;
|
|
@@ -2159,11 +2164,13 @@ declare type RepeatedPressOptions = {
|
|
|
2159
2164
|
export declare type ReplayRunOptions = AgentDeviceRequestOverrides & {
|
|
2160
2165
|
path: string;
|
|
2161
2166
|
update?: boolean;
|
|
2167
|
+
env?: string[];
|
|
2162
2168
|
};
|
|
2163
2169
|
|
|
2164
2170
|
export declare type ReplayTestOptions = AgentDeviceRequestOverrides & AgentDeviceSelectionOptions & {
|
|
2165
2171
|
paths: string[];
|
|
2166
2172
|
update?: boolean;
|
|
2173
|
+
env?: string[];
|
|
2167
2174
|
failFast?: boolean;
|
|
2168
2175
|
timeoutMs?: number;
|
|
2169
2176
|
retries?: number;
|
|
@@ -2244,6 +2251,7 @@ declare type ScreenshotCommandOptions = CommandContext & {
|
|
|
2244
2251
|
out?: FileOutputRef;
|
|
2245
2252
|
fullscreen?: boolean;
|
|
2246
2253
|
overlayRefs?: boolean;
|
|
2254
|
+
maxSize?: number;
|
|
2247
2255
|
appId?: string;
|
|
2248
2256
|
appBundleId?: string;
|
|
2249
2257
|
surface?: 'app' | 'frontmost-app' | 'desktop' | 'menubar';
|
|
@@ -2446,6 +2454,9 @@ declare type SessionRuntimeHints = {
|
|
|
2446
2454
|
export declare type SettingsUpdateOptions = (ClientCommandBaseOptions & {
|
|
2447
2455
|
setting: 'wifi' | 'airplane' | 'location';
|
|
2448
2456
|
state: 'on' | 'off';
|
|
2457
|
+
}) | (ClientCommandBaseOptions & {
|
|
2458
|
+
setting: 'animations';
|
|
2459
|
+
state: 'on' | 'off';
|
|
2449
2460
|
}) | (ClientCommandBaseOptions & {
|
|
2450
2461
|
setting: 'appearance';
|
|
2451
2462
|
state: 'light' | 'dark' | 'toggle';
|
package/dist/src/metro.d.ts
CHANGED
|
@@ -11,11 +11,7 @@ export declare type EnsureMetroTunnelOptions = {
|
|
|
11
11
|
serverBaseUrl: string;
|
|
12
12
|
bearerToken: string;
|
|
13
13
|
localBaseUrl: string;
|
|
14
|
-
bridgeScope:
|
|
15
|
-
tenantId: string;
|
|
16
|
-
runId: string;
|
|
17
|
-
leaseId: string;
|
|
18
|
-
};
|
|
14
|
+
bridgeScope: MetroBridgeScope;
|
|
19
15
|
launchUrl?: string;
|
|
20
16
|
profileKey?: string;
|
|
21
17
|
consumerKey?: string;
|
|
@@ -79,6 +75,12 @@ export declare type MetroBridgeRuntimePayload = {
|
|
|
79
75
|
launch_url?: string;
|
|
80
76
|
};
|
|
81
77
|
|
|
78
|
+
declare type MetroBridgeScope = {
|
|
79
|
+
tenantId: string;
|
|
80
|
+
runId: string;
|
|
81
|
+
leaseId: string;
|
|
82
|
+
};
|
|
83
|
+
|
|
82
84
|
/** Re-export of {@link SessionRuntimeHints} under the Metro-specific alias used by public API consumers. */
|
|
83
85
|
export declare type MetroRuntimeHints = SessionRuntimeHints;
|
|
84
86
|
|
|
@@ -157,14 +159,10 @@ export declare function prepareRemoteMetro(options: PrepareRemoteMetroOptions):
|
|
|
157
159
|
export declare type PrepareRemoteMetroOptions = {
|
|
158
160
|
projectRoot: string;
|
|
159
161
|
kind: 'auto' | 'react-native' | 'expo';
|
|
160
|
-
publicBaseUrl
|
|
162
|
+
publicBaseUrl?: string;
|
|
161
163
|
proxyBaseUrl?: string;
|
|
162
164
|
proxyBearerToken?: string;
|
|
163
|
-
bridgeScope?:
|
|
164
|
-
tenantId: string;
|
|
165
|
-
runId: string;
|
|
166
|
-
leaseId: string;
|
|
167
|
-
};
|
|
165
|
+
bridgeScope?: MetroBridgeScope;
|
|
168
166
|
launchUrl?: string;
|
|
169
167
|
profileKey?: string;
|
|
170
168
|
consumerKey?: string;
|
package/package.json
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-device",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.13.0",
|
|
4
|
+
"description": "Agent-driven CLI for mobile UI automation, network inspection, and performance diagnostics across iOS, Android, tvOS, and macOS.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Callstack",
|
|
7
|
+
"homepage": "https://agent-device.dev/",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/callstackincubator/agent-device.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/callstackincubator/agent-device/issues"
|
|
14
|
+
},
|
|
7
15
|
"type": "module",
|
|
8
16
|
"main": "dist/src/index.js",
|
|
9
17
|
"types": "dist/src/index.d.ts",
|
|
@@ -120,11 +128,20 @@
|
|
|
120
128
|
"agent",
|
|
121
129
|
"device",
|
|
122
130
|
"cli",
|
|
131
|
+
"automation",
|
|
123
132
|
"adb",
|
|
124
133
|
"simctl",
|
|
125
134
|
"devicectl",
|
|
126
135
|
"ios",
|
|
127
|
-
"android"
|
|
136
|
+
"android",
|
|
137
|
+
"tvos",
|
|
138
|
+
"macos",
|
|
139
|
+
"react-native",
|
|
140
|
+
"observability",
|
|
141
|
+
"diagnostics",
|
|
142
|
+
"network",
|
|
143
|
+
"profiling",
|
|
144
|
+
"performance"
|
|
128
145
|
],
|
|
129
146
|
"dependencies": {
|
|
130
147
|
"fast-xml-parser": "^5.5.10",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: agent-device
|
|
3
|
-
description: Automates interactions for Apple-platform apps (iOS, tvOS, macOS) and Android devices. Use when navigating apps, taking snapshots/screenshots, tapping, typing, scrolling,
|
|
3
|
+
description: Automates interactions for Apple-platform apps (iOS, tvOS, macOS) and Android devices. Use when navigating apps, taking snapshots/screenshots, tapping, typing, scrolling, extracting UI info, or collecting logs, network inspection, and perf snapshots across mobile, TV, and desktop targets.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# agent-device
|
|
@@ -71,3 +71,4 @@ Use this skill as a router with mandatory defaults. Read this file first. For no
|
|
|
71
71
|
- Need desktop surfaces, menu bar behavior, or macOS-specific interaction rules: [references/macos-desktop.md](references/macos-desktop.md)
|
|
72
72
|
- Need remote HTTP transport, `connect --remote-config`, or tenant leases on a remote macOS host: [references/remote-tenancy.md](references/remote-tenancy.md)
|
|
73
73
|
This includes remote React Native runs where `agent-device` now prepares Metro locally and manages the local Metro companion tunnel automatically.
|
|
74
|
+
- Need the React Native component tree, props, state, hooks, or render profiling: use `agent-device react-devtools ...` and the [react-devtools skill](../react-devtools/SKILL.md).
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
Open this file when the task turns into failure triage, logs, network inspection, permission prompts, setup trouble, or unstable session behavior.
|
|
6
6
|
|
|
7
|
+
If the debugging task needs the React Native component tree, props, state, hooks, or render profiling, use `agent-device react-devtools ...` and the `skills/react-devtools` workflow instead of trying to infer those internals from the accessibility tree or app logs alone.
|
|
8
|
+
|
|
7
9
|
## Main commands to reach for first
|
|
8
10
|
|
|
9
11
|
- `logs clear --restart`
|
|
@@ -111,7 +113,7 @@ agent-device alert accept
|
|
|
111
113
|
- `snapshot` returns 0 nodes: the app may no longer be foregrounded or the UI is not stable yet. Re-open the app or retry when state settles.
|
|
112
114
|
- Logs are empty: confirm you opened an app session before `logs clear --restart`.
|
|
113
115
|
- Android logs look stale after relaunch: retry the repro window after the process rebinds.
|
|
114
|
-
- Android accessibility snapshots can lag behind visible screen transitions. The next snapshot
|
|
116
|
+
- Android accessibility snapshots can lag behind visible screen transitions. The next snapshot retries suspicious trees for a short post-action deadline after navigation-sensitive actions, and `@ref` actions refresh while that window is active. If the tree still looks stale, use `screenshot` as visual truth, wait briefly, then re-run `snapshot -i`. For animation-heavy runs, try `settings animations off` and restore with `settings animations on`.
|
|
115
117
|
- React Native dev warnings or errors keep reappearing: treat them as part of the app state, not as disposable chrome. Capture one clean repro and include them in the summary.
|
|
116
118
|
- Permission prompts block the flow: wait for the alert and handle it explicitly.
|
|
117
119
|
- If snapshots keep returning 0 nodes on an iOS simulator, restart Simulator and re-open the app.
|
|
@@ -20,6 +20,7 @@ Open this file when the app or screen is already running and you need to discove
|
|
|
20
20
|
- User asks what is visible on screen: `snapshot`
|
|
21
21
|
- User asks for exact text from a known target: `get text`
|
|
22
22
|
- User asks you to tap, type, or choose an element: `snapshot -i`, then act
|
|
23
|
+
- User asks for the React Native component tree, props/state/hooks, or render profiling: use `agent-device react-devtools ...` and the `skills/react-devtools` workflow
|
|
23
24
|
- React Native dev or debug build shows warning/error UI: capture enough evidence to identify it, dismiss it if it is not the requested behavior, then continue the flow and report it in the summary
|
|
24
25
|
- The on-screen keyboard is blocking the next step: `keyboard dismiss`; on iOS do this only while an app session is active, and use `keyboard status|get` only on Android
|
|
25
26
|
- UI does not expose the answer: say so plainly; do not browse or force the app into a new state unless asked
|
|
@@ -49,8 +50,9 @@ Open this file when the app or screen is already running and you need to discove
|
|
|
49
50
|
**Android AX tree lag.** After submits, route changes, or composer transitions, the accessibility tree can lag behind the visible UI. If `snapshot -i` and `screenshot` disagree:
|
|
50
51
|
|
|
51
52
|
1. Trust the screenshot as visual truth.
|
|
52
|
-
2. Take one fresh `snapshot -i`. Android retries
|
|
53
|
+
2. Take one fresh `snapshot -i`. Android retries suspicious trees for a short post-action deadline after navigation-sensitive actions.
|
|
53
54
|
3. If the tree still disagrees with the screenshot, wait briefly, then take one more fresh snapshot. Do not loop snapshots immediately.
|
|
55
|
+
4. For animation-heavy Android runs, use `settings animations off` as an opt-in stabilizer and restore with `settings animations on` after the run.
|
|
54
56
|
|
|
55
57
|
**React Native dev overlays.** In dev or debug builds, warning or error overlays can block taps, change focus, or hide the real UI. Check for them near app open and after major transitions.
|
|
56
58
|
|
|
@@ -222,7 +224,7 @@ Preferred mapping:
|
|
|
222
224
|
Notes:
|
|
223
225
|
|
|
224
226
|
- `wait text` is useful for synchronizing on text presence, but it is not the same as `is visible`.
|
|
225
|
-
- After a nearby navigation or submit on Android, prefer `screenshot`, then
|
|
227
|
+
- After a nearby navigation or submit on Android, prefer `screenshot`, then one fresh `snapshot -i`; `@ref` interactions refresh while the Android freshness window is active.
|
|
226
228
|
|
|
227
229
|
Anti-hallucination rules:
|
|
228
230
|
|
|
@@ -338,6 +340,7 @@ Common batch error categories:
|
|
|
338
340
|
- `SESSION_NOT_FOUND`: open or select the correct session, then retry.
|
|
339
341
|
- `UNSUPPORTED_OPERATION`: switch to a supported command or surface.
|
|
340
342
|
- `AMBIGUOUS_MATCH`: refine the selector or locator, then retry the failed step.
|
|
343
|
+
- `DEVICE_IN_USE`: the device is held by another session — close or reuse the existing session before retrying.
|
|
341
344
|
- `COMMAND_FAILED`: add sync guards and retry from the failing step.
|
|
342
345
|
|
|
343
346
|
## Stop conditions
|
|
@@ -103,8 +103,8 @@ Example `remote-config.json` shape:
|
|
|
103
103
|
"tenant": "acme",
|
|
104
104
|
"runId": "run-123",
|
|
105
105
|
"sessionIsolation": "tenant",
|
|
106
|
-
"platform": "
|
|
107
|
-
"
|
|
106
|
+
"platform": "ios",
|
|
107
|
+
"metroProxyBaseUrl": "https://bridge.example.com"
|
|
108
108
|
}
|
|
109
109
|
```
|
|
110
110
|
|
|
@@ -112,11 +112,11 @@ Optional overrides stay available for advanced cases:
|
|
|
112
112
|
|
|
113
113
|
```json
|
|
114
114
|
{
|
|
115
|
-
"session": "adc-
|
|
116
|
-
"leaseBackend": "
|
|
115
|
+
"session": "adc-ios",
|
|
116
|
+
"leaseBackend": "ios-instance",
|
|
117
117
|
"metroProjectRoot": ".",
|
|
118
118
|
"metroKind": "expo",
|
|
119
|
-
"
|
|
119
|
+
"metroPublicBaseUrl": "http://127.0.0.1:8081"
|
|
120
120
|
}
|
|
121
121
|
```
|
|
122
122
|
|
|
@@ -124,7 +124,10 @@ Optional overrides stay available for advanced cases:
|
|
|
124
124
|
- Omit Metro fields for non-React Native flows.
|
|
125
125
|
- Put `tenant`, `runId`, and `sessionIsolation` in the remote profile so agents can run `agent-device connect --remote-config ./remote-config.json` without extra scope flags. Add `platform`, `leaseBackend`, `session`, or Metro overrides only when the default inference is not enough for that flow.
|
|
126
126
|
- Explicit command-line flags override connected defaults. Use them intentionally when switching session, platform, target, tenant, run, or lease scope.
|
|
127
|
-
- For React Native Metro runs with `metroProxyBaseUrl`, `agent-device >= 0.11.12` can manage the local companion tunnel, but Metro itself still needs to be running locally.
|
|
127
|
+
- For React Native Metro runs with `metroProxyBaseUrl`, `agent-device >= 0.11.12` can manage the local companion tunnel, but Metro itself still needs to be running locally. `metroProxyBaseUrl` is the bridge origin, not a prebuilt `/api/metro/...` route.
|
|
128
|
+
- For cloud stock React Native iOS, use the bridge descriptor's wildcard HTTPS Metro hints directly; do not install or launch the XCTest runner just to make Metro reachable.
|
|
129
|
+
- Android keeps using bridge-provided `/api/metro/runtimes/<runtimeId>/...` Metro routes.
|
|
130
|
+
- `metroPublicBaseUrl` is only needed for direct/non-bridge bundle hints. Bridged profiles can omit it.
|
|
128
131
|
- Use a lease backend that matches the bridge target platform, for example `android-instance`, `ios-instance`, or an explicit `--lease-backend` override.
|
|
129
132
|
|
|
130
133
|
## Transport prerequisites
|
|
@@ -46,7 +46,10 @@ agent-device diff snapshot -i
|
|
|
46
46
|
|
|
47
47
|
Use `screenshot` when the proof needs a rendered image instead of a structural tree.
|
|
48
48
|
|
|
49
|
+
- Add `--max-size 1024` when a full-resolution screenshot is too large for an agent, model, or chat attachment.
|
|
49
50
|
- Add `--overlay-refs` when you want the saved PNG to show fresh `@eN` refs burned into the screenshot.
|
|
51
|
+
- Combine them as `screenshot /tmp/proof.png --max-size 1024 --overlay-refs` when you need a smaller visual proof that still includes tappable refs.
|
|
52
|
+
- Avoid very small `--max-size` values when text, icons, or labels need to remain readable.
|
|
50
53
|
|
|
51
54
|
## Visual regression with diff screenshot
|
|
52
55
|
|
|
@@ -126,5 +129,6 @@ agent-device perf --json
|
|
|
126
129
|
- `startup` is command round-trip timing around `open`.
|
|
127
130
|
- It is not true first-frame or first-interactive telemetry.
|
|
128
131
|
- Android app sessions also expose `memory` (`dumpsys meminfo`) and `cpu` (`dumpsys cpuinfo`) snapshots when the session has an app package context.
|
|
129
|
-
- Apple app sessions on macOS and iOS
|
|
130
|
-
- `
|
|
132
|
+
- Apple app sessions on macOS, iOS simulators, and physical iOS devices also expose `memory` and `cpu` process snapshots when the session has an app bundle ID.
|
|
133
|
+
- On physical iOS devices, sampling uses a short `xcrun xctrace` Activity Monitor capture, so keep the device unlocked, connected, and the app active in the foreground while sampling.
|
|
134
|
+
- `fps` is still unavailable in this release.
|
package/skills/dogfood/SKILL.md
CHANGED
|
@@ -166,6 +166,7 @@ agent-device --session {SESSION} close
|
|
|
166
166
|
- Re-snapshot after any mutation (navigation, modal, list update, form submit).
|
|
167
167
|
- Use `fill` for clear-then-type semantics; use `type` for incremental typing behavior checks.
|
|
168
168
|
- Keep logs optional and targeted: enable/read app logs only when useful for diagnosis.
|
|
169
|
+
- If the issue appears rooted in React Native internals rather than device/app runtime behavior, use `agent-device react-devtools ...` and the `skills/react-devtools` workflow for component-tree or render-profiling inspection.
|
|
169
170
|
- Never read source code of the app under test; findings must come from observed runtime behavior.
|
|
170
171
|
- Write each issue immediately to avoid losing evidence.
|
|
171
172
|
- Never delete screenshots/videos/report artifacts during a session.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: react-devtools
|
|
3
|
+
description: Inspect and profile React Native component trees from agent-device. Use when debugging React Native props, state, hooks, render causes, slow components, excessive re-renders, or questions like why a component re-rendered.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# react-devtools
|
|
7
|
+
|
|
8
|
+
Use this skill when the task needs React Native internals that are not visible in the accessibility tree: component hierarchy, props, state, hooks, render causes, or profiling data.
|
|
9
|
+
|
|
10
|
+
Run commands through `agent-device react-devtools`. The command dynamically runs pinned `agent-react-devtools@0.4.0` and passes arguments through 1:1.
|
|
11
|
+
|
|
12
|
+
The first run may download the pinned package from npm. `agent-device` global flags work before or after `react-devtools`; use `--` before downstream flags only when they intentionally share an `agent-device` global flag name.
|
|
13
|
+
|
|
14
|
+
## Default flow
|
|
15
|
+
|
|
16
|
+
1. Use `agent-device` to open the React Native app and verify the visible state when needed.
|
|
17
|
+
2. Check `agent-device react-devtools status`.
|
|
18
|
+
3. If no app is connected, start or wait for the devtools daemon, then reload or relaunch the app.
|
|
19
|
+
4. Inspect with `get tree`, `find`, and `get component`.
|
|
20
|
+
5. Profile only around the interaction being investigated.
|
|
21
|
+
6. Verify the fix with the same command sequence and interaction.
|
|
22
|
+
|
|
23
|
+
For cross-platform validation with explicit `--device`, `--udid`, or `--serial` selectors, prefer an isolated `--state-dir` over separate named sessions. Named sessions enable bound-session locks during setup. Restart `agent-device react-devtools` between iOS and Android runs so `status`, `get tree`, and profiling clearly refer to the currently launched app.
|
|
24
|
+
|
|
25
|
+
## Main commands
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
agent-device react-devtools status
|
|
29
|
+
agent-device react-devtools wait --connected
|
|
30
|
+
agent-device react-devtools get tree --depth 3
|
|
31
|
+
agent-device react-devtools find <ComponentName>
|
|
32
|
+
agent-device react-devtools get component @c5
|
|
33
|
+
agent-device react-devtools profile start
|
|
34
|
+
agent-device react-devtools profile stop
|
|
35
|
+
agent-device react-devtools profile slow --limit 5
|
|
36
|
+
agent-device react-devtools profile rerenders --limit 5
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Decision rules
|
|
40
|
+
|
|
41
|
+
- Need current UI text, refs, screenshots, logs, network, or device metrics: use the `agent-device` skill.
|
|
42
|
+
- Need props, state, hooks, component ownership, render causes, or React profiler data: use this skill.
|
|
43
|
+
- Start component-tree reads with `get tree --depth 3` or `find <name>` to keep output bounded.
|
|
44
|
+
- Labels like `@c5` reset when the app reloads or components remount. After reload, run `wait --connected` and inspect again.
|
|
45
|
+
- Profiling only captures renders between `profile start` and `profile stop`.
|
|
46
|
+
- On Android, set `adb reverse tcp:8097 tcp:8097` for React DevTools. If Metro is local, also set `adb reverse tcp:8081 tcp:8081`.
|
|
47
|
+
|
|
48
|
+
## References
|
|
49
|
+
|
|
50
|
+
| File | When to read |
|
|
51
|
+
| --------------------------------------- | --------------------------------------------- |
|
|
52
|
+
| [commands.md](references/commands.md) | Command reference and common inspection flows |
|
|
53
|
+
| [profiling.md](references/profiling.md) | Render profiling workflow and interpretation |
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# React DevTools Commands
|
|
2
|
+
|
|
3
|
+
All commands are run through `agent-device react-devtools`.
|
|
4
|
+
|
|
5
|
+
## Connection
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
agent-device react-devtools start
|
|
9
|
+
agent-device react-devtools stop
|
|
10
|
+
agent-device react-devtools status
|
|
11
|
+
agent-device react-devtools wait --connected --timeout 30
|
|
12
|
+
agent-device react-devtools wait --component <ComponentName> --timeout 30
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- `status` shows the daemon port, connected apps, component count, profiling state, uptime, and last connection event.
|
|
16
|
+
- Most commands auto-start the daemon, but `start` is useful before launching or reloading the app.
|
|
17
|
+
- React Native development builds connect to the daemon on port 8097. For Android emulators or physical devices, use `adb reverse tcp:8097 tcp:8097` if the app cannot reach the host. If the app also uses local Metro, set `adb reverse tcp:8081 tcp:8081`.
|
|
18
|
+
|
|
19
|
+
## Validation Notes
|
|
20
|
+
|
|
21
|
+
- When validating the same app across iOS and Android with explicit `--device`, `--udid`, or `--serial` selectors, prefer an isolated `--state-dir` over separate named sessions. A named `--session` enables bound-session lock behavior, so setup commands with explicit target selectors can be rejected.
|
|
22
|
+
- Restart the React DevTools daemon between platforms so `status`, `get tree`, and profiling output belong to the currently launched app.
|
|
23
|
+
- Verify the app is visibly loaded with `snapshot` before collecting React internals. Use `react-devtools` for component state and profiling, not for proving the device/app surface is open.
|
|
24
|
+
|
|
25
|
+
## Component Inspection
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
agent-device react-devtools get tree --depth 3
|
|
29
|
+
agent-device react-devtools get component @c5
|
|
30
|
+
agent-device react-devtools find Button
|
|
31
|
+
agent-device react-devtools find Button --exact
|
|
32
|
+
agent-device react-devtools count
|
|
33
|
+
agent-device react-devtools errors
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- `get tree` prints a component hierarchy with labels like `@c1`, `@c2`.
|
|
37
|
+
- Use `--depth` on large apps. Start at `--depth 3` or `--depth 4`.
|
|
38
|
+
- `get component` accepts a label or numeric React fiber id and shows props, state, and hooks.
|
|
39
|
+
- `find` searches by display name. Use `--exact` when fuzzy results are noisy.
|
|
40
|
+
- `errors` lists components with React-tracked warnings or errors.
|
|
41
|
+
|
|
42
|
+
## Profiling
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
agent-device react-devtools profile start "interaction name"
|
|
46
|
+
agent-device react-devtools profile stop
|
|
47
|
+
agent-device react-devtools profile slow --limit 5
|
|
48
|
+
agent-device react-devtools profile rerenders --limit 5
|
|
49
|
+
agent-device react-devtools profile report @c5
|
|
50
|
+
agent-device react-devtools profile timeline --limit 20
|
|
51
|
+
agent-device react-devtools profile commit 3
|
|
52
|
+
agent-device react-devtools profile export profile.json
|
|
53
|
+
agent-device react-devtools profile diff before.json after.json --limit 10
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- `profile slow` ranks components by average render duration.
|
|
57
|
+
- `profile rerenders` ranks components by render count.
|
|
58
|
+
- `profile report @cN` shows render causes and changed props/state/hooks for one component.
|
|
59
|
+
- `profile timeline` lists commits. Use `--limit` and `--offset` for long sessions.
|
|
60
|
+
- `profile export` writes React DevTools Profiler JSON that can be diffed later.
|
|
61
|
+
|
|
62
|
+
## Common Flows
|
|
63
|
+
|
|
64
|
+
Inspect a component:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
agent-device react-devtools status
|
|
68
|
+
agent-device react-devtools get tree --depth 3
|
|
69
|
+
agent-device react-devtools find SearchScreen
|
|
70
|
+
agent-device react-devtools get component @c12
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Profile a slow interaction:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
agent-device react-devtools profile start "slow search"
|
|
77
|
+
# Trigger the interaction with agent-device or ask the user to perform it.
|
|
78
|
+
agent-device react-devtools profile stop
|
|
79
|
+
agent-device react-devtools profile slow --limit 5
|
|
80
|
+
agent-device react-devtools profile rerenders --limit 5
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Verify a render fix:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
agent-device react-devtools profile start "after fix"
|
|
87
|
+
# Repeat the same interaction.
|
|
88
|
+
agent-device react-devtools profile stop
|
|
89
|
+
agent-device react-devtools profile slow --limit 5
|
|
90
|
+
agent-device react-devtools profile rerenders --limit 5
|
|
91
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# React Native Profiling
|
|
2
|
+
|
|
3
|
+
Use this workflow when the user reports slow interactions, excessive re-renders, unstable props, or unclear render causes.
|
|
4
|
+
|
|
5
|
+
## Baseline
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
agent-device react-devtools status
|
|
9
|
+
agent-device react-devtools count
|
|
10
|
+
agent-device react-devtools get tree --depth 3
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
If the app is not connected, run:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
agent-device react-devtools start
|
|
17
|
+
agent-device react-devtools wait --connected
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Then reload or relaunch the React Native app if needed.
|
|
21
|
+
|
|
22
|
+
## Capture One Interaction
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
agent-device react-devtools profile start "short label"
|
|
26
|
+
# Trigger exactly the interaction being investigated.
|
|
27
|
+
agent-device react-devtools profile stop
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Keep the profiling window narrow. Extra navigation, warm-up work, or unrelated gestures make the report harder to interpret.
|
|
31
|
+
|
|
32
|
+
## Identify Suspects
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
agent-device react-devtools profile slow --limit 5
|
|
36
|
+
agent-device react-devtools profile rerenders --limit 5
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- A component with high average render time is a slow-render suspect.
|
|
40
|
+
- A component with high render count is a re-render suspect.
|
|
41
|
+
- A component can be both.
|
|
42
|
+
|
|
43
|
+
## Drill In
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
agent-device react-devtools profile report @c12
|
|
47
|
+
agent-device react-devtools get component @c12
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Use `profile report` to identify render causes and changed keys. Use `get component` to inspect current props, state, and hooks.
|
|
51
|
+
|
|
52
|
+
Common interpretations:
|
|
53
|
+
|
|
54
|
+
| Signal | Meaning | Typical follow-up |
|
|
55
|
+
| ------------------------------------------ | ----------------------------------- | ---------------------------------------------- |
|
|
56
|
+
| `props-changed` with function props | Parent may pass unstable callbacks | Check whether the parent can use `useCallback` |
|
|
57
|
+
| `props-changed` with object or array props | Parent may pass unstable references | Check whether the parent can use `useMemo` |
|
|
58
|
+
| `parent-rendered` with many child renders | Child has no bailout | Check whether `React.memo` is appropriate |
|
|
59
|
+
| `state-changed` | Component state caused the render | Check whether the state update is necessary |
|
|
60
|
+
| `hooks-changed` | Hook value or dependency changed | Inspect hook values and dependencies |
|
|
61
|
+
|
|
62
|
+
## Verify
|
|
63
|
+
|
|
64
|
+
After making a change, repeat the same interaction:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
agent-device react-devtools profile start "after fix"
|
|
68
|
+
# Repeat the same interaction.
|
|
69
|
+
agent-device react-devtools profile stop
|
|
70
|
+
agent-device react-devtools profile slow --limit 5
|
|
71
|
+
agent-device react-devtools profile rerenders --limit 5
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Compare render counts, average durations, changed keys, and commit counts against the baseline.
|