{
  "markdown": "# caveman-browse\n\n**A token-efficient alternative to Playwright MCP for coding agents.** One Go\nbinary that attaches to the Chrome you already run, reads the real\naccessibility tree, compresses it, and gives your agent four tools that cost\n**297 tokens of catalog** — versus 3,422 for Playwright MCP (0.0.79) and 4,507\nfor Chrome DevTools MCP (1.7.0), measured live 2026-08-14.\n\n| | caveman-browse | Playwright MCP | Chrome DevTools MCP |\n|---|---|---|---|\n| Tool-definition cost (measured 2026-08-14) | **297 tokens** (4 tools) | 3,422 tokens (24 tools) | 4,507 tokens (29 tools) |\n| Page representation | compressed a11y tree | aria-YAML (lossy) | a11y snapshot |\n| Focused query on a 200-row page | **~98 tokens** | ~15.7k (full ARIA) | full snapshot |\n| Byte-exact recovery of the original tree | **yes (CCR)** | no | no |\n| Runtime | 1 static Go binary + your Chrome | Node + Chromium | Node + Puppeteer + Chromium |\n\nNumbers are `inferred` token counts measured with an offline `o200k_base`\ncounter on pinned fixtures — see [BENCHMARK.md](BENCHMARK.md) for methodology,\nreproduction commands, and the cases where Playwright's bare ARIA text is\n*smaller* (tiny pages; we print those too).\n\n**Full-task head-to-head** (same headless agent, same task, server swapped;\nprovider-reported session tokens; 2026-08-14 pilot, n=1/cell, all arms\npassed): finding one row in a 200-row table cost **150k** total input tokens\nthrough caveman-browse vs 203k (Playwright MCP) / 223k (Chrome DevTools MCP);\ncounting matching rows **168k vs 358k / 223k**. On the action-heavy checkout\ntask caveman-browse *lost* (668k vs 362k / 312k) — its settle-proof loop\nre-snapshots after every action instead of trusting dispatch. Full tables,\ncauses, and claim boundaries: [benchmarks/agentloop/RESULTS.md](benchmarks/agentloop/RESULTS.md),\n[benchmarks/toolcatalog/RESULTS.md](benchmarks/toolcatalog/RESULTS.md),\n[benchmarks/snapshot/RESULTS.md](benchmarks/snapshot/RESULTS.md).\n\n## Install\n\n**Claude Code (plugin — server + usage skill):**\n\n```\n/plugin marketplace add JuliusBrussee/caveman-browse\n/plugin install caveman-browse@caveman-browse\n```\n\n**Claude Code (MCP only):**\n\n```bash\nclaude mcp add caveman-browse -- npx -y caveman-browse\n```\n\n**Cursor / any MCP host** (`.mcp.json` / `mcp.json`):\n\n```json\n{ \"mcpServers\": { \"caveman-browse\": { \"command\": \"npx\", \"args\": [\"-y\", \"caveman-browse\"] } } }\n```\n\n**Gemini CLI:**\n\n```bash\ngemini extensions install https://github.com/JuliusBrussee/caveman-browse\n```\n\nThe npm shim downloads a signature-verified prebuilt binary on first run. No\nNode runtime is involved after launch; no Chromium is bundled — it drives your\ninstalled Chrome with a dedicated automation profile.\n\n## The four tools\n\n- `browser_snapshot(url?, wait?, query?, interactive?)` — compact accessibility\n  tree with `[uid]` action handles plus one accounting line\n  (`caveman before=… after=… ratio=… basis=inferred handle=ccr_…`).\n  `query` keeps the ≤12 best-matching nodes plus ancestors — the\n  token-efficient path on large pages. `interactive: true` keeps only\n  actionable nodes.\n- `browser_act(action, uid, text?, option?)` — `click`, `type`, `select`,\n  `scroll`, `wait`. Returns `settled:false` until a focused re-snapshot proves\n  the app updated; the driver never claims success it hasn't seen.\n- `browser_eval(expression)` — JS escape hatch.\n- `browser_recover(recovery_handle, query?)` — the **byte-exact** original\n  `Accessibility.getFullAXTree` payload behind any snapshot (CCR-backed), or\n  BM25-narrowed sections with a query. Compression here is never a one-way\n  door.\n\n## Direct CLI\n\n```bash\nnpx caveman-browse snapshot http://127.0.0.1:3000\nnpx caveman-browse snapshot http://127.0.0.1:3000 \"save settings\"   # focused\nnpx caveman-browse snapshot -i http://127.0.0.1:3000                # actionable only\nnpx caveman-browse act <uid> click\nnpx caveman-browse recover <handle>\nnpx caveman-browse close\n```\n\nDirect commands share one detached, isolated Chrome until `close`. Navigation\nallows `http(s)`, `about:blank`, and bounded `data:text/html`; `file:`,\n`javascript:`, and privileged schemes fail closed with `cave_snake_code`\nerrors.\n\n## Honesty model\n\n- Every savings figure is **`inferred`** (offline BPE count), never provider\n  usage, never billing, never re-projected to a period.\n- Lossy snapshots are emitted **only** when the byte-exact original is stored\n  for recovery (CCR-or-passthrough).\n- Unknown roles, uids, or CDP responses fail closed — no fabricated handles,\n  no claimed success without settlement proof.\n- Scope: same-origin pages with predictable controls. Cross-origin iframes\n  appear as leaves; OOPIFs, dialogs, downloads, and arbitrary-open-web\n  actionability are out of scope (see the claim boundary in BENCHMARK.md).\n\n## Build from source\n\n```bash\ngo build ./cmd/caveman-browse\nCAVEMAN_BROWSE_CHROME=\"/path/to/Chrome\" go test -tags=integration ./...\n```\n\n## License\n\nSource and binaries ship under [Business Source License 1.1](LICENSE)\n(source-available; first-party self-hosted production permitted; third-party\nhosted/managed/embedded use requires a commercial license). Third-party\nnotices: [NOTICE](NOTICE). Part of the [Caveman](https://github.com/JuliusBrussee/caveman)\nefficiency stack; the a11y compressor and CCR live in the Caveman engine.\n",
  "bytes": 5305,
  "sha": "7a5117ed02fff24720a0f8d8e9cfc70fa06aaaae7ea053f910f7618b97e02288",
  "repo_slug": "juliusbrussee/caveman-browse",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_juliusbrussee_caveman_browse_ffad4d6e/readme"
}