# agent-browser: Rust-native browser automation CLI for AI agents

> agent-browser is a Rust-native CLI that drives Chrome for AI agents via accessibility-tree snapshots and refs, with a daemon, MCP server, and cloud fallbacks.

Published: 2026-07-12
URL: https://daniliants.com/insights/agent-browser-rust-native-browser-automation-cli/
Tags: browser-automation, ai-agents, rust, cli-tools

---

## Summary

agent-browser is a Rust-native CLI (no Node or Playwright runtime needed) that drives Chrome for AI agents through an accessibility-tree snapshot-and-ref workflow: `snapshot` returns refs like `@e1` and `@e2`, and `click` or `fill` then act on those refs. It ships as a single fast binary with a persistent background daemon, an optional MCP server, a local live-viewport dashboard, visual and snapshot diffing, React DevTools introspection, and pluggable cloud browser providers (Browserbase, Browserless, Kernel, AgentCore, Browser Use) as drop-in fallbacks when a local headless browser is not viable or gets bot-detected.

## Key Insight

- **What the Rust rewrite bought (reported figures, not published in the repo)**: a widely shared TikTok breakdown of the rewrite claimed the install shrank from 710 MB to 7 MB, using roughly 18x less memory, with a 1.6x faster cold start and 93% fewer tokens from `snapshot` versus dumping the full DOM. The repo itself publishes none of these numbers, so treat the exact figures as unverified. The direction is consistent with the architecture though: dropping the Node runtime and Playwright's bundled browser binaries leaves a single binary that speaks CDP to Chrome directly, and a compressed accessibility-tree snapshot is inherently cheaper to feed a model than a full DOM.
- **Security is opt-in but CLI-native, not prompt-based**: `--confirm-actions eval,download` and `--action-policy <path>` gate specific action categories at the tool level, so approval logic lives in the daemon rather than in an agent's self-discipline. `--allowed-domains` also blocks sub-resource and WebSocket traffic to non-allowlisted domains, not just top-level navigation.
- **`diff` is a first-class subcommand**, not a manual screenshot-and-eyeball step: `diff snapshot` (structural accessibility-tree diff), `diff screenshot --baseline before.png -t 0.2` (pixel diff with an adjustable color threshold), and `diff url <urlA> <urlB> --screenshot --selector "#main"` (compare two live URLs directly, with no manual before/after capture).
- **`dashboard start`** runs a standalone background server (port 4848, independent of any browser session) with a live JPEG viewport stream, a chronological activity and command feed, and console output. It lets a human watch an agent mid-task instead of inferring state from text snapshots.
- **The default 25s per-action timeout is intentionally shorter than the CLI's 30s IPC read timeout** (`AGENT_BROWSER_DEFAULT_TIMEOUT`, default 25000). Raising it above 30000 does not simply allow slower pages, it causes `EAGAIN` errors because the CLI's own read timeout expires first while the daemon is still working.
- **The CLI serves its own version-matched documentation**: `agent-browser skills get core` prints instructions baked into the installed binary, explicitly so that agent instructions never drift from the installed CLI version between frequent releases. Static cheat sheets go stale by design.
- **Cloud provider swap is a one-flag escalation, not a rewrite**: `-p browserbase|browserless|browseruse|kernel|agentcore` plus an API key env var replaces the local Chrome daemon with a remote session, and every other command stays identical. Useful as a fallback rung between a local headless Chrome and giving up when a site starts detecting the local browser.
- **React DevTools and Web Vitals are built in**: `--enable react-devtools` at launch unlocks `react tree`, `react inspect <fiberId>`, `react renders start/stop`, and `react suspense`, while `vitals` reports LCP, CLS, TTFB, FCP and INP and works on any framework without the flag. That turns the CLI into a lightweight frontend performance and debugging tool, not just a form-filler.
- **Refs are deterministic and reusable across a snapshot's lifetime** but go stale on navigation or DOM mutation. A blocked click reports the exact covering element (for example, covered by a consent-banner div), which is enough to dismiss it and re-snapshot without guessing.