cdpilot 0.9.4 → 0.9.5
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 +61 -17
- package/bin/cdpilot.js +1 -0
- package/package.json +1 -1
- package/src/cdpilot.py +2184 -162
package/README.md
CHANGED
|
@@ -28,14 +28,14 @@ No config files. No boilerplate. Just `npx` and go.
|
|
|
28
28
|
AI agents and developers need browser control that **just works**:
|
|
29
29
|
|
|
30
30
|
- **Zero config** — `npx cdpilot launch` starts an isolated browser session
|
|
31
|
-
- **Zero
|
|
31
|
+
- **Zero npm dependencies** — No Puppeteer, no Playwright, no Selenium. Pure CDP over HTTP/WebSocket; the Python side needs one package, `websockets` (the setup wizard installs it)
|
|
32
32
|
- **70+ commands** — Navigate, click, type, screenshot, network, console, accessibility, video understanding, progressive anti-bot resilience, and more
|
|
33
33
|
- **AI-agent friendly** — Designed for Claude, GPT, Gemini, and any LLM tool-use workflow
|
|
34
34
|
- **Isolated sessions** — Your personal browser stays untouched. cdpilot runs in its own profile
|
|
35
35
|
- **Visual feedback** — Green glow overlay, cursor visualization, click ripples, and keystroke display keep you informed during automation
|
|
36
36
|
- **Multi-project isolation** — Each project gets its own browser instance and port automatically, no conflicts
|
|
37
37
|
- **AI control warning** — Red toast notification appears when you hover during active automation
|
|
38
|
-
- **Privacy-first** — Everything runs locally
|
|
38
|
+
- **Privacy-first** — Everything runs locally; nothing leaves your machine unless you opt in (CAPTCHA solver keys, `tls-check`, proxies)
|
|
39
39
|
|
|
40
40
|
### Browser Selection (Workload-Aware Auto-Pick)
|
|
41
41
|
|
|
@@ -141,6 +141,15 @@ that teaches Claude Code when and how to reach for cdpilot's commands. See
|
|
|
141
141
|
[`.claude-plugin/marketplace.json`](.claude-plugin/marketplace.json) and
|
|
142
142
|
[`plugins/cdpilot/`](plugins/cdpilot/).
|
|
143
143
|
|
|
144
|
+
### Smaller MCP tool list
|
|
145
|
+
|
|
146
|
+
`cdpilot mcp --tools core` (or `CDPILOT_MCP_TOOLS=core`; the flag wins) lists 10 core
|
|
147
|
+
tools (navigate, click, fill, content, screenshot, eval, wait_for, assert, tabs, connect)
|
|
148
|
+
plus `browser_tools`. The agent calls `browser_tools` with `list` to see the other
|
|
149
|
+
tools, or `enable` to add some (the server sends `tools/list_changed`). `--tools a,b,c`
|
|
150
|
+
picks tools by name; `all` (default) is unchanged. Schema size of `tools/list`
|
|
151
|
+
(tiktoken `o200k_base`): 45 tools = 5,769 tokens, `core` = 11 tools = 1,342 tokens.
|
|
152
|
+
|
|
144
153
|
### MCP Bundle (.mcpb)
|
|
145
154
|
|
|
146
155
|
For MCP clients that support one-click local server installation (Claude
|
|
@@ -248,11 +257,19 @@ cdpilot frame eval --frame "#card" "document.title" # runs in the frame's
|
|
|
248
257
|
inside it and says so on stderr:
|
|
249
258
|
`note: '#card-element' is not an iframe; using the iframe inside it`.
|
|
250
259
|
- Selectors and texts that already contain `>>>` keep working: when the part
|
|
251
|
-
before the first `>>>` finds no iframe in the page, or a segment is empty
|
|
260
|
+
before the first `>>>` finds no iframe or shadow host in the page, or a segment is empty
|
|
252
261
|
(`click "Next >>>"`), the whole string is used as written, exactly as
|
|
253
262
|
before. If that fails too, one stderr line explains:
|
|
254
|
-
`note: 'Home' matched no iframe; used the selector as written`.
|
|
263
|
+
`note: 'Home' matched no iframe or shadow host; used the selector as written`.
|
|
255
264
|
`--frame` never falls back: a frame it cannot find is an error (exit 1).
|
|
265
|
+
- **Shadow DOM support**: `>>>` hops also pierce open shadow roots (`host.shadowRoot.querySelector(next)`).
|
|
266
|
+
Chains mix freely with iframes: `cdpilot click "iframe#pay >>> my-card >>> button.inner"` or
|
|
267
|
+
`cdpilot click "my-app >>> my-panel >>> input"`. A closed shadow root is unreachable by design
|
|
268
|
+
and fails with `'X' has a closed shadow root; cdpilot cannot reach inside it`.
|
|
269
|
+
When a plain CSS selector matches nothing at document level, cdpilot automatically falls back
|
|
270
|
+
to a depth-first search across all open shadow roots, printing one stderr note:
|
|
271
|
+
`note: '<sel>' found inside the shadow root of <host tag#id>`. Explicit `>>>` hops do not print this note.
|
|
272
|
+
`wait` and `wait-for` poll shadow roots every 200 ms alongside the document MutationObserver.
|
|
256
273
|
- For `smart-click` / `smart-fill` / `smart-select` the part before the first
|
|
257
274
|
`>>>` is a frame only if it looks like a selector (it has `#`, `.` or `[`,
|
|
258
275
|
or starts with an `iframe`/`frame` tag) or is `url=…`; words stay text.
|
|
@@ -298,14 +315,22 @@ cdpilot frame eval --frame "#card" "document.title" # runs in the frame's
|
|
|
298
315
|
### Debugging
|
|
299
316
|
|
|
300
317
|
```bash
|
|
301
|
-
cdpilot console [url]
|
|
302
|
-
cdpilot network [url]
|
|
303
|
-
cdpilot
|
|
304
|
-
cdpilot
|
|
305
|
-
cdpilot
|
|
306
|
-
cdpilot eval
|
|
318
|
+
cdpilot console [url] # Capture console logs
|
|
319
|
+
cdpilot network [url] # Monitor network requests
|
|
320
|
+
cdpilot network <url> --har trace.har # Export navigation traffic as HAR 1.2 JSON (--har - for stdout)
|
|
321
|
+
cdpilot debug [url] # Full diagnostic (console+network+perf+shot)
|
|
322
|
+
cdpilot perf # Performance metrics
|
|
323
|
+
cdpilot eval <js> # Execute JavaScript
|
|
324
|
+
cdpilot eval-batch <json> # Run N JS expressions in 1 roundtrip (5-30x faster)
|
|
307
325
|
```
|
|
308
326
|
|
|
327
|
+
#### Network monitoring & HAR export
|
|
328
|
+
|
|
329
|
+
`cdpilot network <url> --har <file>` exports all HTTP requests of a navigation as standard HAR 1.2 JSON (`--har -` writes to stdout).
|
|
330
|
+
- **Included:** URLs, methods, headers, status codes, query strings, and CDP timing breakdowns (DNS, connect, SSL, send, wait, receive).
|
|
331
|
+
- **Omitted:** Response bodies are not fetched or stored (avoids memory bloat and round-trip overhead); content.size reflects transfer length; bodySize is -1.
|
|
332
|
+
- **Masking:** Sensitive header values matching security patterns (`Cookie`, `Set-Cookie`, `Authorization`, `X-Api-Key`, token, secret) are replaced with `"«masked»"`. URLs are masked the same way as the session log: userinfo passwords and query/fragment parameters named like secrets (`token`, `key`, `code`, `session`, …) in `request.url`, `queryString`, `redirectURL` and URL-bearing header values (`Location`, `Referer`, `Link`); a `data:` URL keeps only its media type.
|
|
333
|
+
|
|
309
334
|
```bash
|
|
310
335
|
# Example: read 4 DOM values in a single CDP roundtrip instead of 4
|
|
311
336
|
cdpilot eval-batch '["document.title","location.href","document.links.length","document.images.length"]'
|
|
@@ -709,7 +734,7 @@ is dropped, never signalled.
|
|
|
709
734
|
|
|
710
735
|
**Idle close** still works while the signer runs: the signer is attached to every page, so instead
|
|
711
736
|
of "a page is attached" cdpilot counts the CDP clients other than the signer (by socket owner:
|
|
712
|
-
`netstat` on macOS
|
|
737
|
+
`netstat` with an `lsof` fallback on macOS, `netstat` on Windows, `ss` on Linux), and a `watch` daemon or a Playwright session keeps
|
|
713
738
|
the browser open. On Linux, `ss -tnp` shows only your own processes' sockets, so a client running
|
|
714
739
|
as another user is not counted and idle close may close the browser under it.
|
|
715
740
|
|
|
@@ -951,6 +976,23 @@ never changes a command's output or exit code, and a failed write costs one
|
|
|
951
976
|
stderr line. `CDPILOT_LOG=0` turns it off; `CDPILOT_LOG_DAYS` (default 14)
|
|
952
977
|
sets how many days are kept. The MCP server exposes it as `browser_log`.
|
|
953
978
|
|
|
979
|
+
### Record & replay
|
|
980
|
+
|
|
981
|
+
Record sequences of CLI commands into a portable flow JSON file and replay them with variable substitution:
|
|
982
|
+
|
|
983
|
+
```bash
|
|
984
|
+
cdpilot record start [--name <n>]
|
|
985
|
+
cdpilot record status
|
|
986
|
+
cdpilot record cancel
|
|
987
|
+
cdpilot go https://example.com
|
|
988
|
+
cdpilot click "#login"
|
|
989
|
+
cdpilot fill "#email" test@test.com
|
|
990
|
+
cdpilot record stop [--save login-flow.json]
|
|
991
|
+
cdpilot replay login-flow.json [--var k=v ...] [--delay real|none|<ms>] [--dry-run] [--continue]
|
|
992
|
+
```
|
|
993
|
+
|
|
994
|
+
Commands that run while recording is active are appended to `$CDPILOT_HOME/record/active.json`; secrets are replaced by `{{name}}` placeholders before a step is written to active.json. `CDPILOT_LOG=0` does not turn recording off, and steps run by `replay` are not recorded. Failed steps (`exit != 0`) are dropped at `record stop`. A value becomes a placeholder `{{name}}` cataloged under `vars` if the selector/label is secret-shaped (`#password`, `input[type=password]`, API key), or the value matches a token/bearer pattern or secret URL parameter. Other typed values (emails, search terms, anything the rules do not recognise) are stored verbatim, so review a flow before sharing it; `--save` files are created with mode 0600. In `replay`, `--delay real` reproduces recorded inter-step timing (capped at 10 s per gap), while `--delay none` or a fixed millisecond delay skips waiting. Variables are supplied via `--var k=v` or `CDPILOT_VAR_<NAME>`; missing variables halt replay before any step runs.
|
|
995
|
+
|
|
954
996
|
### Use your own browser (human-in-the-loop)
|
|
955
997
|
|
|
956
998
|
An agent hits a CAPTCHA or a login wall it cannot get past. A person solves it,
|
|
@@ -1082,7 +1124,9 @@ cdpilot launch --no-webmcp # turn it off again (applies at the next start)
|
|
|
1082
1124
|
Chrome reads feature flags only at startup: a browser that is already running
|
|
1083
1125
|
keeps its flags until `cdpilot stop`.
|
|
1084
1126
|
- `tools list` shows the tools of the page and of its same-origin iframes
|
|
1085
|
-
(with the frame URL
|
|
1127
|
+
(with the frame URL; every readable frame is asked for its own tools, so a
|
|
1128
|
+
frame tool missing from the top document's `getTools()` is still listed and
|
|
1129
|
+
runs in its frame), marks form tools and whether the form submits itself
|
|
1086
1130
|
(`toolautosubmit`), and shows `title` and the `readOnlyHint` /
|
|
1087
1131
|
`consequentialHint` / `untrustedContentHint` annotations. Nothing is injected
|
|
1088
1132
|
into the page: the list is the browser's registry at that moment, so it
|
|
@@ -1230,9 +1274,9 @@ print(result.stdout)
|
|
|
1230
1274
|
| v0.6.0 | + captcha solver + cookies-auto (regression) | 15 / 80 | 18.75% |
|
|
1231
1275
|
| **v0.8.0** | **Full — cookies safe-host scoped + per-task wipe (no proxy, no TLS fork)** | **29 / 80** | **36.25%** |
|
|
1232
1276
|
| v0.7.0 (slot) | + named proxy pools | _depends on user proxy_ | — |
|
|
1233
|
-
| v0.8.0 (slot) |
|
|
1277
|
+
| v0.8.0 (slot) | TLS-aware launcher — withdrawn: camoufox / undetected-chrome do not speak CDP (CHANGELOG 0.8.0) | — | — |
|
|
1234
1278
|
|
|
1235
|
-
**What cdpilot does not do:** `cdpilot` is an avoidance engine,
|
|
1279
|
+
**What cdpilot does not do:** `cdpilot` is an avoidance engine first; the solver plugins above (`cdpilot captcha`, bring your own key, off by default) are a fallback, not the strategy. We prioritize structural stealth (JS fingerprinting, behavioral entropy) to prevent challenges from appearing. When a CAPTCHA blocks progress and cannot be avoided, the task fails — that is the honest definition of our success rate. PerimeterX (2/18), GeeTest (0/4) and Akamai (1/6) are known weaknesses; named proxy pools (v0.7) help where the block is IP-based, while TLS-level fingerprinting cannot be fixed from inside a CDP-driven browser and remains open.
|
|
1236
1280
|
|
|
1237
1281
|
## Recommended Configuration
|
|
1238
1282
|
|
|
@@ -1271,7 +1315,7 @@ Future paid offerings:
|
|
|
1271
1315
|
- **No arbitrary file access** — MCP screenshot filenames are sanitized and restricted to the screenshots directory. Path traversal is blocked.
|
|
1272
1316
|
- **Safe CSS selectors** — All selectors passed to `querySelector` are JSON-escaped to prevent injection.
|
|
1273
1317
|
- **No network exposure** — CDP listens on `127.0.0.1` only. Remote connections are not possible by default.
|
|
1274
|
-
- **
|
|
1318
|
+
- **One dependency** — zero npm packages; the Python side needs only `websockets`. A one-package supply chain is small enough to audit.
|
|
1275
1319
|
|
|
1276
1320
|
Found a vulnerability? Please email the maintainer directly instead of opening a public issue.
|
|
1277
1321
|
|
|
@@ -1309,13 +1353,13 @@ The only browser MCP with built-in test assertions. Here's what we've shipped an
|
|
|
1309
1353
|
- [x] **10 built-in test assertions** — assert, assert-url, assert-title, assert-count, assert-value, assert-attr, assert-visible/hidden, wait-for, check (batch), screenshot-diff
|
|
1310
1354
|
- [x] **`test` runner + `trace` viewer** — `cdpilot test [--watch]` runs `*.cdpt.js` files; `cdpilot trace open <run>` opens a time-travel trace viewer for a run
|
|
1311
1355
|
- [x] **Accessibility tree snapshot** (`a11y-snapshot`) — structured text with @ref handles the agent can act on directly, no vision model needed; 1.4–42× smaller than the page's raw HTML on the four pages we measured (2026-09-27). Not always cheaper than a screenshot: link-heavy pages produce more text than a small screenshot costs
|
|
1312
|
-
- [x] **Token-efficient screenshots** — element-level crop
|
|
1356
|
+
- [x] **Token-efficient screenshots** — element-level crop, JPEG quality control, format selection
|
|
1313
1357
|
- [x] **Vision fallback** (`describe`) — a11y + screenshot + text in one call
|
|
1314
1358
|
- [x] **Annotated screenshots** — @N badge overlays on interactive elements
|
|
1315
1359
|
- [x] **Auto-wait** — MutationObserver-based, 5s automatic element waiting
|
|
1316
1360
|
- [x] **`wait-for-text`** — adaptive text-based waiting (subtree + characterData) for streaming AI responses, async toasts, and selector-less synchronization
|
|
1317
1361
|
- [x] **`eval-batch`** — run N JS expressions in 1 CDP roundtrip (5-30x speedup vs sequential `eval`)
|
|
1318
|
-
- [x] **`block`** — request blocking via `Network.setBlockedURLs` with built-in presets (images/fonts/ads/media)
|
|
1362
|
+
- [x] **`block`** — request blocking via `Network.setBlockedURLs` with built-in presets (images/fonts/ads/media); fewer bytes and faster loads on opt-in (measure on your own pages)
|
|
1319
1363
|
- [x] **`dismiss`** — heuristic auto-click for LLM chat sign-up walls (EN+TR pattern library, destructive-action guards)
|
|
1320
1364
|
- [x] **`adaptive`** — auto-escalate to stealth on CAPTCHA-protected hosts, persistent per-host memory ("run fast, climb walls")
|
|
1321
1365
|
- [x] **`cookies save/load`** — export/import cookies as JSON (replay CF/DataDome clearance across runs)
|
package/bin/cdpilot.js
CHANGED
|
@@ -598,6 +598,7 @@ function showHelp() {
|
|
|
598
598
|
|
|
599
599
|
AI AGENT
|
|
600
600
|
mcp Start MCP server (stdin/stdout JSON-RPC)
|
|
601
|
+
--tools core|all|a,b (env CDPILOT_MCP_TOOLS): smaller tool list
|
|
601
602
|
|
|
602
603
|
SESSION LOG (always on, local, redacted)
|
|
603
604
|
log Today's commands for this project: time, exit, command,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cdpilot",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5",
|
|
4
4
|
"mcpName": "io.github.mehmetnadir/cdpilot",
|
|
5
5
|
"description": "Zero-dependency browser automation CLI. Raw CDP, 70+ commands, friction ladder, 3-tier stealth, CAPTCHA + press-and-hold solvers, proxy pools, MCP server. No Puppeteer/Playwright/Selenium.",
|
|
6
6
|
"bin": {
|