browser-control
browser-control is a Rust CLI that manages browser processes and exposes them
over CDP (Chromium) or WebDriver BiDi (Firefox) for agent-driven development.
It keeps a small persistent registry of the browsers it has started so multiple
agents, shells, or editor sessions can coordinate on the same browser. An
optional MCP server is available as a subcommand.
Install
Homebrew (recommended) — tap this repo, then install:
brew tap rickardp/browser-control https://github.com/rickardp/browser-control.git
brew install browser-control
The formula is rendered into Formula/browser-control.rb by CI on every release, so the tap URL above is all you need.
From crates.io:
cargo install browser-control
Prebuilt binaries for macOS (x86_64/aarch64), Linux (x86_64/aarch64) and Windows (x86_64) are attached to every GitHub Release.
On Windows, install via the PowerShell one-liner:
irm https://raw.githubusercontent.com/rickardp/browser-control/main/scripts/install.ps1 | iex
It downloads the latest release zip, extracts browser-control.exe to %USERPROFILE%\.browser-control\bin, and prepends that directory to your user PATH. The script is idempotent — re-running it upgrades to the latest release, and is a no-op when the requested version is already installed. To pin a version, force a reinstall, or skip the PATH update:
$script = irm https://raw.githubusercontent.com/rickardp/browser-control/main/scripts/install.ps1
& ([scriptblock]::Create($script)) -Version 0.3.5
& ([scriptblock]::Create($script)) -Force
& ([scriptblock]::Create($script)) -NoPathUpdate
To uninstall:
irm https://raw.githubusercontent.com/rickardp/browser-control/main/scripts/uninstall.ps1 | iex
By default the user data directory (%APPDATA%\browser-control, containing the browser registry and config) is preserved. Pass -Purge to remove it as well:
$script = irm https://raw.githubusercontent.com/rickardp/browser-control/main/scripts/uninstall.ps1
& ([scriptblock]::Create($script)) -Purge
Requires Rust 1.80 or newer when building from source. A Node runtime
(bun preferred, node+npm accepted) is required only if you invoke the
Playwright-only MCP tools (browser_click, browser_snapshot, etc.); the
sidecar is spawned lazily on first use.
Usage
The CLI groups commands into lifecycle, config, browser-wide session ops,
page-context ops, and named tabs. Most commands accept --json for
machine-readable output.
Browser selection
Page-context commands (eval, fetch, storage, …) and browser-wide
commands (targets, cookies, wait, wait-for-cookie) accept a
--browser / -b flag (with $BROWSER_CONTROL env fallback) to select
the target browser:
browser-control eval -b firefox 'document.title'
BROWSER_CONTROL=chrome browser-control cookies --format netscape
browser-control fetch --browser brave https://example.com/api/me
Resolution order: --browser flag → $BROWSER_CONTROL env →
browser-control set default <value> → error.
Page-context commands also accept a tab suffix: --browser brave/cart
routes to a named tab. Browser-wide commands reject tab suffixes with an
error.
list-installed
Detect every supported browser installed on this machine.
browser-control list-installed
browser-control list-installed --json
Supported kinds: chrome, edge, chromium, brave (CDP), and firefox
(BiDi).
list-running
List the browsers currently registered and alive. Stale entries (dead PIDs or
unreachable endpoints) are pruned lazily before printing.
browser-control list-running
Columns: NAME, KIND, PID, ENGINE, ENDPOINT, PROFILE, STARTED.
--json adds engine-specific endpoint details for tooling integration:
cdp_port and cdp_ws_url for CDP browsers, bidi_ws_url for Firefox.
Stale rows are re-probed before the WS URLs are printed; fields are omitted
when the probe fails.
start [BROWSER]
Start a browser and register it. Idempotent by kind: if a browser of the
requested kind is already alive, it is reused.
browser-control start # first available Chromium-based
browser-control start firefox
browser-control start chrome --headless --json
BROWSER may be a kind (chrome, edge, chromium, brave, firefox) or a
friendly instance name printed by a previous start (e.g. firefox-pikachu).
When omitted, the first available Chromium-based browser is used.
start blocks until the browser's debugging endpoint is reachable (up to
--wait-timeout seconds, default 30) so the next command in a chain can
attach immediately. Pass --no-wait to return as soon as the process is
spawned.