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.
- package/README.md +127 -282
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,346 +1,191 @@
|
|
|
1
1
|
# chrome-agent
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Web tasks that compile.**
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
|
|
8
|
-
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
### For AI agents (recommended)
|
|
12
|
+
One 3 MB Rust binary over CDP. No Node runtime, no Playwright, no daemon.
|
|
18
13
|
|
|
19
|
-
|
|
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
|
-
|
|
16
|
+
Full documentation: [github.com/sderosiaux/chrome-agent](https://github.com/sderosiaux/chrome-agent).
|
|
25
17
|
|
|
26
|
-
|
|
18
|
+
## Install
|
|
27
19
|
|
|
28
20
|
```bash
|
|
29
|
-
#
|
|
30
|
-
npm install -g chrome-agent
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
##
|
|
27
|
+
## Quickstart
|
|
40
28
|
|
|
41
29
|
```bash
|
|
42
|
-
# Navigate and
|
|
30
|
+
# Navigate and read the page as an accessibility tree with stable uids
|
|
43
31
|
chrome-agent goto https://example.com --inspect
|
|
44
|
-
#
|
|
45
|
-
#
|
|
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
|
-
#
|
|
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
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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
|
-
|
|
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 |
|
|
90
|
-
|
|
91
|
-
| `goto <url> [--inspect] [--
|
|
92
|
-
| `inspect [--
|
|
93
|
-
| `
|
|
94
|
-
| `click --selector "css" [--inspect]` | Click
|
|
95
|
-
| `
|
|
96
|
-
| `fill --uid <uid> <value
|
|
97
|
-
| `fill
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
108
|
-
| `
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
112
|
-
| `
|
|
113
|
-
| `
|
|
114
|
-
| `
|
|
115
|
-
| `
|
|
116
|
-
| `
|
|
117
|
-
| `status`
|
|
118
|
-
|
|
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
|
|
125
|
-
--connect
|
|
126
|
-
--headed Show browser window (default
|
|
127
|
-
--stealth
|
|
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
|
|
103
|
+
--json Structured JSON output
|
|
135
104
|
```
|
|
136
105
|
|
|
137
|
-
|
|
106
|
+
## What a response tells you
|
|
138
107
|
|
|
139
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
167
|
-
|
|
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
|
-
|
|
171
|
-
chrome-agent network --live 5 --body --filter "graphql"
|
|
125
|
+
## uids
|
|
172
126
|
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
##
|
|
131
|
+
## Pipe mode
|
|
178
132
|
|
|
179
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
152
|
+
| Protection | What works |
|
|
251
153
|
|---|---|
|
|
252
154
|
| None | `chrome-agent goto ...` |
|
|
253
|
-
| Cloudflare
|
|
254
|
-
| DataDome
|
|
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
|
-
|
|
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
|
|
260
|
-
|
|
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 |
|
|
328
|
-
|
|
329
|
-
| Language | Rust | Rust
|
|
330
|
-
| Runtime deps | none |
|
|
331
|
-
|
|
|
332
|
-
|
|
|
333
|
-
|
|
|
334
|
-
|
|
|
335
|
-
|
|
|
336
|
-
|
|
|
337
|
-
|
|
|
338
|
-
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
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.
|
|
4
|
-
"description": "Browser automation
|
|
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"
|