browser-control: A Rust CLI That Gives Coding Agents Hands and Eyes
A tiny, fast Rust CLI that drives a real browser over the Chrome DevTools Protocol — built for coding agents.
At a glance
- What is it?
- browser-control is a small Rust CLI that drives a real Chrome browser over the Chrome DevTools Protocol, aimed at coding agents that need to interact with web pages. It offers stable element refs, raw CDP access, and a shell-native design, but its young age and limited documentation demand careful verification.
- Who is it for?
- Adopt browser-control if you are a coding agent or a developer building one that needs a lightweight, shell-callable way to control a real browser without an SDK or MCP. Its stable refs and raw CDP escape hatch fit LLM-driven workflows.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 20 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The Problem: Giving Agents Browser Control Without a Framework
Coding agents often need to interact with web pages, but existing tools tend to be heavy: they require an SDK, a long-running server, or an MCP integration. browser-control takes a different route. It is a single Rust binary that exposes a browser as a set of shell commands. Each command prints compact text or JSON, so an agent that can run a shell command can drive Chrome. The README states it clearly: no LLM, no MCP requirement, no framework. The intended user is a coding agent, or a developer building one, who wants a small, debuggable pipe between the agent and a real browser. This is not a tool for human testers who want a visual UI; it is for automation where every action is a subprocess call.
How It Works: CDP, Stable Refs, and a Hidden Daemon
The architecture is visible from the command list. browser-control launches a Chrome instance and connects over the Chrome DevTools Protocol, either by starting its own browser or by attaching to an existing CDP endpoint. The core mechanism is the snapshot command, which returns numbered refs like @e1 for every actionable element. These refs are stable handles that you can pass directly to click or fill. That design is meant for LLM workflows, where hand-written CSS selectors are brittle. The tool also keeps a hidden daemon running, which maintains in-memory rings for events, network requests, and console messages. This lets an agent query recent activity with commands like events or network. When a command fails, the tool writes a compact trace under .browser-control/traces/, which the agent can read to diagnose itself. The README emphasizes this self-observing property, and it is a genuine differentiator: most automation tools do not give you a built-in failure trace.
Getting Started: Install, Launch, and Drive
Installation is straightforward if you have Rust. The crate is named browser-control-cli, but the installed binary is browser-control. Run cargo install browser-control-cli, then check the version. Alternatively, download a prebuilt binary from the GitHub releases page, which requires no Rust toolchain. For a source build, clone the repository, run rustup toolchain install to get the pinned version, then cargo build --locked --release. After installation, the quick start shows: browser-control init creates a .browser-control workspace, launch starts Chrome and connects, and doctor verifies the endpoint, browser, pid, daemon, and workspace. You can also point at an existing Chrome by setting the BROWSER_CONTROL_CDP_URL or BROWSER_CONTROL_CDP_WS environment variable, with short aliases BU_CDP_URL and BU_CDP_WS. Then you run snapshot to get refs, click @e1, fill a field, or eval JavaScript. The eval command IIFE-wraps a top-level return, so you can write return statements directly.
Commands and Selector Styles: Three Ways to Act
Every action accepts three target styles. The default is the ref style, like click @e3, which comes from snapshot or observe. The second is CSS selectors, like click '#submit' --wait 5, where the --wait flag polls for the element to appear for up to five seconds. The third is coordinates, like click 100,200, which is useful for canvases or maps where there is no stable DOM node. The command set covers observation and action. Observation commands include status, doctor, page-info, snapshot, text, eval, events, network, and console. Action commands include open, click, fill, type, press, and scroll. The press command supports key combos like ctrl+a and cmd+shift+t. There is also a raw CDP command: cdp Runtime.evaluate with a JSON payload. This escape hatch means you can do anything CDP supports, even if the helper commands do not cover it. The README claims you never hit a wall and have to switch tools, which is plausible given the raw access.
Cloud Provider Support: Same Commands, Remote Browser
A notable feature is provider-agnostic cloud support. The README lists Browser Use, Steel, Hyperbrowser, and Browserbase as cloud providers you can drive with the same command set. The mechanism is not detailed in the material, but it likely relies on setting the CDP URL or WebSocket environment variable to point at a remote session. The badge in the README shows these providers, and the text says you can drive a local Chrome or a remote session with the same commands. This is attractive for agents that need to run in isolated environments or at scale. However, the README does not explain how authentication or session management works for each provider. You would need to check the project's source or documentation for specifics. The abstraction is thin: it just speaks CDP, so any provider that exposes a CDP endpoint should work, but the setup steps are left to the user.
Limitations and Failure Modes: What the README Does Not Tell You
The project is at version 0.1.1, with only two releases, so it is early-stage. The README is the only documentation available, and it is truncated. That means you cannot learn about error handling, concurrency, or edge cases from the material. One clear limitation is that the tool assumes Chrome or Chromium is available. If you do not have a browser installed, launch will fail, and doctor is there to report what it found, but you still need to install Chrome yourself. Another potential failure mode is the reliance on stable refs. The snapshot command provides refs, but if the page changes dynamically, those refs may become stale. The README does not explain how refs are invalidated or updated. Also, the tool is built for coding agents that run shell commands. If your agent cannot execute arbitrary binaries or if you need a library API, this is the wrong tool. There is no SDK, so you cannot embed browser-control in a Rust program directly; you must call it as a subprocess.
Alternatives: How It Compares to Playwright and Other CDP Wrappers
The most obvious alternative is Playwright, a full-featured browser automation library with bindings in multiple languages. Playwright has a high-level API, handles waits and assertions, and supports multiple browsers including Firefox and WebKit. browser-control is different in approach: it is not a library but a CLI, and it focuses on a narrow set of operations that an agent can call via shell. Playwright requires you to write code in a programming language, which is heavier for an LLM that just needs to click a button. Another alternative is using raw CDP tools like Chrome's remote debugging interface directly, but that requires you to manage WebSocket connections and JSON messages yourself. browser-control abstracts that away with compact commands. The key difference is that browser-control is designed for composability in a shell pipeline, whereas Playwright is a programmatic framework. If you need fine-grained control over multiple tabs or complex assertions, Playwright is more mature. If you want a quick, stateless command to drive a browser from an agent, browser-control fits better.
Maintenance, Reproducibility, and License
The project is MIT licensed, which is permissive and allows commercial use without restriction. The repository has a pinned toolchain in rust-toolchain.toml and a committed Cargo.lock. The README emphasizes reproducible builds: direct dependencies are exact-version constraints, and transitive dependencies are frozen. You are advised to always build with --locked, and there is a scripts/verify.sh for one-command local verification. This is a strong point for an early-stage project, because it reduces the risk of dependency drift. However, the last push was in August 2026, and the latest release is from June 2026, so the project may be under active development or could be stalled. The maintenance cost is low because it is a single static binary, but you need to rebuild if you want updates. There is no mention of a changelog or migration guide, so upgrading from v0.1.0 to v0.1.1 may involve breaking changes. You should check the release notes for each version before upgrading.
Editorial conclusion
Adopt browser-control if you are a coding agent or a developer building one that needs a lightweight, shell-callable way to control a real browser without an SDK or MCP. Its stable refs and raw CDP escape hatch fit LLM-driven workflows. Do not use it if you require a mature project with extensive documentation or if you need full browser automation features like complex multi-tab orchestration, since the README shows only basic commands. Before adopting, verify that the pinned Rust toolchain and your Chrome version are compatible, and test that the daemon and trace features work in your environment. The project is at version 0.1.1, so expect breaking changes; check the changelog and run the provided scripts/verify.sh to confirm reproducibility.
Community notes