@petukhovart/agent-view 0.9.1 → 0.10.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/.claude-plugin/plugin.json +21 -21
- package/LICENSE +21 -21
- package/README.md +38 -13
- package/dist/cdp/network-stream.d.ts +27 -0
- package/dist/cdp/network-stream.d.ts.map +1 -0
- package/dist/cdp/network-stream.js +336 -0
- package/dist/cdp/network-stream.js.map +1 -0
- package/dist/cdp/transport.d.ts.map +1 -1
- package/dist/cdp/transport.js +167 -8
- package/dist/cdp/transport.js.map +1 -1
- package/dist/cdp/types.d.ts +187 -0
- package/dist/cdp/types.d.ts.map +1 -1
- package/dist/cdp/types.js +55 -0
- package/dist/cdp/types.js.map +1 -1
- package/dist/cli/commands/network.d.ts +19 -0
- package/dist/cli/commands/network.d.ts.map +1 -0
- package/dist/cli/commands/network.js +55 -0
- package/dist/cli/commands/network.js.map +1 -0
- package/dist/cli/index.js +23 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/config/manager.d.ts.map +1 -1
- package/dist/config/manager.js +6 -0
- package/dist/config/manager.js.map +1 -1
- package/dist/config/types.d.ts +8 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/inspectors/network/index.d.ts +19 -0
- package/dist/inspectors/network/index.d.ts.map +1 -0
- package/dist/inspectors/network/index.js +169 -0
- package/dist/inspectors/network/index.js.map +1 -0
- package/dist/server/server.d.ts +12 -0
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +191 -17
- package/dist/server/server.js.map +1 -1
- package/package.json +9 -8
- package/skills/verify/SKILL.md +319 -292
- package/skills/verify-recipe/SKILL.md +286 -286
- package/dist/cdp/console-stream.d.ts +0 -35
- package/dist/cdp/console-stream.d.ts.map +0 -1
- package/dist/cdp/console-stream.js +0 -103
- package/dist/cdp/console-stream.js.map +0 -1
- package/dist/inspectors/dom.d.ts +0 -17
- package/dist/inspectors/dom.d.ts.map +0 -1
- package/dist/inspectors/dom.js +0 -131
- package/dist/inspectors/dom.js.map +0 -1
- package/dist/inspectors/scene/pixi.d.ts +0 -3
- package/dist/inspectors/scene/pixi.d.ts.map +0 -1
- package/dist/inspectors/scene/pixi.js +0 -52
- package/dist/inspectors/scene/pixi.js.map +0 -1
package/skills/verify/SKILL.md
CHANGED
|
@@ -1,292 +1,319 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: verify
|
|
3
|
-
description: "Visual + runtime verification of desktop apps via Chrome DevTools Protocol. Use when modifying UI components, fixing visual bugs, testing user interactions, verifying layout, or when any workflow phase needs to inspect the running application — DOM, screenshots, scene graph, runtime state in pages and SharedWorkers/ServiceWorkers, console errors, or reactive-state diffs over time. Triggers on: verify, check UI, test how it looks, visual regression, screenshot, inspect DOM, check store/state, watch state changes, what changed after click, wait until state, read worker, console errors, runtime check, eval in page."
|
|
4
|
-
allowed-tools: Bash(agent-view *), Read
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Visual Verification with agent-view
|
|
8
|
-
|
|
9
|
-
You have access to `agent-view` CLI for inspecting and interacting with desktop applications via Chrome DevTools Protocol.
|
|
10
|
-
|
|
11
|
-
## Prerequisites
|
|
12
|
-
|
|
13
|
-
The target project must have:
|
|
14
|
-
1. `agent-view.config.json` in project root (run `agent-view init` to generate)
|
|
15
|
-
2. CDP enabled in the app (e.g. `--remote-debugging-port=9876` for Electron — avoid `9222`, it's Chrome's own default and collides when Chrome is open)
|
|
16
|
-
|
|
17
|
-
If config is missing, run `agent-view init` first.
|
|
18
|
-
|
|
19
|
-
## Commands Reference
|
|
20
|
-
|
|
21
|
-
### Discovery & Launch
|
|
22
|
-
```bash
|
|
23
|
-
agent-view launch # Start app from config, wait for CDP readiness (all runtimes incl. Tauri)
|
|
24
|
-
agent-view discover # List windows (JSON) — get window IDs
|
|
25
|
-
agent-view stop # Stop the lazy server
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
**Port conflict**: if the configured port is held by a non-CDP process (e.g. a stray webpack-dev on the same port), `agent-view launch` exits non-zero with `code: PORT_CONFLICT` and reports the owning PID/process name. Ask the user to either close that process or start the app manually — do not kill foreign processes from the skill.
|
|
29
|
-
|
|
30
|
-
**Tauri**: launch works the same as Electron, but the wait timeout is 10 min (cargo builds are slow). If you see a port conflict on the Tauri devUrl port, it's almost always a parallel browser-dev — surface the PID and ask the user.
|
|
31
|
-
|
|
32
|
-
### DOM Inspection
|
|
33
|
-
```bash
|
|
34
|
-
agent-view dom # DOM accessibility tree (default window)
|
|
35
|
-
agent-view dom --window <id|name> # Specific window
|
|
36
|
-
agent-view dom --filter "button" # Filter by text/role
|
|
37
|
-
agent-view dom --depth 3 # Limit tree depth
|
|
38
|
-
agent-view dom --compact # Merge single-child chains onto one line (~40-60% fewer tokens)
|
|
39
|
-
agent-view dom --count # Count of all visible nodes (single integer line)
|
|
40
|
-
agent-view dom --filter "row" --count # Count matching nodes — e.g. "does this table have 5 rows?"
|
|
41
|
-
agent-view dom --max-lines 200 # Hard line budget; refs for truncated nodes still stored
|
|
42
|
-
agent-view dom --diff # Lines changed since last dom call (+ added / - removed)
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
`--count` skips tree output and ref mutations — cheapest way to assert "element exists N times" without loading the full tree into context.
|
|
46
|
-
|
|
47
|
-
### Interaction
|
|
48
|
-
```bash
|
|
49
|
-
agent-view click <ref> # Click element by ref from dom output
|
|
50
|
-
agent-view click --pos 100,200 # Click by coordinates (for canvas)
|
|
51
|
-
agent-view click <ref> --double # Double-click (fires dblclick handlers); works with --filter / --pos too
|
|
52
|
-
agent-view fill <ref> "text" # Type into input field
|
|
53
|
-
agent-view drag --from <ref> --to <ref> # Drag element to another element by ref
|
|
54
|
-
agent-view drag --from-pos 50,80 --to-pos 200,300 # Drag by coordinates (for canvas / Pixi)
|
|
55
|
-
agent-view drag --from <ref> --to <ref> --steps 25 --hold-ms 60 # Smoother movement, longer hold
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
`drag` dispatches `mousePressed` → N × `mouseMoved` → `mouseReleased` via CDP. Endpoints can mix
|
|
59
|
-
ref and coordinate (e.g. `--from <ref> --to-pos 400,300`). For canvas/Pixi targets always use
|
|
60
|
-
`--from-pos`/`--to-pos` — derive the centroid via `agent-view eval` from the scene graph.
|
|
61
|
-
Refs are resolved fresh on each call, so window resizes between snapshots are tolerated.
|
|
62
|
-
Increase `--steps` for handlers using `globalpointermove` so intermediate frames are not skipped.
|
|
63
|
-
|
|
64
|
-
### Screenshots
|
|
65
|
-
```bash
|
|
66
|
-
agent-view screenshot --scale 0.5 # Recommended: JPEG at half-res (~3× fewer vision tokens)
|
|
67
|
-
agent-view screenshot --scale 0.5 --window <id> # Specific window
|
|
68
|
-
agent-view screenshot --crop "Sidebar" # Crop to element bounding box (~1.6k tokens — 12× win)
|
|
69
|
-
agent-view screenshot --crop "Chart" --scale 0.5 # Crop + scale (stacks)
|
|
70
|
-
agent-view screenshot # Full-res PNG (expensive: ~19k tokens at 1920×1080)
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
`--crop <filter>` resolves the element with the same filter syntax as `dom --filter`, then crops the screenshot to its bounding box. Prefer `--crop` over full-window screenshots whenever you only need to inspect a specific section. Falls back to full-window with a stderr warning if the filter matches nothing.
|
|
74
|
-
|
|
75
|
-
### Runtime State (`eval`)
|
|
76
|
-
|
|
77
|
-
Reads runtime values DOM/screenshot can't reveal — store contents, computed flags, worker internals.
|
|
78
|
-
**Requires `"allowEval": true` in `agent-view.config.json`** — if the call returns "eval is disabled", tell the user to add the flag rather than working around it.
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
agent-view eval "store.state.user.role" # default page target
|
|
82
|
-
agent-view eval --window "Settings" "router.currentRoute.path"
|
|
83
|
-
agent-view eval --target sync-worker "self.queue.length" # SharedWorker / ServiceWorker by id or substring
|
|
84
|
-
agent-view eval --await "fetch('/api/health').then(r => r.status)"
|
|
85
|
-
agent-view eval --json "({ buttons: document.querySelectorAll('button').length })"
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
When to reach for `eval` instead of `dom`:
|
|
89
|
-
- The truth lives in JS state, not the DOM (Pinia/Vuex/Redux/Zustand store, Vue refs, computed values, app singletons).
|
|
90
|
-
- The target is a worker (`shared_worker`, `service_worker`, `worker`) — DOM doesn't exist there.
|
|
91
|
-
- You need a precise number/string answer, not a tree to scan.
|
|
92
|
-
- Verifying a `window.*` API or globally-exposed object exists. `eval` runs in the page's **main world**, so anything set on `window` directly or exposed via `contextBridge.exposeInMainWorld` is reachable. APIs placed only in an isolated-world preload (without `contextBridge`) will NOT be visible — that is not an agent bug, that is the host app's wiring.
|
|
93
|
-
|
|
94
|
-
### Reactive State (`watch`)
|
|
95
|
-
|
|
96
|
-
Streams JSON-patch diffs of an expression over time. Use when you need to see *what changed* between an action and a final state — `eval` shows the snapshot, `watch` shows the trajectory. **Requires `"allowEval": true`.**
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
agent-view watch "store.cart.total" # 250ms poll, default 10 changes or 30s
|
|
100
|
-
agent-view watch "appState" --until "appState.status === 'ready'" # wait-for-condition with diff log
|
|
101
|
-
agent-view watch "store.user" --max-changes 1 # capture exactly one change after a click
|
|
102
|
-
agent-view watch "appState" --json # NDJSON, machine-readable
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
When to reach for `watch` instead of `eval`:
|
|
106
|
-
- Debugging "the click did X but state shows Y — what happened in between?"
|
|
107
|
-
- Time-based assertions ("wait until store.status === 'ready'") — `--until` exits cleanly when truthy.
|
|
108
|
-
- Confirming an action triggered the *expected* sequence of mutations, not just the final state.
|
|
109
|
-
|
|
110
|
-
Output: `init` line (baseline), one line per RFC 6902 op (`replace /path old → new`, `add /items/0 ...`), final `stop` line with reason. Snapshot size cap 256 KB — narrow the expression (`store.x.y`, not `store`) for large objects.
|
|
111
|
-
|
|
112
|
-
### Console (`console`)
|
|
113
|
-
|
|
114
|
-
Streams `Runtime.consoleAPICalled` + `Log.entryAdded`. Use to confirm a flow finished without errors, or to surface a specific warning after an interaction.
|
|
115
|
-
|
|
116
|
-
```bash
|
|
117
|
-
agent-view console # buffered messages from auto-attached targets
|
|
118
|
-
agent-view console --level error,warn # filter
|
|
119
|
-
agent-view console --target sync-worker # one target (title/URL substring, same fuzzy semantics as eval --target)
|
|
120
|
-
agent-view console --target IJ56KL # one target (exact id)
|
|
121
|
-
agent-view console --follow --timeout 10 # stream window (use sparingly — 10s of waiting)
|
|
122
|
-
agent-view console --follow --until "ready" # exit as soon as a message contains "ready"
|
|
123
|
-
agent-view console --follow --until "/error/i" # exit on regex match (case-insensitive)
|
|
124
|
-
agent-view console --clear # baseline before an interaction
|
|
125
|
-
agent-view console --since "2026-04-26T10:00:00Z"
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
`--until` requires `--follow`. Exits immediately when a message matches (substring or `/regex/flags`). On timeout without match exits non-zero.
|
|
129
|
-
|
|
130
|
-
Standard pattern for "did this action error?":
|
|
131
|
-
```bash
|
|
132
|
-
agent-view console --clear
|
|
133
|
-
agent-view click --filter "Save"
|
|
134
|
-
agent-view wait --filter "Saved"
|
|
135
|
-
agent-view console --level error # expect "(no console messages)"
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
Default attached target types: `page`, `shared_worker`, `service_worker` (override via `consoleTargets` in config).
|
|
139
|
-
|
|
140
|
-
###
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
```bash
|
|
145
|
-
agent-view
|
|
146
|
-
agent-view
|
|
147
|
-
agent-view
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
agent-view
|
|
162
|
-
agent-view
|
|
163
|
-
agent-view
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
7. **
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
**
|
|
1
|
+
---
|
|
2
|
+
name: verify
|
|
3
|
+
description: "Visual + runtime verification of desktop apps via Chrome DevTools Protocol. Use when modifying UI components, fixing visual bugs, testing user interactions, verifying layout, or when any workflow phase needs to inspect the running application — DOM, screenshots, scene graph, runtime state in pages and SharedWorkers/ServiceWorkers, console errors, or reactive-state diffs over time. Triggers on: verify, check UI, test how it looks, visual regression, screenshot, inspect DOM, check store/state, watch state changes, what changed after click, wait until state, read worker, console errors, runtime check, eval in page."
|
|
4
|
+
allowed-tools: Bash(agent-view *), Read
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Visual Verification with agent-view
|
|
8
|
+
|
|
9
|
+
You have access to `agent-view` CLI for inspecting and interacting with desktop applications via Chrome DevTools Protocol.
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
The target project must have:
|
|
14
|
+
1. `agent-view.config.json` in project root (run `agent-view init` to generate)
|
|
15
|
+
2. CDP enabled in the app (e.g. `--remote-debugging-port=9876` for Electron — avoid `9222`, it's Chrome's own default and collides when Chrome is open)
|
|
16
|
+
|
|
17
|
+
If config is missing, run `agent-view init` first.
|
|
18
|
+
|
|
19
|
+
## Commands Reference
|
|
20
|
+
|
|
21
|
+
### Discovery & Launch
|
|
22
|
+
```bash
|
|
23
|
+
agent-view launch # Start app from config, wait for CDP readiness (all runtimes incl. Tauri)
|
|
24
|
+
agent-view discover # List windows (JSON) — get window IDs
|
|
25
|
+
agent-view stop # Stop the lazy server
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Port conflict**: if the configured port is held by a non-CDP process (e.g. a stray webpack-dev on the same port), `agent-view launch` exits non-zero with `code: PORT_CONFLICT` and reports the owning PID/process name. Ask the user to either close that process or start the app manually — do not kill foreign processes from the skill.
|
|
29
|
+
|
|
30
|
+
**Tauri**: launch works the same as Electron, but the wait timeout is 10 min (cargo builds are slow). If you see a port conflict on the Tauri devUrl port, it's almost always a parallel browser-dev — surface the PID and ask the user.
|
|
31
|
+
|
|
32
|
+
### DOM Inspection
|
|
33
|
+
```bash
|
|
34
|
+
agent-view dom # DOM accessibility tree (default window)
|
|
35
|
+
agent-view dom --window <id|name> # Specific window
|
|
36
|
+
agent-view dom --filter "button" # Filter by text/role
|
|
37
|
+
agent-view dom --depth 3 # Limit tree depth
|
|
38
|
+
agent-view dom --compact # Merge single-child chains onto one line (~40-60% fewer tokens)
|
|
39
|
+
agent-view dom --count # Count of all visible nodes (single integer line)
|
|
40
|
+
agent-view dom --filter "row" --count # Count matching nodes — e.g. "does this table have 5 rows?"
|
|
41
|
+
agent-view dom --max-lines 200 # Hard line budget; refs for truncated nodes still stored
|
|
42
|
+
agent-view dom --diff # Lines changed since last dom call (+ added / - removed)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`--count` skips tree output and ref mutations — cheapest way to assert "element exists N times" without loading the full tree into context.
|
|
46
|
+
|
|
47
|
+
### Interaction
|
|
48
|
+
```bash
|
|
49
|
+
agent-view click <ref> # Click element by ref from dom output
|
|
50
|
+
agent-view click --pos 100,200 # Click by coordinates (for canvas)
|
|
51
|
+
agent-view click <ref> --double # Double-click (fires dblclick handlers); works with --filter / --pos too
|
|
52
|
+
agent-view fill <ref> "text" # Type into input field
|
|
53
|
+
agent-view drag --from <ref> --to <ref> # Drag element to another element by ref
|
|
54
|
+
agent-view drag --from-pos 50,80 --to-pos 200,300 # Drag by coordinates (for canvas / Pixi)
|
|
55
|
+
agent-view drag --from <ref> --to <ref> --steps 25 --hold-ms 60 # Smoother movement, longer hold
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
`drag` dispatches `mousePressed` → N × `mouseMoved` → `mouseReleased` via CDP. Endpoints can mix
|
|
59
|
+
ref and coordinate (e.g. `--from <ref> --to-pos 400,300`). For canvas/Pixi targets always use
|
|
60
|
+
`--from-pos`/`--to-pos` — derive the centroid via `agent-view eval` from the scene graph.
|
|
61
|
+
Refs are resolved fresh on each call, so window resizes between snapshots are tolerated.
|
|
62
|
+
Increase `--steps` for handlers using `globalpointermove` so intermediate frames are not skipped.
|
|
63
|
+
|
|
64
|
+
### Screenshots
|
|
65
|
+
```bash
|
|
66
|
+
agent-view screenshot --scale 0.5 # Recommended: JPEG at half-res (~3× fewer vision tokens)
|
|
67
|
+
agent-view screenshot --scale 0.5 --window <id> # Specific window
|
|
68
|
+
agent-view screenshot --crop "Sidebar" # Crop to element bounding box (~1.6k tokens — 12× win)
|
|
69
|
+
agent-view screenshot --crop "Chart" --scale 0.5 # Crop + scale (stacks)
|
|
70
|
+
agent-view screenshot # Full-res PNG (expensive: ~19k tokens at 1920×1080)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`--crop <filter>` resolves the element with the same filter syntax as `dom --filter`, then crops the screenshot to its bounding box. Prefer `--crop` over full-window screenshots whenever you only need to inspect a specific section. Falls back to full-window with a stderr warning if the filter matches nothing.
|
|
74
|
+
|
|
75
|
+
### Runtime State (`eval`)
|
|
76
|
+
|
|
77
|
+
Reads runtime values DOM/screenshot can't reveal — store contents, computed flags, worker internals.
|
|
78
|
+
**Requires `"allowEval": true` in `agent-view.config.json`** — if the call returns "eval is disabled", tell the user to add the flag rather than working around it.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
agent-view eval "store.state.user.role" # default page target
|
|
82
|
+
agent-view eval --window "Settings" "router.currentRoute.path"
|
|
83
|
+
agent-view eval --target sync-worker "self.queue.length" # SharedWorker / ServiceWorker by id or substring
|
|
84
|
+
agent-view eval --await "fetch('/api/health').then(r => r.status)"
|
|
85
|
+
agent-view eval --json "({ buttons: document.querySelectorAll('button').length })"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
When to reach for `eval` instead of `dom`:
|
|
89
|
+
- The truth lives in JS state, not the DOM (Pinia/Vuex/Redux/Zustand store, Vue refs, computed values, app singletons).
|
|
90
|
+
- The target is a worker (`shared_worker`, `service_worker`, `worker`) — DOM doesn't exist there.
|
|
91
|
+
- You need a precise number/string answer, not a tree to scan.
|
|
92
|
+
- Verifying a `window.*` API or globally-exposed object exists. `eval` runs in the page's **main world**, so anything set on `window` directly or exposed via `contextBridge.exposeInMainWorld` is reachable. APIs placed only in an isolated-world preload (without `contextBridge`) will NOT be visible — that is not an agent bug, that is the host app's wiring.
|
|
93
|
+
|
|
94
|
+
### Reactive State (`watch`)
|
|
95
|
+
|
|
96
|
+
Streams JSON-patch diffs of an expression over time. Use when you need to see *what changed* between an action and a final state — `eval` shows the snapshot, `watch` shows the trajectory. **Requires `"allowEval": true`.**
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
agent-view watch "store.cart.total" # 250ms poll, default 10 changes or 30s
|
|
100
|
+
agent-view watch "appState" --until "appState.status === 'ready'" # wait-for-condition with diff log
|
|
101
|
+
agent-view watch "store.user" --max-changes 1 # capture exactly one change after a click
|
|
102
|
+
agent-view watch "appState" --json # NDJSON, machine-readable
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
When to reach for `watch` instead of `eval`:
|
|
106
|
+
- Debugging "the click did X but state shows Y — what happened in between?"
|
|
107
|
+
- Time-based assertions ("wait until store.status === 'ready'") — `--until` exits cleanly when truthy.
|
|
108
|
+
- Confirming an action triggered the *expected* sequence of mutations, not just the final state.
|
|
109
|
+
|
|
110
|
+
Output: `init` line (baseline), one line per RFC 6902 op (`replace /path old → new`, `add /items/0 ...`), final `stop` line with reason. Snapshot size cap 256 KB — narrow the expression (`store.x.y`, not `store`) for large objects.
|
|
111
|
+
|
|
112
|
+
### Console (`console`)
|
|
113
|
+
|
|
114
|
+
Streams `Runtime.consoleAPICalled` + `Log.entryAdded`. Use to confirm a flow finished without errors, or to surface a specific warning after an interaction.
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
agent-view console # buffered messages from auto-attached targets
|
|
118
|
+
agent-view console --level error,warn # filter
|
|
119
|
+
agent-view console --target sync-worker # one target (title/URL substring, same fuzzy semantics as eval --target)
|
|
120
|
+
agent-view console --target IJ56KL # one target (exact id)
|
|
121
|
+
agent-view console --follow --timeout 10 # stream window (use sparingly — 10s of waiting)
|
|
122
|
+
agent-view console --follow --until "ready" # exit as soon as a message contains "ready"
|
|
123
|
+
agent-view console --follow --until "/error/i" # exit on regex match (case-insensitive)
|
|
124
|
+
agent-view console --clear # baseline before an interaction
|
|
125
|
+
agent-view console --since "2026-04-26T10:00:00Z"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`--until` requires `--follow`. Exits immediately when a message matches (substring or `/regex/flags`). On timeout without match exits non-zero.
|
|
129
|
+
|
|
130
|
+
Standard pattern for "did this action error?":
|
|
131
|
+
```bash
|
|
132
|
+
agent-view console --clear
|
|
133
|
+
agent-view click --filter "Save"
|
|
134
|
+
agent-view wait --filter "Saved"
|
|
135
|
+
agent-view console --level error # expect "(no console messages)"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Default attached target types: `page`, `shared_worker`, `service_worker` (override via `consoleTargets` in config).
|
|
139
|
+
|
|
140
|
+
### Network (`network`)
|
|
141
|
+
|
|
142
|
+
Request/response timeline, headers, timing, bodies, and WebSocket/SSE frames. Use to confirm an expected API call fired, diagnose a silent 404 / CORS block / missing auth header, or verify "button disabled until the network completes".
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
agent-view network # recent requests, newest at the bottom
|
|
146
|
+
agent-view network --req 3 # expand one: headers, timing, body / WS frame log
|
|
147
|
+
agent-view network --status 4xx,5xx # only failures (class or exact code, e.g. 404)
|
|
148
|
+
agent-view network --method POST # mutations among reads
|
|
149
|
+
agent-view network --type xhr,fetch # drop document/image/font noise
|
|
150
|
+
agent-view network --url "*/api/save*" # URL substring or * glob
|
|
151
|
+
agent-view network --follow --until "/api/save" # stream until a matching request fires
|
|
152
|
+
agent-view network --clear # baseline before an interaction
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Eager, unlike `console`.** `network` captures from app launch, so page-load traffic (initial XHR/fetch, auth handshakes, boot 404s) is usually already buffered by the time you call it — in most cases you don't need to reload. `console` is the opposite (lazy: attaches on first call, loses earlier output). Call this asymmetry out so it isn't mistaken for a bug. Caveat: for very fast apps the earliest request can fire before capture attaches. If boot traffic looks missing, don't conclude "no request fired" — reload (`agent-view eval "location.reload()"`) and re-check before deciding.
|
|
156
|
+
|
|
157
|
+
`[req=N]` handles are reallocated on every list call (like `dom` refs) — expand from the most recent list. Sensitive headers are redacted by default (`--raw-headers` reveals them). Response/request **bodies** require `"captureBody": true` in config; WebSocket frame payloads are visible by default.
|
|
158
|
+
|
|
159
|
+
Standard pattern for "did the save call fire and succeed?":
|
|
160
|
+
```bash
|
|
161
|
+
agent-view network --clear
|
|
162
|
+
agent-view click --filter "Save"
|
|
163
|
+
agent-view wait --filter "Saved"
|
|
164
|
+
agent-view network --url "*/api/save*" # expect one POST with status 200
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Targets (`targets`)
|
|
168
|
+
|
|
169
|
+
When `--window` doesn't show what you expected, or you need a worker target id for `eval`/`console`:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
agent-view targets # everything connectable
|
|
173
|
+
agent-view targets --type shared_worker,service_worker # filter
|
|
174
|
+
agent-view targets --json # machine-readable
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
You usually don't need this — `eval --target <substring>` and `--window <name>` both do fuzzy matching. Reach for `targets` when the substring is ambiguous.
|
|
178
|
+
|
|
179
|
+
### Scene / Canvas / WebGL (only when `webgl` is configured in agent-view.config.json)
|
|
180
|
+
|
|
181
|
+
These commands read the scene graph from canvas-based rendering engines. Skip this section if the project has no `webgl` field in config.
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
agent-view scene # Scene graph from configured engine
|
|
185
|
+
agent-view scene --filter "player" # Filter by object name/type
|
|
186
|
+
agent-view scene --verbose # Extended props (scale, alpha, rotation)
|
|
187
|
+
agent-view scene --diff # Changes since last call
|
|
188
|
+
agent-view scene --compact # Merge single-child chains onto one line (reduces output)
|
|
189
|
+
agent-view snap # DOM + Scene combined
|
|
190
|
+
agent-view snap --scale 0.5 # DOM + Scene + Screenshot (path appended as === Screenshot === section)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Picking the right tool
|
|
194
|
+
|
|
195
|
+
Verifications cost very different amounts. Pick the cheapest tool that can actually answer the question:
|
|
196
|
+
|
|
197
|
+
| The question is about… | Use | Why |
|
|
198
|
+
|---|---|---|
|
|
199
|
+
| Element existence / text / role | `dom --filter` | Cheapest, structured, no vision tokens |
|
|
200
|
+
| Count of matching elements | `dom --filter X --count` | Single integer, no tree output, no ref mutations |
|
|
201
|
+
| App state, store contents, computed values | `eval "expr"` | DOM doesn't expose JS state; reading the tree to infer it is wasteful and unreliable |
|
|
202
|
+
| Does `window.X` / a globally-exposed API exist? | `eval "typeof window.X"` | DOM doesn't show JS globals; only authoritative check |
|
|
203
|
+
| State *trajectory* — what changed during/after an action | `watch "expr" --until …` or `--max-changes 1` | `eval` shows the final snapshot only; `watch` shows the diffs in order |
|
|
204
|
+
| Worker logic (SharedWorker / ServiceWorker) | `eval --target <name>` | Workers have no DOM at all |
|
|
205
|
+
| Did the last action throw or warn? | `console --clear` before, `console --level error,warn` after | Catches errors that don't surface in the DOM |
|
|
206
|
+
| Layout/visual of a specific element | `screenshot --crop "<element>"` | ~1.6k tokens (1 tile) — crops to bounding box, massive token win |
|
|
207
|
+
| Layout, spacing, full-window visual regression | `screenshot --scale 0.5` | The only tool that sees pixels — but expensive (~6k tokens), use last |
|
|
208
|
+
| Canvas/WebGL scene contents | `scene --diff` | DOM is empty for canvas apps |
|
|
209
|
+
| What DOM nodes changed after an interaction | `dom --diff` | Returns only `+`/`-` lines; much cheaper than re-reading the full tree |
|
|
210
|
+
|
|
211
|
+
When two tools could answer the same question, prefer the one higher up the table. A common mistake is screenshotting to check "is the count = 5?" when `eval "store.counter"` returns the number directly for ~50 tokens.
|
|
212
|
+
|
|
213
|
+
## Verification Workflow
|
|
214
|
+
|
|
215
|
+
### Execution discipline (read first, every run)
|
|
216
|
+
|
|
217
|
+
A run can produce one of three outcomes per step: **pass**, **fail**, **requires_visual_review**. There is no fourth bucket called "actually fine, here's why". A failed `Expected:` line is FAIL.
|
|
218
|
+
|
|
219
|
+
These heuristics catch real bugs. Skipping them is how recipes silently pass while bugs sit in plain sight in the same data:
|
|
220
|
+
|
|
221
|
+
1. **A failed `Expected:` is FAIL.** If output disagrees with the expected line, mark `fail` and continue. Do not edit the expected line. Do not invent prose explanations inline ("label reuse", "convention", "recipe arithmetic off"). Justifications belong in the bug report after the run, never in the per-step log.
|
|
222
|
+
|
|
223
|
+
2. **UI-vs-model mismatch is the bug, not noise.** When a count or hierarchy check returns `match: false`:
|
|
224
|
+
- Default hypothesis: the UI renderer is wrong.
|
|
225
|
+
- Before considering "the filter matched something extra in some side panel", query bounding boxes and ancestor chains of the matched elements. Two matches at the same x-coordinate in adjacent y rows = sibling rows in one list = renderer bug.
|
|
226
|
+
- Do not dismiss DOM/model divergence with "scene-graph is the source of truth". The model is one representation; the bug may live in the gap between model and UI.
|
|
227
|
+
|
|
228
|
+
3. **Defensive eval reads.** Every `node.field` read (e.g. `transform.x`, `transform.width`) must be sentinel-checked before being used in arithmetic. A renamed field silently returns `NaN`/`null`, which fail-passes downstream comparisons. Add `isFinite(value)` / `value !== undefined` guards inline.
|
|
229
|
+
|
|
230
|
+
4. **No hardcoded literal IDs.** If a recipe contains hardcoded node-ID prefixes that don't match the current scene, the entire recipe degrades to no-op without errors. Verify at least one expected ID exists; if not, derive IDs by role at runtime and proceed with the corrected lookup. Flag the recipe as needing an ID-refresh fix.
|
|
231
|
+
|
|
232
|
+
5. **Reload checkpoint is not optional.** If the recipe has a `## Round-Trip Checkpoint` or `## Invariants` section mentioning reload/save/persistence — run it. If it does not, but the feature mutated persisted structure — run one anyway: `agent-view eval "location.reload()"`, wait for the app to come back, re-read the structural signature, diff. Drift is a real bug, not a "fixed-up on save".
|
|
233
|
+
|
|
234
|
+
6. **Recipe-stated invariants run first or fail closed.** If the recipe has an `## Invariants` section, execute those steps before the action-specific evidence commands. A failed invariant is FAIL for that invariant *and* a flag on the rest of the run — keep running the remaining steps, tag them as "trust-impaired until invariant restored".
|
|
235
|
+
|
|
236
|
+
7. **Never claim a `window.*` API is missing without `eval`.** Before reporting "API not exposed" / "global X doesn't exist" / "the host doesn't expose Y", you MUST run `agent-view eval "typeof window.X"` and report the literal result (`"undefined"` / `"object"` / `"function"`). DOM scraping cannot answer this question — globals are not in the AX tree. If `eval` returns `"undefined"`, the API really is absent from the main world; if it returns anything else, the API is reachable and your earlier conclusion was wrong. No exceptions, no "I checked the source code instead".
|
|
237
|
+
|
|
238
|
+
### Recipe Execution Mode (when a recipe file exists)
|
|
239
|
+
|
|
240
|
+
If the developer points you at a `.claude/verify-recipes/<slug>.md` file, or one is discoverable via `ls .claude/verify-recipes/`, execute it inline yourself — **no subagent**.
|
|
241
|
+
|
|
242
|
+
1. `Read` the recipe.
|
|
243
|
+
2. If it has a `## Repro Steps` section, follow them — log in, navigate, set up data — using `agent-view` commands. Modern recipes (0.6+) may have `## Manual Preconditions` / `## Bringup` / `## Machine Preconditions` instead; treat those as documentation describing the expected state and execute the actions inline. There is no formal DSL — read what the section says and do it.
|
|
244
|
+
3. Resolve the window id once with `agent-view discover` if you need `--window`.
|
|
245
|
+
4. **If the recipe has an `## Invariants` section, run those steps first.** A failed invariant is FAIL — record it, then continue to evidence commands but tag subsequent results as "trust-impaired" until the invariant is restored.
|
|
246
|
+
5. Run each `## Evidence Commands` subsection in order. Compare output to its `Expected:` line. Mark each as `pass` / `fail` / `requires_visual_review`. **Follow the Execution discipline above** — particularly rules 1 and 2.
|
|
247
|
+
6. After 2–3 consecutive failures, stop and flag the recipe as likely stale. Distinguish "recipe stale" (hardcoded IDs no longer match) from "feature broken" (invariants violated on a current scene).
|
|
248
|
+
7. Run `## Regression Checks`.
|
|
249
|
+
8. **Run the round-trip checkpoint** (discipline rule 5) — either the recipe's section or, if absent and the feature is persistent, an ad-hoc reload check.
|
|
250
|
+
9. If a `## Design Conformance` section is present, run the inline workflow below.
|
|
251
|
+
10. Report a tight summary: passed / failed / visual-review counts plus one-liner per failure, and **any invariant violations called out separately**. Don't paste raw stdout unless asked.
|
|
252
|
+
|
|
253
|
+
### Ad-hoc Mode (standalone)
|
|
254
|
+
|
|
255
|
+
After making code changes:
|
|
256
|
+
|
|
257
|
+
1. **Determine affected areas** from git diff
|
|
258
|
+
2. **Ensure app is running**: `agent-view launch` or `agent-view discover`
|
|
259
|
+
3. **Inspect DOM**: `agent-view dom --filter "<area>" --depth 2` — check structure matches expectations
|
|
260
|
+
4. **Interact if needed**: `agent-view click`/`fill` → `agent-view dom --filter` to verify state changed
|
|
261
|
+
5. **For canvas apps**: `agent-view scene --diff` to see what changed
|
|
262
|
+
6. **For non-DOM truth** (store, computed values, worker state): `agent-view eval` — much cheaper than reading the DOM tree to infer state
|
|
263
|
+
7. **After any interaction that could fail silently**: `agent-view console --level error` — catches uncaught exceptions, network failures, framework warnings
|
|
264
|
+
8. **Screenshot only for final visual confirm**: `agent-view screenshot --scale 0.5` — captures layout/styling that DOM can't reveal
|
|
265
|
+
|
|
266
|
+
### Scenario Execution Mode (from plan)
|
|
267
|
+
|
|
268
|
+
When UI scenarios are pre-generated (e.g., from a plan file with `## UI Scenarios` section):
|
|
269
|
+
|
|
270
|
+
1. **Read scenario steps** with symbolic refs (`$var` notation)
|
|
271
|
+
2. **Resolve each $var**: `agent-view dom --filter "<text>" --depth 3` → map to ref ID
|
|
272
|
+
3. **Execute steps** sequentially: fill, click, dom --filter (verify expected outcome)
|
|
273
|
+
4. **Screenshot**: `agent-view screenshot --scale 0.5` — only on FAIL and at E2E scenario end, not every step
|
|
274
|
+
5. **Report per-scenario**: PASS / FAIL with reason and evidence
|
|
275
|
+
|
|
276
|
+
This mode works with any workflow that generates plan files with UI scenarios.
|
|
277
|
+
|
|
278
|
+
### Design Conformance (inline)
|
|
279
|
+
|
|
280
|
+
When a recipe contains a `## Design Conformance` table — `(label, screenshot command, expected reference path)` rows — execute it yourself, no subagent.
|
|
281
|
+
|
|
282
|
+
For each row:
|
|
283
|
+
1. Run the screenshot command (capture the saved file path from stdout).
|
|
284
|
+
2. `Read` both the captured image and the `expected_path`. If `expected_path` doesn't exist or is unreadable, mark the pair `skipped (expected_missing)` and move on.
|
|
285
|
+
3. Compare visually for: layout (relative position, alignment), sizing, color (dominant color family), typography (weight/size broadly), content presence (anything missing or extra), decorations (borders, shadows, dashed/solid lines, icons).
|
|
286
|
+
4. Report each pair as `match` / `minor_mismatch` / `major_mismatch` with a one-sentence deviation. Major = missing/wrong component, broken layout, wrong color family, wrong text content. Minor = <10px spacing drift, slight color shade, small decoration difference.
|
|
287
|
+
|
|
288
|
+
Tolerance default: a designer's code-review level — flag what they'd notice, ignore anti-aliasing noise. Don't speculate about CSS causes — describe what looks different and let the parent / user decide.
|
|
289
|
+
|
|
290
|
+
## Resilience
|
|
291
|
+
|
|
292
|
+
- **Stale refs:** After HMR, navigation, or state change — re-run `dom` for fresh refs before interacting
|
|
293
|
+
- **Element not found:** Wait 2s, retry once (render delay after HMR). If still missing — report FAIL
|
|
294
|
+
- **CDP disconnect:** Run `agent-view discover` to check. If no windows — `agent-view launch` (auto-starts Electron/Browser/Tauri). On `PORT_CONFLICT` — surface PID/process and ask user.
|
|
295
|
+
- **Max retries per command:** 2. After that — SKIP scenario step with warning
|
|
296
|
+
|
|
297
|
+
## Important Notes
|
|
298
|
+
|
|
299
|
+
- **Refs are session-scoped** — after HMR or navigation, run `dom` again for fresh refs
|
|
300
|
+
- **Multiple windows**: use `--window <id>` from `discover` output when titles overlap
|
|
301
|
+
- **Multiwindow**: all commands support `--window` flag
|
|
302
|
+
- **Output format**: plain text (DOM, scene), JSON (discover only), file path (screenshot)
|
|
303
|
+
- **Lazy server**: auto-starts on first call, shuts down after 5min idle
|
|
304
|
+
|
|
305
|
+
## Token Optimization
|
|
306
|
+
|
|
307
|
+
Vision tokens dominate cost. One full-res screenshot ≈ 19k tokens (1920×1080, 12 tiles).
|
|
308
|
+
|
|
309
|
+
| Technique | Savings |
|
|
310
|
+
|---|---|
|
|
311
|
+
| `agent-view eval "expr"` for state checks | Returns one value (~50 tokens) instead of a DOM/screenshot |
|
|
312
|
+
| `agent-view dom --filter "row" --count` | Single integer answer — zero tree tokens |
|
|
313
|
+
| `agent-view dom --filter X --depth 2` | Narrow tree to relevant subtree, cap depth |
|
|
314
|
+
| `agent-view screenshot --scale 0.5` | ~3× fewer vision tokens (4 tiles) |
|
|
315
|
+
| `agent-view screenshot --scale 0.25` | ~12× fewer vision tokens (1 tile, ~1.6k tokens) |
|
|
316
|
+
| `agent-view screenshot --crop "<element>"` | ~12× fewer in best case (1 tile) — crops to element bounding box |
|
|
317
|
+
| DOM/eval-first: screenshot only for final visual confirm | Eliminates most screenshot calls |
|
|
318
|
+
|
|
319
|
+
**Default rule**: if the answer is a value → `eval`; if the answer is "is element X visible/correct?" → `agent-view dom --filter`; if you need pixels for a specific section → `screenshot --crop "<element>"` (one tile); only call `screenshot --scale 0.5` for full-window visual proof.
|