@petukhovart/agent-view 0.3.0 → 0.5.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/marketplace.json +14 -0
- package/.claude-plugin/plugin.json +2 -2
- package/README.md +164 -113
- package/dist/cdp/ax-cache.d.ts +7 -0
- package/dist/cdp/ax-cache.d.ts.map +1 -1
- package/dist/cdp/ax-cache.js +7 -0
- package/dist/cdp/ax-cache.js.map +1 -1
- package/dist/cdp/transport.d.ts.map +1 -1
- package/dist/cdp/transport.js +98 -27
- package/dist/cdp/transport.js.map +1 -1
- package/dist/cdp/types.d.ts +45 -2
- package/dist/cdp/types.d.ts.map +1 -1
- package/dist/cdp/types.js +6 -0
- package/dist/cdp/types.js.map +1 -1
- package/dist/cli/commands/console.d.ts +1 -0
- package/dist/cli/commands/console.d.ts.map +1 -1
- package/dist/cli/commands/console.js +1 -0
- package/dist/cli/commands/console.js.map +1 -1
- package/dist/cli/commands/dom.d.ts +4 -0
- package/dist/cli/commands/dom.d.ts.map +1 -1
- package/dist/cli/commands/dom.js +4 -0
- package/dist/cli/commands/dom.js.map +1 -1
- package/dist/cli/commands/drag.d.ts +13 -0
- package/dist/cli/commands/drag.d.ts.map +1 -0
- package/dist/cli/commands/drag.js +72 -0
- package/dist/cli/commands/drag.js.map +1 -0
- package/dist/cli/commands/scene.d.ts +1 -0
- package/dist/cli/commands/scene.d.ts.map +1 -1
- package/dist/cli/commands/scene.js +2 -0
- package/dist/cli/commands/scene.js.map +1 -1
- package/dist/cli/commands/screenshot.d.ts +1 -0
- package/dist/cli/commands/screenshot.d.ts.map +1 -1
- package/dist/cli/commands/screenshot.js +4 -0
- package/dist/cli/commands/screenshot.js.map +1 -1
- package/dist/cli/commands/snap.d.ts +1 -0
- package/dist/cli/commands/snap.d.ts.map +1 -1
- package/dist/cli/commands/snap.js +2 -0
- package/dist/cli/commands/snap.js.map +1 -1
- package/dist/cli/commands/watch.d.ts +12 -0
- package/dist/cli/commands/watch.d.ts.map +1 -0
- package/dist/cli/commands/watch.js +233 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/index.js +48 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/config/manager.js +1 -1
- package/dist/config/types.d.ts +0 -3
- package/dist/config/types.d.ts.map +1 -1
- package/dist/inspectors/dom/index.d.ts +13 -0
- package/dist/inspectors/dom/index.d.ts.map +1 -1
- package/dist/inspectors/dom/index.js +255 -103
- package/dist/inspectors/dom/index.js.map +1 -1
- package/dist/inspectors/scene/formatter.d.ts.map +1 -1
- package/dist/inspectors/scene/formatter.js +56 -8
- package/dist/inspectors/scene/formatter.js.map +1 -1
- package/dist/inspectors/scene/types.d.ts +1 -0
- package/dist/inspectors/scene/types.d.ts.map +1 -1
- package/dist/inspectors/watch/index.d.ts +18 -0
- package/dist/inspectors/watch/index.d.ts.map +1 -0
- package/dist/inspectors/watch/index.js +39 -0
- package/dist/inspectors/watch/index.js.map +1 -0
- package/dist/inspectors/watch/types.d.ts +70 -0
- package/dist/inspectors/watch/types.d.ts.map +1 -0
- package/dist/inspectors/watch/types.js +21 -0
- package/dist/inspectors/watch/types.js.map +1 -0
- package/dist/server/server.d.ts +9 -1
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +279 -48
- package/dist/server/server.js.map +1 -1
- package/dist/server/watch-session.d.ts +32 -0
- package/dist/server/watch-session.d.ts.map +1 -0
- package/dist/server/watch-session.js +165 -0
- package/dist/server/watch-session.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +61 -60
- package/skills/verify/SKILL.md +64 -13
- package/skills/verify-recipe/SKILL.md +185 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "agent-view",
|
|
3
|
+
"owner": {
|
|
4
|
+
"name": "PetukhovArt",
|
|
5
|
+
"url": "https://github.com/PetukhovArt"
|
|
6
|
+
},
|
|
7
|
+
"plugins": [
|
|
8
|
+
{
|
|
9
|
+
"name": "agent-view",
|
|
10
|
+
"source": "./",
|
|
11
|
+
"description": "Visual verification CLI for desktop apps (Electron/Tauri/Browser) via Chrome DevTools Protocol. Inspect DOM, interact with UI, capture screenshots, and read WebGL scene graphs."
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-view",
|
|
3
|
-
"description": "Visual verification CLI for desktop apps (Electron/Tauri/Browser) via Chrome DevTools Protocol.
|
|
4
|
-
"version": "0.
|
|
3
|
+
"description": "Visual verification CLI for desktop apps (Electron/Tauri/Browser) via Chrome DevTools Protocol. Ships two skills: verify (run DOM, screenshot, eval, watch, console checks against a live app) and verify-recipe (author a disciplined verification plan as a .md file).",
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cdp",
|
|
7
7
|
"electron",
|
package/README.md
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
# agent-view
|
|
2
2
|
|
|
3
|
-
**Give your AI agent eyes and hands for desktop apps
|
|
3
|
+
**Give your AI agent eyes and hands for complex desktop apps verification**
|
|
4
4
|
|
|
5
5
|
AI coding agents can write code, run tests, and read logs — but they can't *see* what the app actually looks like. Without visual verification, an agent is essentially **coding blind** — builds pass, tests are green, but the login form is broken, the button is off-screen, or the modal never appears.
|
|
6
6
|
|
|
7
|
-
agent-view bridges that gap: it connects to any Chromium-based desktop app via Chrome DevTools Protocol and lets the agent inspect
|
|
7
|
+
agent-view bridges that gap: it connects to any Chromium-based desktop app via Chrome DevTools Protocol and lets the agent inspect, interact, and verify.
|
|
8
8
|
|
|
9
9
|
Built for [Claude Code](https://docs.anthropic.com/en/docs/claude-code), but works with any AI agent or automation pipeline that can call CLI commands.
|
|
10
10
|
|
|
11
|
+
## What it does
|
|
12
|
+
|
|
13
|
+
- **DOM accessibility tree** with ref IDs — compact, LLM-friendly, with text/role filters; `--compact` merges single-child chains for 40–60% fewer tokens, `--count` returns just the match count, `--max-lines` caps output, `--diff` emits only what changed since the last call
|
|
14
|
+
- **Screenshots** — full-res PNG, scaled WebP (~3–12× fewer vision tokens), or `--crop <filter>` to a single element bounding box
|
|
15
|
+
- **Interaction** — click, fill, and drag by ref or coordinates; works with Vue/React/native frameworks
|
|
16
|
+
- **JS state via `eval`** — read store contents, computed values, async results without scraping the DOM
|
|
17
|
+
- **Reactive state via `watch`** — stream JSON-patch diffs of any expression (store, ref, computed) until a condition is met
|
|
18
|
+
- **Console capture** — `console.log/warn/error` per page and per worker, with level/since filters and `--follow --until <pattern>` for early exit on a matching log
|
|
19
|
+
- **Worker access** — SharedWorker, ServiceWorker, dedicated Worker visible alongside pages; fuzzy `--target` resolution everywhere (id → title → URL)
|
|
20
|
+
- **Canvas / WebGL scene graph** — PixiJS today, engine-pluggable; `--compact` mirrors the DOM mode
|
|
21
|
+
|
|
11
22
|
## Why CLI, not MCP?
|
|
12
23
|
|
|
13
24
|
Most alternatives in this space are MCP servers with 30+ tool definitions loaded into context on every session. That burns tokens before the agent even starts working.
|
|
@@ -16,68 +27,70 @@ agent-view is a CLI. One Bash call, compact text output, zero schema overhead. T
|
|
|
16
27
|
|
|
17
28
|
And CLI works everywhere — Claude Code, Copilot, Codex, custom pipelines, CI. No MCP client required.
|
|
18
29
|
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
The real power isn't in individual commands — it's in the **loop**:
|
|
30
|
+
## Install & Update
|
|
22
31
|
|
|
23
|
-
|
|
24
|
-
Code → Launch → See → Verify → Fix → See again
|
|
25
|
-
```
|
|
32
|
+
### Claude Code (recommended)
|
|
26
33
|
|
|
27
|
-
|
|
34
|
+
Two steps — both required:
|
|
28
35
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- `eval <expr>` — read state directly (`store.user.role`, computed values, async getters). Gated by `"allowEval": true` in config.
|
|
34
|
-
- `eval --target <worker>` — same, but inside a SharedWorker / ServiceWorker / dedicated Worker.
|
|
35
|
-
- `console` — capture `console.log/warn/error` per page or per worker. `--clear` for baselines, `--level` to filter.
|
|
36
|
-
- `targets` — list every connectable CDP target.
|
|
36
|
+
```bash
|
|
37
|
+
# 1. Install the plugin — adds two skills: verify (run checks against a live app) and verify-recipe (author a verification plan)
|
|
38
|
+
/plugin marketplace add PetukhovArt/agent-view
|
|
39
|
+
/plugin install agent-view@agent-view
|
|
37
40
|
|
|
38
|
-
|
|
41
|
+
# 2. Install the CLI — the skill calls these binaries; the plugin doesn't bundle them
|
|
42
|
+
npm install -g @petukhovart/agent-view
|
|
43
|
+
```
|
|
39
44
|
|
|
40
|
-
|
|
45
|
+
The plugin ships two skills. **`verify`** executes visual and runtime checks against a running app. **`verify-recipe`** generates a `.claude/verify-recipes/<slug>.md` file — a disciplined, cheapest-first command sequence for a feature or bugfix — that you or any AI agent can run later. Trigger it with phrases like "write a verify-recipe for the login fix" or "generate a verification plan for this feature".
|
|
41
46
|
|
|
42
|
-
|
|
47
|
+
Verify:
|
|
43
48
|
|
|
44
|
-
|
|
49
|
+
```bash
|
|
50
|
+
agent-view --version # 0.5.0+
|
|
51
|
+
```
|
|
45
52
|
|
|
46
|
-
|
|
47
|
-
|---|---|---|---|
|
|
48
|
-
| `dom` cold fetch | 10ms | 2ms | ~30–80ms |
|
|
49
|
-
| `dom` warm (cache hit) | 10ms | 1ms | ~30–80ms |
|
|
50
|
-
| Full cycle `dom → click → dom` | 27ms | 17ms | ~75ms |
|
|
51
|
-
| `click --filter "Save"` | 12ms | 17ms† | ~15–30ms |
|
|
53
|
+
### Standalone CLI (any other agent, CI, or scripting)
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
```bash
|
|
56
|
+
npm install -g @petukhovart/agent-view
|
|
57
|
+
```
|
|
55
58
|
|
|
56
|
-
|
|
59
|
+
Everything works from this alone — `agent-view dom`, `screenshot`, `eval`, etc. Skip the plugin step.
|
|
57
60
|
|
|
58
|
-
|
|
61
|
+
### Update
|
|
59
62
|
|
|
60
|
-
|
|
63
|
+
```bash
|
|
64
|
+
# Update the CLI to the latest version
|
|
65
|
+
npm update -g @petukhovart/agent-view
|
|
61
66
|
|
|
62
|
-
|
|
67
|
+
# Update the Claude Code plugin (refreshes skills from the marketplace)
|
|
68
|
+
/plugin marketplace update agent-view
|
|
69
|
+
/plugin install agent-view@agent-view # re-run to pick up new skill versions
|
|
70
|
+
```
|
|
63
71
|
|
|
64
|
-
|
|
72
|
+
The two are independent — bump the CLI when a new release ships features (see `CHANGELOG.md`), bump the plugin when skill instructions change.
|
|
65
73
|
|
|
66
74
|
## Enabling CDP
|
|
67
75
|
|
|
76
|
+
agent-view talks to your app over Chrome DevTools Protocol. Your app must be launched with a debugging port open.
|
|
77
|
+
|
|
68
78
|
### Recommended: in code (reliable, works with any build tool)
|
|
69
79
|
|
|
70
80
|
Add to your Electron main process:
|
|
71
81
|
|
|
72
82
|
```js
|
|
73
|
-
app.commandLine.appendSwitch('remote-debugging-port', '
|
|
83
|
+
app.commandLine.appendSwitch('remote-debugging-port', '9876');
|
|
74
84
|
```
|
|
75
85
|
|
|
86
|
+
> Any free port works — `9876` is just an example. Avoid `9222` (Chrome's own default remote-debugging port) to prevent
|
|
87
|
+
> collisions when Chrome is open.
|
|
88
|
+
|
|
76
89
|
For dev-only:
|
|
77
90
|
|
|
78
91
|
```js
|
|
79
92
|
if (!app.isPackaged) {
|
|
80
|
-
|
|
93
|
+
app.commandLine.appendSwitch('remote-debugging-port', '9876');
|
|
81
94
|
}
|
|
82
95
|
```
|
|
83
96
|
|
|
@@ -85,46 +98,26 @@ if (!app.isPackaged) {
|
|
|
85
98
|
|
|
86
99
|
```bash
|
|
87
100
|
# Plain Electron
|
|
88
|
-
electron . --remote-debugging-port=
|
|
101
|
+
electron . --remote-debugging-port=9876
|
|
89
102
|
|
|
90
103
|
# electron-vite (note the -- to forward the flag past the build tool)
|
|
91
|
-
npx electron-vite dev -- --remote-debugging-port=
|
|
104
|
+
npx electron-vite dev -- --remote-debugging-port=9876
|
|
92
105
|
```
|
|
93
106
|
|
|
94
107
|
### Other runtimes
|
|
95
108
|
|
|
96
|
-
| Runtime
|
|
97
|
-
|
|
98
|
-
| **Tauri**
|
|
99
|
-
| **Any Chromium app** | `--remote-debugging-port=
|
|
109
|
+
| Runtime | Setup |
|
|
110
|
+
|----------------------|--------------------------------------------|
|
|
111
|
+
| **Tauri** | CDP via devtools configuration |
|
|
112
|
+
| **Any Chromium app** | `--remote-debugging-port=9876` launch flag |
|
|
100
113
|
|
|
101
114
|
### Verify CDP is working
|
|
102
115
|
|
|
103
116
|
```bash
|
|
104
|
-
curl -s http://localhost:
|
|
117
|
+
curl -s http://localhost:9876/json/version
|
|
105
118
|
```
|
|
106
119
|
|
|
107
|
-
If you see a JSON response with
|
|
108
|
-
|
|
109
|
-
## Install
|
|
110
|
-
|
|
111
|
-
### As CLI tool
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
npm install -g @petukhovart/agent-view
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### As Claude Code plugin
|
|
118
|
-
|
|
119
|
-
```bash
|
|
120
|
-
# Add marketplace (once)
|
|
121
|
-
/plugin marketplace add PetukhovArt/agent-view
|
|
122
|
-
|
|
123
|
-
# Install plugin
|
|
124
|
-
/plugin install agent-view@agent-view
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
This gives Claude the `/agent-view:verify` skill — it knows when and how to use agent-view for visual verification during development workflows.
|
|
120
|
+
If you see a JSON response with process info — you're good.
|
|
128
121
|
|
|
129
122
|
## Quick start
|
|
130
123
|
|
|
@@ -144,7 +137,7 @@ agent-view screenshot # PNG screenshot
|
|
|
144
137
|
|
|
145
138
|
# 4. Interact
|
|
146
139
|
agent-view click 5 # Click element by ref
|
|
147
|
-
agent-view fill 3 "hello"
|
|
140
|
+
agent-view fill 3 "hello" # Type into input
|
|
148
141
|
|
|
149
142
|
# 5. Verify the result
|
|
150
143
|
agent-view dom --filter "success" # Check for expected element
|
|
@@ -161,28 +154,47 @@ A background server connects to your app's CDP port, caches sessions, and auto-s
|
|
|
161
154
|
|
|
162
155
|
## Config
|
|
163
156
|
|
|
164
|
-
Running `agent-view init` in your project root generates `agent-view.config.json
|
|
157
|
+
Running `agent-view init` in your project root generates `agent-view.config.json`. Minimal form:
|
|
165
158
|
|
|
166
159
|
```json
|
|
167
160
|
{
|
|
168
161
|
"runtime": "electron",
|
|
169
|
-
"port":
|
|
162
|
+
"port": 9876,
|
|
170
163
|
"launch": "npm run dev"
|
|
171
164
|
}
|
|
172
165
|
```
|
|
173
166
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
167
|
+
Full form with all optional fields:
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"runtime": "electron",
|
|
172
|
+
"port": 9876,
|
|
173
|
+
"launch": "npm run dev",
|
|
174
|
+
"allowEval": true,
|
|
175
|
+
"webgl": {
|
|
176
|
+
"engine": "pixi"
|
|
177
|
+
},
|
|
178
|
+
"consoleBufferSize": 500,
|
|
179
|
+
"consoleTargets": ["page", "shared_worker", "service_worker"]
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
| Field | Required | Description |
|
|
184
|
+
|---------------------|----------|-----------------------------------------------------------------------------------------------------------|
|
|
185
|
+
| `runtime` | yes | `"electron"`, `"tauri"`, or `"browser"` |
|
|
186
|
+
| `port` | yes | CDP debugging port |
|
|
187
|
+
| `launch` | no | Command to start the app |
|
|
188
|
+
| `webgl.engine` | no | `"pixi"` (scene extractor architecture supports adding more engines) |
|
|
189
|
+
| `allowEval` | no | `true` to enable `agent-view eval` and `watch`. Off by default — opt-in for arbitrary JS execution |
|
|
190
|
+
| `consoleBufferSize` | no | Per-target console ring capacity. Default `500` |
|
|
191
|
+
| `consoleTargets` | no | Target types `agent-view console` auto-attaches to. Default `["page", "shared_worker", "service_worker"]` |
|
|
183
192
|
|
|
184
193
|
## Commands
|
|
185
194
|
|
|
195
|
+
Every command targeting a window accepts `--window <id|title-substring>` (IDs come from `discover`). Examples below omit
|
|
196
|
+
it for brevity.
|
|
197
|
+
|
|
186
198
|
### `init`
|
|
187
199
|
|
|
188
200
|
Auto-generates config by reading `package.json`.
|
|
@@ -203,12 +215,22 @@ Dumps the accessibility tree in compact text format. Each element gets a session
|
|
|
203
215
|
agent-view dom
|
|
204
216
|
agent-view dom --filter "Submit" # Filter by text/role
|
|
205
217
|
agent-view dom --depth 3 # Limit tree depth
|
|
206
|
-
agent-view dom --
|
|
218
|
+
agent-view dom --max-lines 200 # Hard line budget (refs for hidden nodes still stored)
|
|
207
219
|
agent-view dom --text # Fall back to DOM textContent search when AX returns no match
|
|
220
|
+
agent-view dom --compact # Merge single-child chains onto one line (saves ~40-60% tokens)
|
|
221
|
+
agent-view dom --count # Return only the count of matching nodes (e.g. "5")
|
|
222
|
+
agent-view dom --filter "row" --count # Count how many rows match
|
|
223
|
+
agent-view dom --diff # Show only lines that changed since last call
|
|
208
224
|
```
|
|
209
225
|
|
|
210
226
|
When `--filter` is set, depth defaults to unlimited so deep matches aren't truncated.
|
|
211
227
|
|
|
228
|
+
`--count` skips tree formatting and ref-store mutations entirely — useful for assertions like "does this section have N rows?" without the token cost of a full tree dump.
|
|
229
|
+
|
|
230
|
+
`--max-lines <n>` caps the number of output lines. When the tree exceeds the budget, output is truncated after `n-1` lines and a summary tail `… M more nodes` is appended. Refs for all nodes — including those past the cutoff — are still registered in the ref store, so a follow-up `dom --filter` or `click <ref>` works without re-running.
|
|
231
|
+
|
|
232
|
+
`--diff` computes a line-level diff against the previous `dom` call for the same target. The first call always returns the full tree (no prior snapshot). Subsequent calls emit only added (`+ `) and removed (`- `) lines. Returns `No changes` when the tree is identical.
|
|
233
|
+
|
|
212
234
|
### `click`
|
|
213
235
|
|
|
214
236
|
Clicks a DOM element by ref ID or coordinates.
|
|
@@ -226,18 +248,40 @@ Types text into an input. Uses native value setter + dispatches input/change eve
|
|
|
226
248
|
agent-view fill 3 "hello@example.com"
|
|
227
249
|
```
|
|
228
250
|
|
|
251
|
+
### `drag`
|
|
252
|
+
|
|
253
|
+
HTML5 / pointer-driven drag-and-drop via CDP `Input.dispatchMouseEvent`
|
|
254
|
+
(`mousePressed` → N × `mouseMoved` → `mouseReleased`). Real mouse events, not
|
|
255
|
+
synthesized JS events — works with `vue-draggable-resizable`, `react-grid-layout`,
|
|
256
|
+
gridstack, kanban boards, file drop zones, map pin drags, resize handles.
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
agent-view drag --from 42 --to 88 # ref → ref
|
|
260
|
+
agent-view drag --from-pos 86,792 --to-pos 640,200 # coord → coord (canvas, custom DnD)
|
|
261
|
+
agent-view drag --from 42 --to-pos 640,200 # mixed
|
|
262
|
+
agent-view drag --from 5 --to 9 --steps 20 --hold-ms 150
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
`--steps` (default 10) controls intermediate `mouseMoved` events so libraries
|
|
266
|
+
that throttle on movement deltas still see continuous motion. `--hold-ms`
|
|
267
|
+
inserts a pause between press and the first move (some libs require >100ms
|
|
268
|
+
for touch-style activation). `--button` accepts `left|right|middle`.
|
|
269
|
+
|
|
229
270
|
### `screenshot`
|
|
230
271
|
|
|
231
|
-
Captures a screenshot, saves to temp dir, prints the file path. PNG by default;
|
|
272
|
+
Captures a screenshot, saves to temp dir, prints the file path. PNG by default; WebP (q=80) when `--scale` is set (JPEG fallback for older Chrome/Electron).
|
|
232
273
|
|
|
233
274
|
```bash
|
|
234
275
|
agent-view screenshot
|
|
235
|
-
agent-view screenshot --
|
|
236
|
-
agent-view screenshot --scale 0.
|
|
237
|
-
agent-view screenshot --
|
|
276
|
+
agent-view screenshot --scale 0.5 # Half-res WebP (~3× fewer vision tokens)
|
|
277
|
+
agent-view screenshot --scale 0.25 # Quarter-res WebP (~12× fewer, 1 tile)
|
|
278
|
+
agent-view screenshot --crop "Sidebar" # Crop to element bounding box (~12× fewer in best case)
|
|
279
|
+
agent-view screenshot --crop "Chart" --scale 0.5 # Crop + scale (stacks)
|
|
238
280
|
```
|
|
239
281
|
|
|
240
|
-
`--scale` accepts a factor in `(0, 1]`. CDP-side clip +
|
|
282
|
+
`--scale` accepts a factor in `(0, 1]`. CDP-side clip + WebP encode — recommended for agent loops where vision tokens dominate cost.
|
|
283
|
+
|
|
284
|
+
`--crop <filter>` resolves a DOM element by the same filter syntax as `dom --filter`, then crops the screenshot to its bounding box before encoding. One tile (~1.6k vision tokens) instead of twelve (~19k) in the best case. If the filter matches nothing a warning is emitted to stderr and the full window is captured instead. Combines naturally with `--scale`.
|
|
241
285
|
|
|
242
286
|
### `scene`
|
|
243
287
|
|
|
@@ -248,14 +292,16 @@ agent-view scene # Full scene graph
|
|
|
248
292
|
agent-view scene --diff # Changes since last call
|
|
249
293
|
agent-view scene --filter "player" # Filter by name/type
|
|
250
294
|
agent-view scene --verbose # Extended props (alpha, scale, bounds)
|
|
295
|
+
agent-view scene --compact # Merge single-child chains onto one line
|
|
251
296
|
```
|
|
252
297
|
|
|
253
298
|
### `snap`
|
|
254
299
|
|
|
255
|
-
Combined DOM + scene graph in one call. Shows DOM always; scene section appears when a WebGL engine is detected.
|
|
300
|
+
Combined DOM + scene graph in one call. Shows DOM always; scene section appears when a WebGL engine is detected. Pass `--scale` to also capture a screenshot and append it as a third section.
|
|
256
301
|
|
|
257
302
|
```bash
|
|
258
303
|
agent-view snap
|
|
304
|
+
agent-view snap --scale 0.5 # DOM + Scene + Screenshot (path written to tmp)
|
|
259
305
|
```
|
|
260
306
|
|
|
261
307
|
### `wait`
|
|
@@ -301,55 +347,60 @@ Streams or dumps console output (`Runtime.consoleAPICalled` + `Log.entryAdded`)
|
|
|
301
347
|
```bash
|
|
302
348
|
agent-view console # buffered messages since attach
|
|
303
349
|
agent-view console --follow --timeout 10 # stream for 10s
|
|
304
|
-
agent-view console --
|
|
350
|
+
agent-view console --follow --until "ready" # exit as soon as a message contains "ready"
|
|
351
|
+
agent-view console --follow --until "/error/i" # exit on regex match (case-insensitive)
|
|
352
|
+
agent-view console --target IJ56KL # restrict to one target (exact id)
|
|
353
|
+
agent-view console --target sync-worker # restrict to one target (title/URL substring)
|
|
305
354
|
agent-view console --level error,warn # level filter
|
|
306
355
|
agent-view console --since "2026-04-26T10:00:00Z"
|
|
307
356
|
agent-view console --clear # drop in-memory ring
|
|
308
357
|
```
|
|
309
358
|
|
|
310
|
-
|
|
359
|
+
`--until <pattern>` requires `--follow`. Exits as soon as a message matches the pattern (substring or `/regex/flags`). On timeout without match exits non-zero with `Timeout: pattern not seen in <N>s`.
|
|
311
360
|
|
|
312
|
-
|
|
361
|
+
`--target` resolves the same way as `eval --target`: exact id wins, then title substring, then URL substring. If no match is found, an error is returned.
|
|
313
362
|
|
|
314
|
-
|
|
363
|
+
Default attached target types: `page`, `shared_worker`, `service_worker`. Override with `consoleTargets` in config.
|
|
315
364
|
|
|
316
|
-
|
|
365
|
+
### `watch`
|
|
317
366
|
|
|
318
|
-
|
|
367
|
+
Polls a JS expression and streams JSON-patch (RFC 6902) diffs as it changes. Closes the "what changed between click and final state?" gap that screenshots and DOM dumps can't cover. **Requires `"allowEval": true`** (same gate as `eval`).
|
|
319
368
|
|
|
320
369
|
```bash
|
|
321
|
-
agent-view
|
|
322
|
-
agent-view
|
|
370
|
+
agent-view watch "store.cart.total" # 250ms poll, exits at 10 changes or 30s
|
|
371
|
+
agent-view watch "appState" --interval 100 --duration 60 # tighter cadence, longer window
|
|
372
|
+
agent-view watch "store.status" --until "store.status === 'ready'" # wait-for assertion
|
|
373
|
+
agent-view watch "appState" --max-changes 1 # snapshot first change after a click
|
|
374
|
+
agent-view watch "appState" --json # NDJSON, one frame per line
|
|
323
375
|
```
|
|
324
376
|
|
|
325
|
-
|
|
377
|
+
Output frames: `init` (baseline value), `diff` (RFC 6902 ops since last frame), `error`, `stop`. SIGINT exits cleanly. Snapshot size cap 256 KB — narrow the expression (e.g. `store.cart.items.length`) when watching large objects.
|
|
326
378
|
|
|
327
|
-
|
|
328
|
-
|---------|--------|-----|
|
|
329
|
-
| `dom`, `scene`, `snap` | Plain text | LLM-friendly, minimal tokens |
|
|
330
|
-
| `discover` | JSON | Machine-parseable |
|
|
331
|
-
| `screenshot` | File path | Agent reads the image |
|
|
379
|
+
### `stop`
|
|
332
380
|
|
|
333
|
-
|
|
381
|
+
Stops the background lazy server.
|
|
334
382
|
|
|
335
|
-
|
|
383
|
+
## Output format
|
|
336
384
|
|
|
337
|
-
|
|
385
|
+
| Command | Format | Why |
|
|
386
|
+
|------------------------|------------|------------------------------|
|
|
387
|
+
| `dom`, `scene`, `snap` | Plain text | LLM-friendly, minimal tokens |
|
|
388
|
+
| `discover` | JSON | Machine-parseable |
|
|
389
|
+
| `screenshot` | File path | Agent reads the image |
|
|
338
390
|
|
|
339
|
-
|
|
340
|
-
claude --plugin-dir /path/to/agent-view
|
|
341
|
-
```
|
|
391
|
+
## Performance
|
|
342
392
|
|
|
343
|
-
|
|
393
|
+
Built for tight `dom → click → dom` loops. Typical Electron app, ~200 AX nodes:
|
|
344
394
|
|
|
345
|
-
|
|
395
|
+
| Scenario | agent-view | Playwright (estimate) |
|
|
396
|
+
|--------------------------------|------------|-----------------------|
|
|
397
|
+
| `dom` cold fetch | 2ms | ~30–80ms |
|
|
398
|
+
| `dom` warm (cache hit) | 1ms | ~30–80ms |
|
|
399
|
+
| Full cycle `dom → click → dom` | 17ms | ~75ms |
|
|
346
400
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
# Use that path with --plugin-dir
|
|
351
|
-
claude --plugin-dir "$(npm root -g)/agent-view"
|
|
352
|
-
```
|
|
401
|
+
What makes it fast: 300ms AX-tree cache (invalidated on `click`/`fill`/navigation; cached responses prefixed with
|
|
402
|
+
`[cache]`), parallel CDP calls in `click`, `Accessibility.queryAXTree` for filter lookups, and a single persistent CDP
|
|
403
|
+
WebSocket reused across commands (no relay).
|
|
353
404
|
|
|
354
405
|
## Example: testing a login flow
|
|
355
406
|
|
|
@@ -378,8 +429,8 @@ agent-view screenshot
|
|
|
378
429
|
|
|
379
430
|
### CDP not responding
|
|
380
431
|
|
|
381
|
-
1. Check the port is listening: `curl -s http://localhost:
|
|
382
|
-
2. For electron-vite: make sure you use `--` before the flag: `npx electron-vite dev -- --remote-debugging-port=
|
|
432
|
+
1. Check the port is listening: `curl -s http://localhost:9876/json/version`
|
|
433
|
+
2. For electron-vite: make sure you use `--` before the flag: `npx electron-vite dev -- --remote-debugging-port=9876`
|
|
383
434
|
3. Restart the app — HMR doesn't restart the main process
|
|
384
435
|
|
|
385
436
|
### Stale refs after HMR
|
package/dist/cdp/ax-cache.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import type { AXNode } from './types.js';
|
|
2
|
+
export type AxTreeResult = {
|
|
3
|
+
nodes: AXNode[];
|
|
4
|
+
fromCache: boolean;
|
|
5
|
+
};
|
|
2
6
|
export declare class AxTreeCache {
|
|
3
7
|
private entries;
|
|
4
8
|
get(key: string): AXNode[] | null;
|
|
9
|
+
getWithMeta(key: string): AxTreeResult & {
|
|
10
|
+
found: boolean;
|
|
11
|
+
};
|
|
5
12
|
set(key: string, nodes: AXNode[]): void;
|
|
6
13
|
invalidate(key: string): void;
|
|
7
14
|
invalidateAll(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ax-cache.d.ts","sourceRoot":"","sources":["../../src/cdp/ax-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AASxC,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAgC;IAE/C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI;IAUjC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAIvC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI7B,aAAa,IAAI,IAAI;CAGtB"}
|
|
1
|
+
{"version":3,"file":"ax-cache.d.ts","sourceRoot":"","sources":["../../src/cdp/ax-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AASxC,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,SAAS,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAgC;IAE/C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI;IAUjC,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE;IAQ3D,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAIvC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI7B,aAAa,IAAI,IAAI;CAGtB"}
|
package/dist/cdp/ax-cache.js
CHANGED
|
@@ -11,6 +11,13 @@ export class AxTreeCache {
|
|
|
11
11
|
}
|
|
12
12
|
return entry.nodes;
|
|
13
13
|
}
|
|
14
|
+
getWithMeta(key) {
|
|
15
|
+
const cached = this.get(key);
|
|
16
|
+
if (cached) {
|
|
17
|
+
return { nodes: cached, fromCache: true, found: true };
|
|
18
|
+
}
|
|
19
|
+
return { nodes: [], fromCache: false, found: false };
|
|
20
|
+
}
|
|
14
21
|
set(key, nodes) {
|
|
15
22
|
this.entries.set(key, { nodes, timestamp: Date.now() });
|
|
16
23
|
}
|
package/dist/cdp/ax-cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ax-cache.js","sourceRoot":"","sources":["../../src/cdp/ax-cache.ts"],"names":[],"mappings":"AAEA,MAAM,eAAe,GAAG,GAAG,CAAA;
|
|
1
|
+
{"version":3,"file":"ax-cache.js","sourceRoot":"","sources":["../../src/cdp/ax-cache.ts"],"names":[],"mappings":"AAEA,MAAM,eAAe,GAAG,GAAG,CAAA;AAY3B,MAAM,OAAO,WAAW;IACd,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAA;IAE/C,GAAG,CAAC,GAAW;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACnC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAA;QACvB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,GAAG,eAAe,EAAE,CAAC;YACnD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YACxB,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,KAAK,CAAC,KAAK,CAAA;IACpB,CAAC;IAED,WAAW,CAAC,GAAW;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC5B,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;QACxD,CAAC;QACD,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACtD,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,KAAe;QAC9B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IACzD,CAAC;IAED,UAAU,CAAC,GAAW;QACpB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAC1B,CAAC;IAED,aAAa;QACX,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;IACtB,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/cdp/transport.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/cdp/transport.ts"],"names":[],"mappings":"AAEA,OAAO,EAML,KAAK,SAAS,EAId,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,WAAW,EAKjB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAoBhD,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAkBpE;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAQ9E;AAsKD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,CAmBhG;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC,WAAW,CAAC,CAoNtB"}
|