@swmansion/argent 0.32.1-next.0 → 0.32.1-next.2
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/dist/cli-cmds.mjs +1 -1
- package/dist/installer.mjs +7 -7
- package/dist/mcp-server.mjs +1 -1
- package/dist/tool-args.generated.d.ts +178 -178
- package/dist/tool-server.cjs +1270 -1459
- package/package.json +1 -1
- package/rules/argent.md +19 -183
- package/skills/argent-android-emulator-setup/SKILL.md +5 -13
- package/skills/argent-create-e2e/SKILL.md +1 -1
- package/skills/argent-create-e2e/references/e2e-yaml.md +12 -17
- package/skills/argent-create-e2e/references/live-authoring.md +25 -65
- package/skills/argent-create-e2e/references/reliability-and-recovery.md +8 -8
- package/skills/argent-device-interact/SKILL.md +65 -367
- package/skills/argent-device-interact/references/chromium.md +4 -19
- package/skills/argent-device-interact/references/foldables.md +8 -0
- package/skills/argent-device-interact/references/harmonyos.md +13 -50
- package/skills/argent-ios-device-interact/SKILL.md +0 -1
- package/skills/argent-ios-device-setup/SKILL.md +1 -1
- package/skills/argent-ios-simulator-setup/SKILL.md +3 -9
- package/skills/argent-lens/SKILL.md +20 -75
- package/skills/argent-metro-debugger/SKILL.md +35 -101
- package/skills/argent-native-profiler/SKILL.md +23 -92
- package/skills/argent-qa-e2e/SKILL.md +5 -5
- package/skills/argent-react-native-app-workflow/SKILL.md +34 -203
- package/skills/argent-react-native-optimization/SKILL.md +10 -26
- package/skills/argent-react-native-optimization/references/fix-reference.md +11 -11
- package/skills/argent-react-native-optimization/references/lint-rules.md +4 -5
- package/skills/argent-react-native-optimization/references/semantic-checklist.md +2 -2
- package/skills/argent-react-native-profiler/SKILL.md +46 -110
- package/skills/argent-screen-recording/SKILL.md +18 -37
- package/skills/argent-screenshot-diff/SKILL.md +8 -52
- package/skills/argent-settings-permissions/SKILL.md +15 -117
- package/skills/argent-test-ui-flow/SKILL.md +20 -90
- package/skills/argent-tv-interact/SKILL.md +9 -34
- package/skills/argent-tv-interact/references/vega.md +23 -0
- package/agents/argent-environment-inspector.md +0 -107
- package/agents/references/quality-control-checklist.md +0 -45
- package/skills/argent-device-interact/references/gesture-examples.md +0 -114
- package/skills/argent-device-interact/references/secrets.md +0 -23
- package/skills/argent-metro-debugger/references/failure-scenarios.md +0 -14
- package/skills/argent-metro-debugger/references/source-maps.md +0 -27
- package/skills/argent-react-native-profiler/references/diagnostic-tools.md +0 -101
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Phase 1: Lint Rules
|
|
2
2
|
|
|
3
3
|
Run once at the project root. Catches mechanical issues deterministically.
|
|
4
|
-
Install missing plugins before running
|
|
4
|
+
Install missing plugins before running. On ESLint 10, `eslint-plugin-react-native` crashes: install with `--legacy-peer-deps` (npm; pnpm only warns) and run `npx eslint@9`.
|
|
5
|
+
With React Compiler active, leave out the react-perf rules, `react/jsx-no-bind` and `react-native/no-inline-styles`, unless the compiler skips some components (`compilationMode: "annotation"`, `"use no memo"`, a `sources` filter).
|
|
5
6
|
|
|
6
7
|
## Rules
|
|
7
8
|
|
|
@@ -48,8 +49,6 @@ Install missing plugins before running: `npm install --save-dev eslint-plugin-re
|
|
|
48
49
|
|
|
49
50
|
## Procedure
|
|
50
51
|
|
|
51
|
-
1.
|
|
52
|
-
|
|
53
|
-
2b. If no config, create a temporary `.eslintrc.json` with all rules above.
|
|
54
|
-
2. Run: `npx eslint --format json <src_dir>`; replace `<src_dir>` with the project's JS/TS source root (check `package.json` scripts or look for `src/`, `app/`, `lib/`)
|
|
52
|
+
1. Add the rules above for this run only: extend the project's ESLint config, or on ESLint 10 use a temporary flat config that spreads it. With no project config, create a temporary `eslint.config.mjs`; on a TypeScript project give it `typescript-eslint`'s parser, or every `.tsx` file fails to parse.
|
|
53
|
+
2. Run: `npx eslint --format json <src_dir>` (`npx eslint@9 -c <temp config>` on ESLint 10); replace `<src_dir>` with the project's JS/TS source root (check `package.json` scripts or look for `src/`, `app/`, `lib/`)
|
|
55
54
|
3. Parse output into: `file:line -> rule -> message`.
|
|
@@ -7,7 +7,7 @@ See [fix-reference.md](fix-reference.md) for concrete fix patterns per finding.
|
|
|
7
7
|
|
|
8
8
|
### Memoization
|
|
9
9
|
|
|
10
|
-
Check every exported function component: is it rendered in a list, a frequently-updating parent, or a context consumer? If yes and props are stable, wrap in `React.memo`. Check context providers for unstable `value` props.
|
|
10
|
+
Check every exported function component: is it rendered in a list, a frequently-updating parent, or a context consumer? If yes and props are stable, wrap in `React.memo`. Check context providers for unstable `value` props. If React Compiler is active, check only the components it skips (`compilationMode: "annotation"`, `"use no memo"`, a `sources` filter).
|
|
11
11
|
|
|
12
12
|
### List rendering
|
|
13
13
|
|
|
@@ -27,7 +27,7 @@ Check all `useEffect` hooks that create timers, listeners, or subscriptions. Ver
|
|
|
27
27
|
|
|
28
28
|
### State hygiene
|
|
29
29
|
|
|
30
|
-
Check for unused state (set but never rendered), unbounded state growth (arrays/objects that grow without cap), and derived state that should be computed
|
|
30
|
+
Check for unused state (set but never rendered), unbounded state growth (arrays/objects that grow without cap), and derived state that should be computed during render instead.
|
|
31
31
|
|
|
32
32
|
### Monolithic context
|
|
33
33
|
|
|
@@ -7,162 +7,98 @@ This skill is complementary to `argent-react-native-optimization`, not a replace
|
|
|
7
7
|
|
|
8
8
|
Physical iPhone: not supported; `react-profiler-*` reject `kind: "device"`. Profile on a simulator.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## 1. Tools
|
|
11
11
|
|
|
12
12
|
### React Profiler (Hermes / React commits)
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
| `react-profiler-component-source` | AST lookup: file, line, memoization status, 50 lines of source for a component. |
|
|
21
|
-
| `react-profiler-renders` | Live fiber walk: render counts + durations per component (no profiling session required). |
|
|
22
|
-
| `react-profiler-fiber-tree` | Live fiber walk: full component hierarchy as JSON. |
|
|
14
|
+
- `react-profiler-start` / `react-profiler-stop`: record CPU samples and React commits around an interaction.
|
|
15
|
+
- `react-profiler-analyze`: turn the recording into a ranked report: hot commits with the JS functions that ran during each.
|
|
16
|
+
- `react-profiler-status`: **only after an interruption** (debugger drop, Metro reload, pause, subagent handoff, any doubt), never otherwise. A debugger drop also ends the recording; check status before stopping or restarting.
|
|
17
|
+
- `react-profiler-component-source`: source, location and memoization status of a component the report flagged.
|
|
18
|
+
- `react-profiler-renders`: how many instances of each component are mounted in the top 30 levels of the tree, with their last render time; no session needed. It does not count re-renders: record a profile for that.
|
|
19
|
+
- `react-profiler-fiber-tree`: live component hierarchy, no session needed, for tracing a component's ancestry.
|
|
23
20
|
|
|
24
|
-
### Drill-
|
|
21
|
+
### Drill-down queries (after analyze)
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
| `profiler-combined-report` | Cross-correlated report when both React Profiler and native profiler ran in parallel. |
|
|
32
|
-
| `profiler-load` | List and reload previous profiling sessions from disk for re-investigation with query tools. |
|
|
23
|
+
- `profiler-cpu-query`: JS CPU: top functions, a time window, a function's call tree, CPU during a component's commits.
|
|
24
|
+
- `profiler-commit-query`: React commits by component, time range, commit index, or cascade tree.
|
|
25
|
+
- `profiler-stack-query`: native data: hang stacks, function callers, thread breakdown, leak details.
|
|
26
|
+
- `profiler-combined-report`: correlates native hangs with React commits when both profilers ran.
|
|
27
|
+
- `profiler-load`: reload an earlier session from disk for the query tools.
|
|
33
28
|
|
|
34
|
-
For native profiling
|
|
29
|
+
For native profiling on its own, see the `argent-native-profiler` skill.
|
|
35
30
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
## 3. Agent Behavior Guidelines
|
|
39
|
-
|
|
40
|
-
Follow these rules throughout the profiling workflow:
|
|
41
|
-
|
|
42
|
-
- Start `react-profiler-start` and `native-profiler-start` in parallel (two tool calls in one message). Both need `device_id`; use the same UDID for both so their data can be correlated later. This gives best coverage.
|
|
43
|
-
- If the user only wants native profiling, use the `argent-native-profiler` skill workflow. Only skip `native-profiler-start` if the user has **already explicitly said** they don't want native profiling in this session
|
|
44
|
-
|
|
45
|
-
### After analysis: ask about next steps
|
|
46
|
-
|
|
47
|
-
After presenting the analysis report, always ask the user what they want to do next. Present these options:
|
|
48
|
-
|
|
49
|
-
1. **Investigate further**: drill down into specific findings using query tools (CPU call trees, commit cascades, hang stacks, etc.) to identify root causes with confidence before making changes.
|
|
50
|
-
2. **Implement fixes**: apply changes based on the current findings, then re-profile to measure whether the metric changed (improved, regressed, or stayed flat).
|
|
51
|
-
3. **Done for now**: accept the report as-is.
|
|
52
|
-
|
|
53
|
-
Do NOT silently move on after the report. The report is the starting point, not the end; query tools exist specifically to let you dig deeper into anything the report flags.
|
|
54
|
-
|
|
55
|
-
### During investigation: use query tools proactively
|
|
56
|
-
|
|
57
|
-
When drilling down, chain query tool calls based on what you find:
|
|
58
|
-
|
|
59
|
-
- A hot commit -> `profiler-commit-query` mode=`by_index` to see all components -> `profiler-cpu-query` mode=`component_cpu` for the slowest one -> `profiler-cpu-query` mode=`call_tree` for the hot function -> read the source file -> propose a fix.
|
|
60
|
-
- A memory leak -> `profiler-stack-query` mode=`leak_stacks` to identify the responsible module -> read the native source if actionable.
|
|
61
|
-
- A native hang -> `profiler-stack-query` mode=`hang_stacks` to get the native call chain -> correlate with React commit timing.
|
|
62
|
-
|
|
63
|
-
### After fixes: always re-profile
|
|
64
|
-
|
|
65
|
-
When you apply a fix, always re-profile the same scenario afterward. Compare before/after metrics (commit durations, CPU time, render counts) and report honestly: did the target metric improve, stay flat, or regress? Did any _other_ metric get worse? If you need to reference the original data, use `profiler-load` to reload the pre-fix session. If the fix showed no improvement or introduced a regression, say so explicitly and reconsider the approach.
|
|
31
|
+
## 2. Guidelines
|
|
66
32
|
|
|
67
|
-
|
|
33
|
+
- Start `react-profiler-start` and `native-profiler-start` together, as `react-profiler-start` describes. If the user wants only native profiling, follow `argent-native-profiler`.
|
|
34
|
+
- **Never move on silently after a report.** The report is the starting point: ask the user whether to investigate further with the query tools, implement fixes and re-profile, or stop.
|
|
35
|
+
- **Record the interaction as an e2e test** (`argent-create-e2e` skill) before the first run when profiling needs a specific interaction sequence (scroll a list, navigate screens, trigger an animation), then replay it for every later run. This removes interaction variance from before/after comparisons. It matters most when re-profiling after a fix, comparing several sessions, or when the path is more than 2-3 steps.
|
|
68
36
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
- You are about to re-profile after applying a fix (Step 8).
|
|
72
|
-
- The user asks you to compare multiple profiling sessions.
|
|
73
|
-
- The interaction path is more than 2-3 steps long.
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## 4. Standard Profiling Workflow
|
|
37
|
+
## 3. Workflow
|
|
78
38
|
|
|
79
39
|
**Complete all steps in order; do not break mid-flow.**
|
|
80
40
|
|
|
81
41
|
### Step 1: Start profiling
|
|
82
42
|
|
|
83
|
-
|
|
43
|
+
Before starting, define lightweight success criteria with the user: which metric matters most (e.g. `totalRenderMs`, a specific commit's duration, a component's render count) and what change would be meaningful.
|
|
44
|
+
|
|
45
|
+
Start the profilers as described in §2. **Save `startedAtEpochMs` from the response** for annotations. Every later profiler and query call in this session must use the same `device_id`. Then:
|
|
84
46
|
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
If you received information about **existing profiling session** being owned by another agent:
|
|
88
|
-
- if session is marked as "stale", you may overtake it without prompting the user for allowance
|
|
89
|
-
- if session is NOT "stale" - before taking action and terminating the other session, **stop and ask user what you should do**, explaining the situation.
|
|
47
|
+
- If the user asked you to profile, drive the interaction yourself (`argent-device-interact` skill).
|
|
48
|
+
- If the user wants to interact themselves, suggest what to do (e.g. "scroll the list", "switch tabs") and wait for their reply.
|
|
90
49
|
|
|
91
50
|
While a profiler records, interaction tools return no automatic screenshot or element tree, so the capture does not load the app. Call `screenshot` or `describe` when you need to see the screen; interaction tools still wait for the screen to settle before they return, so add no wait of your own; on an Android emulator each screenshot during a profile takes one frame in about 100 ms and does not wake the screen capture; on a physical Android device it takes about 150–200 ms and briefly wakes the device screen capture, so take them sparingly there.
|
|
92
51
|
|
|
93
52
|
#### Annotate every interaction
|
|
94
53
|
|
|
95
|
-
After each `gesture-tap` or `gesture-swipe
|
|
54
|
+
After each `gesture-tap` or `gesture-swipe`, record an annotation with `offsetMs = timestampMs - startedAtEpochMs`, using the `timestampMs` the gesture returned. Never use `Date.now()`; only the server-side timestamps. Annotate _every_ interaction, back-navigation swipes included, and pass them all to `react-profiler-analyze` in Step 3.
|
|
96
55
|
|
|
97
56
|
### Step 2: Stop and collect
|
|
98
57
|
|
|
99
|
-
Call `react-profiler-stop` **and** `native-profiler-stop` in parallel
|
|
100
|
-
If `fiber_renders_captured: 0`, warn the user: React commit data may be missing.
|
|
58
|
+
Call `react-profiler-stop` **and** `native-profiler-stop` in parallel (skip the native one only if you did not start it). If `fiber_renders_captured` is 0, warn the user that React commit data may be missing.
|
|
101
59
|
|
|
102
60
|
### Step 3: Analyze
|
|
103
61
|
|
|
104
|
-
Call `react-profiler-analyze` with
|
|
105
|
-
|
|
106
|
-
If you performed interactions using `gesture-tap`/`gesture-swipe`, pass `annotations` to mark when each action occurred. Each annotation's `offsetMs` must be computed as `tapTimestampMs - startedAtEpochMs`, where `tapTimestampMs` is the `timestampMs` returned by the gesture-tap/gesture-swipe tool and `startedAtEpochMs` was returned by `react-profiler-start`. Do **not** use `Date.now()` for this calculation; only server-side timestamps from the tool return values.
|
|
62
|
+
Call `react-profiler-analyze` with your annotations. Check the report's React Compiler and build-mode lines before proposing fixes.
|
|
107
63
|
|
|
108
|
-
If
|
|
109
|
-
|
|
110
|
-
The analyze report includes **CPU hotspots per commit**, showing exactly which JS functions ran during each slow React commit. Raw data is saved to disk automatically for later reload.
|
|
64
|
+
If both profilers ran, also call `native-profiler-analyze`, then **you must** call `profiler-combined-report`: it surfaces correlations the individual reports miss.
|
|
111
65
|
|
|
112
66
|
### Step 4: Assess results
|
|
113
67
|
|
|
114
|
-
|
|
68
|
+
Judge whether the results actually explain what is wrong. **Do not assume an improvement always exists**; check the findings against how React Native works, give honest feedback, and be ready to change approach.
|
|
115
69
|
|
|
116
70
|
### Step 5: Present findings and ask about next steps
|
|
117
71
|
|
|
118
|
-
|
|
72
|
+
Summarize the key findings, whether there is room for improvement, and how further work could affect performance. Then ask the user how to proceed (§2).
|
|
119
73
|
|
|
120
74
|
### Step 6: Drill-down investigation (iterative)
|
|
121
75
|
|
|
122
|
-
|
|
76
|
+
Chain the query tools from what the report flags:
|
|
123
77
|
|
|
124
|
-
- **Slow
|
|
125
|
-
- **
|
|
126
|
-
- **
|
|
127
|
-
- **
|
|
128
|
-
- **Who triggered whom?** -> `profiler-commit-query` mode=`cascade_tree`: visual parent-child cascade.
|
|
129
|
-
- **iOS hang details?** -> `profiler-stack-query` mode=`hang_stacks`: native call stacks during a hang.
|
|
78
|
+
- **Slow commit** → `profiler-commit-query` `by_index` (every component, props changes, parent cascade) or `cascade_tree` (who triggered whom).
|
|
79
|
+
- **Slow component** → `profiler-cpu-query` `component_cpu` → `call_tree` for the hot function → read the source → propose a fix.
|
|
80
|
+
- **A time range** → `profiler-commit-query` `by_time_range`, or `profiler-cpu-query` `time_window`.
|
|
81
|
+
- **Native hang or leak** → `profiler-stack-query` `hang_stacks` / `leak_stacks`; correlate the hang's timing with React commits.
|
|
130
82
|
|
|
131
|
-
|
|
83
|
+
Pass component names exactly as the report prints them; the wrapped name (`Memo(...)`, `Forget(...)`, `ForwardRef(...)`) resolves too. Repeat until you find the root-cause function and file, judging the evidence as in Step 4. After each round, ask the user whether to keep digging or move to fixing.
|
|
132
84
|
|
|
133
85
|
### Step 7: Reload a previous session
|
|
134
86
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
1. Call `profiler-load` mode=`list` to see all saved sessions with timestamps (the list now also shows Runtime / Device / Metro bundle columns to help identify the right session).
|
|
138
|
-
2. Call `profiler-load` mode=`load_react` session_id=`<timestamp>` device_id=`<UDID>` to reload React data. `device_id` scopes the reload into the `port:device_id` cache slot.
|
|
139
|
-
3. Call `profiler-load` mode=`load_native` session_id=`<timestamp>` device_id=`<UDID>` to reload native profiler data.
|
|
140
|
-
4. Query tools now operate on the reloaded session data; **pass the same `device_id` you loaded with**, otherwise they will miss the cache.
|
|
141
|
-
|
|
142
|
-
This is useful for before/after comparisons: profile, fix, re-profile, then reload the original session to compare metrics side by side.
|
|
87
|
+
To revisit earlier data, e.g. to compare before and after a fix: `profiler-load` mode `list`, then `load_react` and/or `load_native` with the `session_id` and the `device_id`. **Pass that same `device_id` to the query tools afterwards**, or they miss the reloaded data.
|
|
143
88
|
|
|
144
89
|
### Step 8: Apply fix and re-profile
|
|
145
90
|
|
|
146
|
-
|
|
91
|
+
Read the bottleneck's source (`react-profiler-component-source` or the Read tool), apply the fix, then re-profile the same scenario (Step 1 → interaction → Steps 2-4). Report honestly whether the target metric improved, stayed flat, or regressed, and whether any _other_ metric got worse (e.g. fewer renders but more CPU time, or a different component now re-renders more). If the fix brought no net benefit or unacceptable tradeoffs, revert and reconsider.
|
|
147
92
|
|
|
148
|
-
|
|
93
|
+
If the interaction was recorded as an e2e test, replay it with `e2e-execute` instead of repeating the steps by hand. If the replay fails (e.g. a UI fix changed the layout), follow `argent-create-e2e`'s [Diagnose a replay failure](../argent-create-e2e/references/reliability-and-recovery.md#diagnose-a-replay-failure) before retrying the profiling cycle.
|
|
149
94
|
|
|
150
|
-
If the user
|
|
151
|
-
|
|
152
|
-
**React Compiler rule:** If the analyze report indicates React Compiler is enabled, do NOT propose `useCallback`/`useMemo`/`React.memo` unless you confirmed compiler bail-out (check `react-profiler-fiber-tree` for absent `useMemoCache` on that component).
|
|
153
|
-
|
|
154
|
-
---
|
|
95
|
+
If the user does not want changes, present the report and suggest the fix without applying it.
|
|
155
96
|
|
|
156
|
-
|
|
97
|
+
**React Compiler rule:** do NOT propose `useCallback`/`useMemo`/`React.memo` for a component the report marks ✓ (compiled). For a component in your source marked ⚠️ (bailout suspected), fix what stops the compiler instead.
|
|
157
98
|
|
|
158
|
-
|
|
159
|
-
- **Re-run after fixes**: Always re-profile after changes. Report honestly whether the metric improved, regressed, or stayed flat; do not assume improvement.
|
|
160
|
-
- **`excluded` is informational**: Components in `animatedSubtrees` and `recyclerChildren` re-render by design.
|
|
161
|
-
- **Strict Mode**: Double-invokes renders. The pipeline halves `normalizedRenderCount` automatically when detected.
|
|
162
|
-
- **Debugger connection**: If interrupted, started profiling also closes. Before attempting recovery, call `react-profiler-status`: it tells you whether the session is `active`, `taken_over`, `stopped`, or `no_react_runtime`, so you can decide whether to stop, restart, or reconnect first.
|
|
163
|
-
- **Confounders to watch for**:
|
|
164
|
-
- Live API data may differ between runs (different payload sizes, content counts), which shifts render counts and durations independently of your fix. Note when data-dependent components show variance.
|
|
165
|
-
- Profiler overhead inflates CPU measurements. If iOS Instruments shows `JSLexer`, `JSONEmitter`, or Hermes internals dominating the JS thread, that reflects profiler instrumentation cost, not app work. Discount those entries.
|
|
166
|
-
- Runs are not perfectly reproducible. Small variations (under ~10-15%) in commit duration may be noise; only treat consistent, directional changes as signal.
|
|
99
|
+
## 4. Caveats
|
|
167
100
|
|
|
168
|
-
|
|
101
|
+
- **Dev builds** render ~3x slower than production (the report notes it). Prioritize render counts over durations: counts carry over to production. They are already halved when Strict Mode double-invokes renders.
|
|
102
|
+
- **Live API data** may differ between runs (payload sizes, item counts) and shift render counts and durations independently of your fix. Note when data-dependent components vary.
|
|
103
|
+
- **Run-to-run noise:** variations under ~10-15% in commit duration may be noise; only treat consistent, directional changes as signal.
|
|
104
|
+
- **Profiler overhead:** if the native profile shows `JSLexer`, `JSONEmitter` or Hermes internals dominating the JS thread, that is instrumentation cost, not app work. Discount those entries.
|
|
@@ -3,48 +3,29 @@ name: argent-screen-recording
|
|
|
3
3
|
description: Record a video of an iOS simulator or Android emulator/device screen using argent MCP tools. Use when the user asks to record the screen, capture a video of a flow, interaction, or animation, produce a screen recording, or document app behavior as a video clip.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
`screen-recording-start` and `screen-recording-stop` carry the options (`timeLimitSeconds`, `trimStatic`, `showTouches`) and the result fields. One recording per device at a time; different devices can record concurrently.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
- `screen-recording-stop`: stop the capture, finalize the container, and retrieve the video as a downloadable artifact (`video.hostPath` for co-located clients).
|
|
8
|
+
## 1. Critical: never leave a recording running
|
|
10
9
|
|
|
11
|
-
|
|
10
|
+
A forgotten recording keeps capturing until its `timeLimitSeconds` cap fires, holding the session and delaying the video. Use both safety nets:
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
## 2. Critical: never leave a recording running
|
|
16
|
-
|
|
17
|
-
A recording does not stop itself before its `timeLimitSeconds` cap, so a forgotten one keeps capturing until the cap fires, holding the recording session, wasting disk, and delaying the video you are waiting on (and with `trimStatic: false` it comes back padded with dead air). Two safety nets exist; use both:
|
|
18
|
-
|
|
19
|
-
1. **Set yourself a reminder the moment the recording starts.** You know the expected capture length (the interaction you are about to drive). Immediately after `screen-recording-start` returns, schedule a wake-up for that expected end time using whatever your harness provides: a built-in reminder/wakeup or scheduled-task tool if you have one, otherwise a background shell running `sleep <expected-seconds>` whose completion notification pulls you back. When it fires, call `screen-recording-stop`. Do not rely on remembering.
|
|
20
|
-
2. **Read the tool-result notes.** While a recording is running, every argent tool result carries a `NOTE:` reminding you it is still going and how to stop it. If the note says the recording already ended (time limit hit), still call `screen-recording-stop`; that is what hands you the file.
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## 3. Workflow
|
|
25
|
-
|
|
26
|
-
1. Ensure the target device is booted and the app is in the state you want the video to open on (`list-devices`, `launch-app`, `argent-device-interact`).
|
|
27
|
-
2. Call `screen-recording-start` with `udid` and a `timeLimitSeconds` slightly above the expected interaction length (default 180, max 600). Taps and swipes are drawn into the video by default (see the touch-visualizer note below); pass `showTouches: false` for a clean raw-screen capture.
|
|
28
|
-
3. Set the end-of-recording reminder described in §2; this step is not optional.
|
|
29
|
-
4. Drive the interaction to capture: gestures, navigation, typing (`argent-device-interact`). Prefer `run-sequence` for tight multi-step interactions so tool-call latency does not pad the video.
|
|
30
|
-
5. Call `screen-recording-stop` with the same `udid`. It returns `{ video, durationMs, wallClockMs?, trimmedMs?, warning? }`; `video` is an artifact whose resolved path points at the durably-saved file (see below). The video is already final when stop returns (the watermark is stamped during capture, not in a second pass), so stop takes well under a second.
|
|
31
|
-
6. Check `warning`: it reports cap-triggered stops, early encoder exits, a dropped frame stream, and possibly-truncated containers. Verify the file plays (or at least has a sane size) before presenting it to the user.
|
|
12
|
+
1. **Set yourself a reminder the moment the recording starts**, for the expected end of the interaction. Use whatever your harness provides: a reminder/wakeup or scheduled-task tool if you have one, otherwise a background shell running `sleep <expected-seconds>` whose completion notification pulls you back. When it fires, call `screen-recording-stop`. Do not rely on remembering.
|
|
13
|
+
2. **Read the tool-result notes.** While a recording runs, every argent tool result carries a `NOTE:` about it. If the note says the recording already ended, still call `screen-recording-stop`: that is what hands you the file.
|
|
32
14
|
|
|
33
|
-
|
|
15
|
+
## 2. Workflow
|
|
34
16
|
|
|
35
|
-
|
|
17
|
+
1. Get the device booted and the app into the state the video should open on (`list-devices`, `launch-app`, `argent-device-interact`).
|
|
18
|
+
2. Call `screen-recording-start` with `udid` and a `timeLimitSeconds` slightly above the expected interaction length.
|
|
19
|
+
3. Set the end-of-recording reminder from §1; this step is not optional.
|
|
20
|
+
4. Drive the interaction (`argent-device-interact`). Prefer `run-sequence` for tight multi-step interactions so tool-call latency does not pad the video.
|
|
21
|
+
5. Call `screen-recording-stop` with the same `udid`. Check `warning` (cap-triggered stop, early encoder exit, dropped frame stream, possibly truncated file) and confirm the file has a sane size before presenting it.
|
|
36
22
|
|
|
37
|
-
**
|
|
38
|
-
|
|
39
|
-
---
|
|
23
|
+
**Where the file lands.** A finished recording is saved durably on the **client**, even with a remote `argent link` tool-server: into `<project>/.argent/recordings/` (the nearest ancestor of the client's working directory with a `.git`/`package.json`/`.argent`), or `~/.argent/recordings/` outside a project. Change it with `argent config set recordings.directory <dir>` (`--scope project` for a per-repo choice). Mention the path to the user, and that the file is untracked: add it to `.gitignore` or clean it up if it shouldn't be committed.
|
|
40
24
|
|
|
41
|
-
##
|
|
25
|
+
## 3. Platform notes and limits
|
|
42
26
|
|
|
43
|
-
- **
|
|
44
|
-
- **
|
|
45
|
-
- **
|
|
46
|
-
- **Android**:
|
|
47
|
-
- **
|
|
48
|
-
- **Remote (`remote:`) simulators**: recorded on the remote runner, and `screen-recording-stop` downloads the mp4, so a long recording takes a while to retrieve. Unlike a local recording, the video keeps the portrait orientation of the screen, so a device in landscape plays sideways.
|
|
49
|
-
- **ffmpeg is required for local devices**: it is the encoder, so `screen-recording-start` fails up front with an install hint if it is missing (`brew install ffmpeg` on macOS). It is resolved from `PATH` plus the usual Homebrew prefixes. On a remote simulator it is optional; only the post-pass uses it.
|
|
50
|
-
- **Watermark**: the Argent logo + "By @swmansion" is stamped bottom-left while encoding, faint (20% opacity) and per-pixel contrast-matched to the background (light logo over dark UI, dark logo over light UI). On by default; turn it off with `argent disable video-watermark` (re-enable with `argent enable video-watermark`). The flag is read when the recording starts.
|
|
27
|
+
- **Recordable**: iOS simulators (local and remote `remote:`), Android emulators and physical Android devices. **Unsupported**: physical iPhones, tvOS simulators, Chromium apps, Vega/Fire TV and HarmonyOS. For a still frame use `screenshot`; for a replayable interaction script use `argent-create-e2e`.
|
|
28
|
+
- **One size per video**: the video keeps the size of the screen at the start; a later size change is letterboxed. On a foldable simulator, start recording on the panel you need at full size.
|
|
29
|
+
- **Remote (`remote:`) simulators**: the video keeps the screen's portrait orientation, so a device in landscape plays sideways.
|
|
30
|
+
- **Android**: secure screens (DRM, some password fields) come out black.
|
|
31
|
+
- **Watermark**: a faint Argent logo is stamped bottom-left. Turn it off with `argent disable video-watermark`; the flag is read when a recording starts.
|
|
@@ -5,65 +5,21 @@ description: Compare saved or live app screenshots with the argent screenshot-di
|
|
|
5
5
|
|
|
6
6
|
## 1. Role
|
|
7
7
|
|
|
8
|
-
Use `screenshot-diff` as supporting visual evidence for UI QA and visual regression checks. It highlights pixel-visible change or stability; it does not replace visual inspection, accessibility/component-tree state, frame/attribute checks, logs, network evidence, or app behavior.
|
|
8
|
+
Use `screenshot-diff` as supporting visual evidence for UI QA and visual regression checks. It highlights pixel-visible change or stability; it does not replace visual inspection, accessibility/component-tree state, frame/attribute checks, logs, network evidence, or app behavior. Its description covers the input combinations, physical-iPhone captures and the result.
|
|
9
9
|
|
|
10
|
-
Do not use screenshot diffing for tap-coordinate discovery. Use `describe
|
|
11
|
-
|
|
12
|
-
`screenshot-diff` supports physical iPhones (kind `"device"`) for both saved-file diffs and live captures. A live capture on hardware goes through the on-device runner at full resolution, is device-wide, and needs no registered app. Keep baselines per device model and resolution, and note that the `rotation` parameter is ignored on hardware: the capture follows the device's real orientation.
|
|
10
|
+
Do not use screenshot diffing for tap-coordinate discovery. Use `describe` or `native-describe-screen` to find targets first.
|
|
13
11
|
|
|
14
12
|
## 2. When To Use
|
|
15
13
|
|
|
16
|
-
Use `screenshot-diff` when pixel comparison can answer the verification question:
|
|
17
|
-
|
|
18
14
|
- Required for explicit "UI regression test", "visual regression test", "screenshot diff", "compare screenshots", or "before/after visual comparison" requests, unless stable comparable screenshots cannot be produced.
|
|
19
|
-
- Good fit when the
|
|
20
|
-
- Good fit when the risk is unintended visual regression outside the exact element changed.
|
|
15
|
+
- Good fit when the expected result is pixel-visible, or when the risk is an unintended visual regression outside the exact element changed.
|
|
21
16
|
- Poor fit when the result is better verified structurally: state changes, navigation existence, accessibility tree contents, console/network behavior, or unit tests.
|
|
22
17
|
- Poor fit when dynamic content, unpausable animation, timestamps, ads, random data, or missing baseline/current screenshots would make the comparison noisy or meaningless.
|
|
23
18
|
|
|
24
|
-
## 3.
|
|
25
|
-
|
|
26
|
-
Use normal downscaled `screenshot` calls for UI context and state checks. Use full-resolution screenshots only when saving baseline/current PNG files for visual regression comparison. Suppress the image block so the full-size PNG is not loaded into context:
|
|
27
|
-
|
|
28
|
-
```json
|
|
29
|
-
{ "udid": "<UDID>", "scale": 1.0, "includeImageInContext": false }
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
Capture the stable baseline before the relevant interaction or before editing whenever feasible. Compare it to the post-change or post-interaction screen after the app reloads, rebuilds, or reaches the state under test.
|
|
33
|
-
|
|
34
|
-
## 4. Parameters
|
|
19
|
+
## 3. Deterministic Flow
|
|
35
20
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
- Rare fixture flow: live baseline plus saved current -> `captureBaseline: true`, `currentPath`, `udid`, `outputDir`.
|
|
41
|
-
- Do not combine `captureBaseline: true` with `captureCurrent: true`, or provide both a path and live capture flag for the same side.
|
|
42
|
-
|
|
43
|
-
## 5. Deterministic Flow
|
|
44
|
-
|
|
45
|
-
1. Navigate to the known-good state.
|
|
46
|
-
2. Capture a baseline PNG with `screenshot` using `scale: 1.0` and `includeImageInContext: false`; keep the returned `path`.
|
|
47
|
-
3. Perform the interaction, apply the code change and navigate to the state under test.
|
|
48
|
-
4. Call `screenshot-diff` with the saved `baselinePath`, `captureCurrent: true`, `udid`, and `outputDir`.
|
|
21
|
+
1. Navigate to the known-good state. Capture the baseline before the relevant interaction or before editing whenever feasible.
|
|
22
|
+
2. Save a baseline PNG with `screenshot` using `scale: 1.0` and `includeImageInContext: false`, so the full-size image stays out of context; keep the returned `path`. Use normal downscaled screenshots for everything else.
|
|
23
|
+
3. Perform the interaction, apply the code change and navigate to the state under test, after the app reloads or rebuilds.
|
|
24
|
+
4. Call `screenshot-diff` with that `baselinePath`, `captureCurrent: true`, `udid`, and `outputDir`. If both images are already saved, pass `currentPath` instead of `captureCurrent`.
|
|
49
25
|
5. Inspect the summary and artifact paths, then combine the diff with normal visual inspection and any structural/runtime evidence needed for the assertion.
|
|
50
|
-
|
|
51
|
-
```json
|
|
52
|
-
{
|
|
53
|
-
"baselinePath": "/tmp/baseline.png",
|
|
54
|
-
"captureCurrent": true,
|
|
55
|
-
"udid": "<UDID>",
|
|
56
|
-
"outputDir": "/tmp/argent-diff"
|
|
57
|
-
}
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
If both images are already saved, use file paths for both sides:
|
|
61
|
-
|
|
62
|
-
```json
|
|
63
|
-
{
|
|
64
|
-
"baselinePath": "/tmp/baseline.png",
|
|
65
|
-
"currentPath": "/tmp/current.png",
|
|
66
|
-
"udid": "<UDID>",
|
|
67
|
-
"outputDir": "/tmp/argent-diff"
|
|
68
|
-
}
|
|
69
|
-
```
|