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 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 dependency** — No Puppeteer, no Playwright, no Selenium. Pure CDP over HTTP
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. No data leaves your machine
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] # Capture console logs
302
- cdpilot network [url] # Monitor network requests
303
- cdpilot debug [url] # Full diagnostic (console+network+perf+shot)
304
- cdpilot perf # Performance metrics
305
- cdpilot eval <js> # Execute JavaScript
306
- cdpilot eval-batch <json> # Run N JS expressions in 1 roundtrip (5-30x faster)
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 and Windows, `ss` on Linux), and a `watch` daemon or a Playwright session keeps
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), marks form tools and whether the form submits itself
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) | + TLS-aware launcher (camoufox/undetected-chrome) | _depends on browser choice_ | — |
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, not a CAPTCHA solver. We prioritize structural stealth (JS fingerprinting, behavioral entropy) to prevent challenges from appearing. When a CAPTCHA blocks progress and cannot be bypassed, 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; v0.7+ (residential proxy) and v0.8+ (TLS fingerprint correction via camoufox) target these directly.
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
- - **No dependencies** — Zero npm/Python runtime dependencies means zero supply-chain attack surface.
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 (13x smaller), JPEG quality control, format selection
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), 3-10x faster page loads on opt-in
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.4",
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": {