chrome-agent 0.14.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +127 -282
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -1,346 +1,191 @@
1
1
  # chrome-agent
2
2
 
3
- Browser automation for AI agents. Single Rust binary, zero runtime dependencies, talks CDP directly to Chrome.
3
+ **Web tasks that compile.**
4
4
 
5
- ## Why
5
+ A browser doesn't report back. The click lands on a cookie banner, the form drops what you typed,
6
+ the page navigates away mid-action, and the tool returns success anyway. Everything the agent does
7
+ next is built on that.
6
8
 
7
- Existing tools (Playwright, Puppeteer, Selenium) carry heavy runtimes and weren't designed for agents. Agents need:
8
- - **Minimum tokens** a11y tree snapshots instead of raw HTML (~50 tokens vs ~2000)
9
- - **Minimum round-trips** — `--inspect` returns updated page state with every action
10
- - **Zero setup** — single binary, headless by default, no npm/Node required
11
- - **Persistent sessions** — login once, stay logged in across invocations
12
- - **Stable UIDs** — element identifiers based on `backendNodeId`, survive between inspects
13
- - **3 targeting modes** — uid from accessibility tree, CSS selectors, or coordinates
9
+ chrome-agent reads the page back after every action and answers which one it was: the change held,
10
+ something else took the click, or nothing could be observed. One word, in JSON, to branch on.
14
11
 
15
- ## Install
16
-
17
- ### For AI agents (recommended)
12
+ One 3 MB Rust binary over CDP. No Node runtime, no Playwright, no daemon.
18
13
 
19
- ```bash
20
- # Install the skill — your agent learns chrome-agent automatically
21
- npx skills add sderosiaux/chrome-agent
22
- ```
14
+ chrome-agent v0.16.0 (~28.2K lines of Rust in `src/`, blank and comment-only lines excluded; 3 MB binary)
23
15
 
24
- This installs a `SKILL.md` that teaches your agent (Claude Code, Cursor, Copilot, etc.) how to use chrome-agent, including the workflow, commands, and best practices.
16
+ Full documentation: [github.com/sderosiaux/chrome-agent](https://github.com/sderosiaux/chrome-agent).
25
17
 
26
- ### CLI binary
18
+ ## Install
27
19
 
28
20
  ```bash
29
- # npm (downloads prebuilt binary)
30
- npm install -g chrome-agent
31
-
32
- # or with npx (no install needed)
33
- npx chrome-agent --help
34
-
35
- # or with Cargo (builds from source)
36
- cargo install chrome-agent
21
+ npx skills add sderosiaux/chrome-agent # skill file + binary, for coding agents
22
+ npm install -g chrome-agent # prebuilt binary
23
+ npx chrome-agent --help # no install
24
+ cargo install chrome-agent # from source
37
25
  ```
38
26
 
39
- ## Quick Start
27
+ ## Quickstart
40
28
 
41
29
  ```bash
42
- # Navigate and inspect the page in one call
30
+ # Navigate and read the page as an accessibility tree with stable uids
43
31
  chrome-agent goto https://example.com --inspect
44
- # https://example.com — Example Domain
45
- # uid=n1 RootWebArea "Example Domain"
46
- # → uid=n9 heading "Example Domain" level=1
47
- # → uid=n10 paragraph "This domain is for..."
48
- # → uid=n12 link "Learn more"
32
+ # uid=n9 heading "Example Domain" level=1
33
+ # uid=n12 link "More information..."
49
34
 
50
- # Click by uid, get updated page state
35
+ # Act by uid, by CSS selector, or by coordinates
51
36
  chrome-agent click n12 --inspect
37
+ chrome-agent click --selector "button.submit"
38
+ chrome-agent click --xy 100,200
52
39
 
53
- # Fill a form field
40
+ # Fill, then check what the page kept
54
41
  chrome-agent fill --uid n20 "user@test.com"
42
+ chrome-agent assert value --uid n20 --equals "user@test.com"
55
43
 
56
- # Or target by CSS selector (when uids aren't practical)
57
- chrome-agent click --selector "button.submit"
58
- chrome-agent fill --selector "input[name=email]" "hello@test.com"
59
-
60
- # Extract article content (Mozilla Readability — reader mode)
44
+ # Content, not markup
61
45
  chrome-agent read
62
-
63
- # Extract full visible text (use --selector to scope, --truncate to cap)
46
+ chrome-agent extract --limit 30
64
47
  chrome-agent text --selector "main" --truncate 500
65
48
 
66
- # Evaluate JavaScript
67
- chrome-agent eval "document.title"
68
-
69
- # Screenshot (returns file path, not binary data)
70
- chrome-agent screenshot
71
- ```
72
-
73
- ## How It Works
74
-
75
- ```
76
- chrome-agent v0.14.0 (Rust, ~11.5K lines, 3 MB binary)
77
-
78
- │ WebSocket (Chrome DevTools Protocol)
79
-
80
- Chrome / Chromium (headless by default)
49
+ # JSON for everything
50
+ chrome-agent --json eval "document.title"
51
+ chrome-agent screenshot --format jpeg --quality 60 --max-width 1024
81
52
  ```
82
53
 
83
- No Node.js. No Playwright. No daemon required. Headless by default `--headed` for debugging.
84
-
85
- UIDs are stable across inspects (based on Chrome's `backendNodeId`). The agent inspects, picks a uid, acts — even minutes later. When a11y tree isn't practical, CSS selectors and coordinates work as fallbacks. Click auto-falls back to JS `.click()` when the element has no box model.
54
+ Chrome stays alive between invocations, so a command costs a connection, not a browser launch. Give
55
+ each parallel agent its own `--browser <name>`, or they corrupt each other's session state.
86
56
 
87
57
  ## Commands
88
58
 
89
- | Command | Description |
90
- |---------|------------|
91
- | `goto <url> [--inspect] [--max-depth N] [--header "K: V"]` | Navigate to URL. `--header` sends extra HTTP headers (repeatable) |
92
- | `inspect [--verbose] [--max-depth N] [--uid nN] [--filter "role,role"] [--max-chars N] [--offset K]` | Accessibility tree with stable uids. `--max-chars`/`--offset` cap and page the output |
93
- | `click <uid> [--inspect] [--max-depth N]` | Click by uid (JS fallback if no box model) |
94
- | `click --selector "css" [--inspect]` | Click by CSS selector |
95
- | `click --xy 100,200` | Click by coordinates |
96
- | `fill --uid <uid> <value> [--inspect]` | Fill input by uid |
97
- | `fill --selector "css" <value>` | Fill by CSS selector |
98
- | `fill-form <uid=val>...` | Batch fill multiple fields |
99
- | `read [--html] [--truncate N]` | Extract main content (Mozilla Readability) |
100
- | `text [uid] [--selector "css"] [--truncate N]` | Extract visible text (page or element) |
101
- | `eval <expression> [--selector "css"]` | Run JS in page context (`el` = matched element) |
102
- | `network [--filter "pattern"] [--body] [--live N]` | Capture network requests / API responses |
103
- | `console [--level error] [--clear]` | Show captured console.log/warn/error + JS exceptions |
104
- | `pipe` | Persistent connection: JSON stdin JSON stdout |
105
- | `wait <text\|url\|selector> <pattern>` | Wait for condition |
106
- | `wait network-idle [--idle-ms N] [--timeout N]` | Wait until the network is quiet (SPA/XHR settle) |
107
- | `type <text> [--selector "css"]` | Type into focused/selected element |
108
- | `press <key>` | Press Enter, Tab, Escape, etc. |
109
- | `scroll <down\|up\|uid>` | Scroll page or element into view |
110
- | `hover <uid>` | Hover over element |
111
- | `back` | Navigate back in history |
112
- | `screenshot [--filename name] [--format jpeg\|png] [--quality N] [--max-width N] [--uid nN\|--selector "css"]` | Screenshot file path. JPEG/max-width shrink it; `--uid`/`--selector` clip to one element |
113
- | `pdf [--filename name] [--landscape] [--background]` | Print the current page to a PDF file |
114
- | `download <url> [--out path] [--timeout N]` | Download a URL fetched in-page (cookies/auth preserved) → `{path,bytes,mime}` |
115
- | `tabs` | List open browser tabs |
116
- | `close [--purge]` | Close browser (--purge deletes profile/cookies) |
117
- | `status` | Show session info |
118
- | `stop` | Stop background daemon |
119
-
120
- ## Global Flags
59
+ | Command | What it does |
60
+ |---|---|
61
+ | `goto <url> [--inspect] [--header "K: V"]` | Navigate. Reports where you landed and what answered. |
62
+ | `inspect [--filter "role,role"] [--uid nN] [--urls] [--max-chars N] [--offset K]` | Accessibility tree with stable uids. |
63
+ | `diff` | What changed since the last inspect. |
64
+ | `click <uid> [--selector "css"] [--xy X,Y] [--inspect]` | Click. JS fallback when there is no box model. |
65
+ | `dblclick <uid>` | Double-click, same targeting modes. |
66
+ | `fill --uid <uid> <value>` | Fill an input. Reports the value the page kept. |
67
+ | `fill-form <uid=val>...` | Fill several fields at once. |
68
+ | `select --uid <uid> <value>` | Pick a `<select>` option by value or visible text. |
69
+ | `check <uid>` / `uncheck <uid>` | Idempotent checkbox and radio control. |
70
+ | `upload --uid <uid> <file>...` | Upload to a file input. |
71
+ | `drag <from-uid> <to-uid>` | Mouse-event drag. |
72
+ | `type <text>` / `press <key>` / `hover <uid>` / `scroll <down\|up\|uid>` | Keyboard and pointer primitives. |
73
+ | `wait <text\|url\|selector> <pattern>` | Wait for a condition. `wait network-idle` for SPA settle. |
74
+ | `assert value\|text\|url\|state\|exists ...` | Check a page fact. Exit 2 when it does not hold. |
75
+ | `read [--html] [--truncate N]` | Article extraction via Mozilla Readability. |
76
+ | `text [--selector "css"] [--truncate N]` | Visible text of the page or one element. |
77
+ | `extract [--limit N] [--scroll] [--a11y]` | Auto-detect repeating records. No selectors needed. |
78
+ | `eval <expression> [--selector "css"]` | JS in page context. |
79
+ | `screenshot [--format jpeg\|png] [--quality N] [--max-width N] [--uid nN]` | Screenshot to a file path. |
80
+ | `pdf [--filename name] [--landscape] [--background]` | Print the page to PDF. |
81
+ | `download <url> [--out path]` | Fetch in-page so cookies and auth carry over. |
82
+ | `network [--filter "pattern"] [--body] [--live N] [--abort "pattern"]` | Requests and API responses. |
83
+ | `console [--level error] [--clear]` | console.log/warn/error and JS exceptions. |
84
+ | `frame <selector\|main>` | Bind `eval`/`inspect` to an iframe, inside a `pipe`/`batch` process. |
85
+ | `emulate device --width W --height H` | Device metrics for one named page. |
86
+ | `pipe` / `batch` | Persistent JSON stdin/stdout, or a JSON array on stdin. |
87
+ | `tabs` / `status` / `history` / `close [--purge]` | Session management. |
88
+
89
+ ## Global flags
121
90
 
122
91
  ```
123
92
  --browser <name> Named browser profile (default: "default")
124
- --page <name> Named page/tab (default: "default")
125
- --connect [url] Connect to running Chrome (auto or explicit)
126
- --headed Show browser window (default is headless)
127
- --stealth Bypass bot detection (Cloudflare, Turnstile)
128
- --timeout <seconds> Command timeout (default: 30)
129
- --max-depth <N> Limit inspect tree depth (works with --inspect on any command)
93
+ --page <name> Named tab (default: "default")
94
+ --connect <auto|url> Attach to a running Chrome (a value is required)
95
+ --headed Show the browser window (default: headless)
96
+ --stealth Anti-detection CDP patches
130
97
  --copy-cookies Use cookies from your real Chrome profile
98
+ --timeout <seconds> Command timeout (default: 30)
99
+ --max-depth <N> Limit inspect depth
100
+ --verdict <mode> auto (default) reads the page back; off reports the action only
131
101
  --dialog <mode> JS dialog policy: accept (default), dismiss, or manual
132
- --dialog-text <text> Text submitted for prompt() dialogs under --dialog accept
133
102
  --ignore-https-errors Accept self-signed certificates
134
- --json Structured JSON output for all commands
103
+ --json Structured JSON output
135
104
  ```
136
105
 
137
- JS dialogs (`alert`/`confirm`/`prompt`/`beforeunload`) are auto-answered by default (`--dialog accept`) so the page never hangs on a blocking dialog.
106
+ ## What a response tells you
138
107
 
139
- ## The Inspect Act Inspect Loop
108
+ `ok:true` means the command ran, not that the page complied. Every mutating action carries a
109
+ `verdict`, a `verdict_reason` and a `next` — one token from `proceed`, `inspect`, `retry`,
110
+ `confirm`, `dismiss`, `stop` — so an agent branches without parsing prose.
140
111
 
141
- ```bash
142
- # 1. Navigate and inspect
143
- chrome-agent goto https://app.com/login --inspect
144
- # uid=n47 heading "Login" level=1
145
- # uid=n52 textbox "Email" focusable
146
- # uid=n58 textbox "Password" focusable
147
- # uid=n63 button "Sign In" focusable
148
-
149
- # 2. Act
150
- chrome-agent fill --uid n52 "user@test.com"
151
- chrome-agent fill --uid n58 "password123"
152
-
153
- # 3. Click with --inspect to get result + new state in one call
154
- chrome-agent click n63 --inspect
155
- # → Clicked uid=n63
156
- # → uid=n101 heading "Dashboard" level=1
157
- # → uid=n105 navigation "Main menu"
158
- ```
159
-
160
- UIDs (n47, n52, etc.) are stable — they won't change between inspects as long as the DOM node exists.
161
-
162
- ## Network Capture
163
-
164
- Extract API data directly instead of DOM scraping:
112
+ | `verdict` | Means |
113
+ |---|---|
114
+ | `changed` | The page moved; `delta` says how. |
115
+ | `navigated` | New document. Every stored uid is dead. |
116
+ | `intercepted` | Another element received the event; `intercepted_by` names it. |
117
+ | `not_kept` | The write reached the element and it does not hold it. Read `value.actual`. |
118
+ | `no_effect` | Delivery proven by hit test, and the tree stayed still. |
119
+ | `unchanged` | The tree was identical while the tool watched. Delivery not proven. |
120
+ | `unknown` | Nothing could be compared. Never repeat the action — it may already have landed. |
165
121
 
166
- ```bash
167
- # Show resources loaded by the page (stealth-safe, uses Performance API)
168
- chrome-agent network --filter "api"
122
+ Exit codes: `0` success, `1` error, `2` a claim this tool made did not hold, `130` Ctrl+C. `2` is
123
+ a failed `assert`, or a `macro run` guard that was checked and did not hold — nothing else.
169
124
 
170
- # Capture live traffic with response bodies (5 seconds)
171
- chrome-agent network --live 5 --body --filter "graphql"
125
+ ## uids
172
126
 
173
- # JSON output for structured extraction
174
- chrome-agent --json network --body --filter "api" --limit 10
175
- ```
127
+ Element ids come from Chrome's `backendNodeId`, printed as `n82`. They stay valid across inspects
128
+ of the same page. A navigation reassigns them all, so re-inspect after `goto`, `back`, or a click
129
+ that changes route. CSS selectors and coordinates work where a uid is impractical.
176
130
 
177
- ## Console Capture
131
+ ## Pipe mode
178
132
 
179
- See what the page logs useful for debugging and error detection:
133
+ One process, one connection, one JSON line per response, and uids stay stable across the whole
134
+ sequence — which is the reason to reach for it. The speed-up is real and small: pipe removes about
135
+ 12 ms of per-command overhead, worth 1.5x on a stream of reads (nine commands, 352 ms → 228 ms) and
136
+ 1.1x on a stream of fills and clicks (2029 ms → 1908 ms), where the settle window and the tree
137
+ re-read pipe does not touch are most of the cost. Measured on 2026-08-30, M4 Max, Chrome 152,
138
+ median of 9 runs (`scripts/measure-pipe.sh` in the repo).
180
139
 
181
140
  ```bash
182
- chrome-agent console # all messages
183
- chrome-agent console --level error # errors + exceptions only
184
- chrome-agent console --clear # read and clear buffer
185
- ```
186
-
187
- Stealth-safe: uses injected interceptor, not `Runtime.enable`.
188
-
189
- ## Pipe Mode
190
-
191
- Persistent connection for high-performance agent workflows:
192
-
193
- ```bash
194
- # Start pipe (one connection, reads JSON from stdin)
195
141
  echo '{"cmd":"goto","url":"https://example.com","inspect":true}
196
142
  {"cmd":"click","uid":"n12","inspect":true}
197
143
  {"cmd":"read"}' | chrome-agent pipe
198
144
  ```
199
145
 
200
- Each command returns one JSON line: `{"ok":true,...}` or `{"ok":false,"error":"..."}`. 10x faster than spawning chrome-agent per command.
201
-
202
- ## Content Extraction
203
-
204
- ```bash
205
- # Article content (Readability — like Firefox Reader Mode)
206
- chrome-agent read
207
- # → # Article Title
208
- # → Clean article text without nav, footer, sidebar...
209
-
210
- # Full page text (scoped by selector)
211
- chrome-agent text --selector "[role=main]" --truncate 1000
212
-
213
- # Structured data via JS
214
- chrome-agent eval "JSON.stringify([...document.querySelectorAll('h2')].map(e => e.textContent))"
215
- ```
216
-
217
- ## Stealth Mode
218
-
219
- Many sites (Cloudflare, Turnstile) block headless Chrome. `--stealth` patches 7 automation fingerprints via CDP:
220
-
221
- ```bash
222
- chrome-agent --stealth goto https://protected-site.com --inspect
223
- ```
224
-
225
- What it patches:
226
- - `navigator.webdriver` → `undefined`
227
- - `chrome.runtime` → mocked (headless doesn't have it)
228
- - Permissions API → consistent with real browser
229
- - WebGL renderer → masks ANGLE/headless fingerprint
230
- - User-Agent → removes "HeadlessChrome"
231
- - Input `screenX`/`pageX` leak → random offset added
232
- - `Runtime.enable` → skipped (the #1 CDP detection vector)
233
-
234
- All patches are CDP-level (`Page.addScriptToEvaluateOnNewDocument`). No fake Chrome flags.
235
-
236
- ### Heavy bot protection (DataDome, Kasada)
237
-
238
- Some sites (Leboncoin, etc.) use advanced fingerprinting that detects bundled Chromium regardless of CDP patches. For these, connect to your real installed Chrome instead:
239
-
240
- ```bash
241
- # Launch your real Chrome with debugging enabled
242
- google-chrome --remote-debugging-port=9222 &
243
-
244
- # Connect chrome-agent to it
245
- chrome-agent --connect http://127.0.0.1:9222 goto https://www.leboncoin.fr --inspect
246
- ```
146
+ ## Bot detection
247
147
 
248
- Real Chrome has genuine canvas/audio/codec fingerprints that Chromium lacks.
148
+ `--stealth` applies 7 CDP-level patches: `navigator.webdriver`, `chrome.runtime`, the Permissions
149
+ API, the WebGL renderer, the User-Agent, an input coordinate leak, and never calling
150
+ `Runtime.enable`.
249
151
 
250
- | Protection Level | Solution |
152
+ | Protection | What works |
251
153
  |---|---|
252
154
  | None | `chrome-agent goto ...` |
253
- | Cloudflare/Turnstile | `chrome-agent --stealth goto ...` |
254
- | DataDome/Kasada | `chrome-agent --connect` to real Chrome |
155
+ | Cloudflare JS challenge | `--stealth` clears it |
156
+ | Cloudflare managed Turnstile, DataDome, Kasada | `--stealth` does not help. Use `--connect`. |
157
+ | Logged-in sites | `--copy-cookies`, optionally with `--stealth` |
255
158
 
256
- ## JSON Mode
159
+ Heavy protection fingerprints the Chromium binary itself, so the only route is a real installed
160
+ Chrome. `--copy-cookies` copies the cookie database from your Chrome profile and leaves your real
161
+ Chrome untouched.
257
162
 
258
163
  ```bash
259
- chrome-agent --json goto https://example.com --inspect
260
- # {"ok":true,"url":"...","title":"...","snapshot":"uid=n1 heading..."}
261
-
262
- chrome-agent --json eval "1+1"
263
- # → {"ok":true,"result":2}
264
-
265
- chrome-agent --json read
266
- # → {"ok":true,"title":"...","text":"...","excerpt":"...","byline":"..."}
267
-
268
- # Errors also structured (exit 1, JSON still on stdout for agent parsing):
269
- chrome-agent --json click n99
270
- # → {"ok":false,"error":"Element uid=n99 not found.","hint":"Run 'chrome-agent inspect'"}
271
- ```
272
-
273
- ## Multi-Tab
274
-
275
- ```bash
276
- chrome-agent --page main goto https://app.com
277
- chrome-agent --page docs goto https://docs.app.com
278
- chrome-agent --page main eval "document.title" # → "App"
279
- chrome-agent --page docs eval "document.title" # → "Docs"
280
- ```
281
-
282
- ### Parallel Agents
283
-
284
- Multiple agents sharing the same browser corrupt each other's sessions. Isolate with `--browser`:
285
-
286
- ```bash
287
- # Agent 1
288
- chrome-agent --browser agent1 goto https://example.com
289
-
290
- # Agent 2 (separate Chrome instance)
291
- chrome-agent --browser agent2 goto https://other.com
292
- ```
293
-
294
- ## Using with AI Agents
295
-
296
- ### Skill (recommended)
297
-
298
- ```bash
299
- npx skills add sderosiaux/chrome-agent
300
- ```
301
-
302
- This installs a SKILL.md that teaches your agent the full chrome-agent workflow, commands, and tips. Works with Claude Code, Cursor, Copilot, and any agent that reads skill files.
303
-
304
- ### Manual
305
-
306
- Tell your agent to run `chrome-agent --help` — the help output includes a complete LLM usage guide.
307
-
308
- ### Claude Code permissions
309
-
310
- ```json
311
- {
312
- "permissions": {
313
- "allow": ["Bash(chrome-agent *)"]
314
- }
315
- }
316
- ```
317
-
318
- ### Connect to Your Browser
319
-
320
- ```bash
321
- chrome-agent --connect inspect # auto-discover Chrome with debugging
322
- google-chrome --remote-debugging-port=9222 # or launch manually
164
+ google-chrome --remote-debugging-port=9222 &
165
+ chrome-agent --connect http://127.0.0.1:9222 goto https://www.leboncoin.fr --inspect
166
+ chrome-agent --stealth --copy-cookies goto x.com/home --inspect
323
167
  ```
324
168
 
325
169
  ## Comparison
326
170
 
327
- | | chrome-agent | dev-browser | chrome-devtools-mcp | Playwright MCP |
328
- |---|---|---|---|---|
329
- | Language | Rust | Rust + Node.js | TypeScript | TypeScript |
330
- | Runtime deps | none | Node.js + npm + Playwright + QuickJS | Node.js + Puppeteer | Node.js + Playwright |
331
- | Binary size | ~3 MB | ~3 MB (CLI) + ~200 MB (daemon + deps) | npm package | npm package |
332
- | CLI startup (reuse session) | ~10ms | ~500ms (daemon check) | N/A (MCP server) | N/A (MCP server) |
333
- | Element targeting | uid + CSS selector + coordinates | CSS selectors + snapshotForAI | uid (sequential) | CSS selectors |
334
- | UID stability | backendNodeId (stable across inspects) | N/A | sequential (reassigned each snapshot) | N/A |
335
- | Action + observe | `--inspect` flag (1 call) | 1 script (batched) | 1 MCP call per action | 1 MCP call per action |
336
- | Script batching | No (atomic commands + eval) | Full JS scripts in QuickJS sandbox | No | No |
337
- | Stealth mode | 7 CDP patches + Runtime.enable skip | No | No | No |
338
- | Reader mode | `read` (Mozilla Readability) | No | No | No |
339
- | Sandbox | Chrome sandbox | QuickJS WASM sandbox | Chrome sandbox | No |
340
- | Network capture | Retroactive + live | No | No | Metadata only (no bodies) |
341
- | Console capture | Stealth-safe interceptor | No | Console messages | No |
342
- | Pipe mode | JSON stdin/stdout | No | No | No |
343
- | Code | ~10.2K lines | ~76K lines (69K Playwright fork) | ~12K lines | Playwright |
171
+ | | chrome-agent | agent-browser (Vercel) | Playwright MCP |
172
+ |---|---|---|---|
173
+ | Language | Rust | Rust | TypeScript |
174
+ | Runtime deps | none | none (CLI) | Node + Playwright |
175
+ | Startup | 12 ms measured, one command on a running browser | daemon | cold start |
176
+ | UID stability | `backendNodeId`, stable across inspects | sequential, reassigned per snapshot | N/A |
177
+ | Compliance reporting | `verdict`/`next` on every action | no | no |
178
+ | Stealth | 7 CDP patches | delegated to cloud providers | none |
179
+ | Reader mode | `read` (Readability.js) | none | none |
180
+ | Record extraction | `extract`, structural, no LLM call | none | none |
181
+ | MCP server | none | yes | yes |
182
+ | Code | ~28.2K lines of Rust in `src/` (blank and comment-only lines excluded; a test re-measures it) | ~40K lines (their figure, unverified here) | Playwright |
183
+
184
+ ## Using it from an agent
185
+
186
+ `npx skills add sderosiaux/chrome-agent` installs a SKILL.md. Otherwise `chrome-agent --help`
187
+ embeds a full LLM usage guide, and every error carries a `hint` naming the next action. Claude Code
188
+ permissions: `{"permissions": {"allow": ["Bash(chrome-agent *)"]}}`.
344
189
 
345
190
  ## License
346
191
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "chrome-agent",
3
- "version": "0.14.0",
4
- "description": "Browser automation for AI agents. Single binary, zero dependencies, CDP direct.",
3
+ "version": "0.16.0",
4
+ "description": "Web tasks that compile. Browser automation that reads the page back after every action and reports what actually happened, in JSON. Single binary, CDP direct.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "chrome-agent": "./bin/chrome-agent.js"