Empty means empty
In 0.20.1, batched assert_value checks accept an empty expected value on both direct CDP and the extension bridge. Non-empty fields still fail the check and stop the batch. Extension 0.7.11 remains current.
open source by Revitt
Give your agent inspectable control of Chrome, Chromium and other Chromium browsers. Read only what matters, act on named controls, and turn proven workflows into repeatable recipes. Use your own model through MCP, HTTP or the CLI.
Read the technical deep dive by Max Revitt →
Latest release v0.20.1 · macOS · Linux
0.20.1 · 2 October 2026
The latest patch fixes empty-value batch assertions. It builds on 0.20’s improvements to targeting, observations and local usage reporting.
In 0.20.1, batched assert_value checks accept an empty expected value on both direct CDP and the extension bridge. Non-empty fields still fail the check and stop the batch. Extension 0.7.11 remains current.
0.20 prioritises active-dialog controls and exposes styled native checkboxes. Trusted clicks verify their targets and refuse inactive tabs until explicitly focused. An action receipt still needs an application postcondition.
Use brw usage to inspect local operation timings, outcomes and payload sizes. HTTP, MCP, CLI and optional-reader records are separate measurement boundaries; their totals are not the agent’s complete context or model bill.
0.20.1 release notes → · How brw’s refs, observations and recipes work →
why brw
brw is the browser-control layer. Your agent chooses what to do; brw reads pages, acts on controls and checks outcomes. Connect your existing assistant or build your own workflow around it.
More than clicks: tabs, groups, forms, files, console, network, responsive testing, downloads, artifacts and human hand-off — exposed as MCP and HTTP.
Find one control, read one section, or return only snapshot changes. Batch related actions and keep large captures in artifacts until you need them.
Pass a reviewed recipe in one call, or search and run a pinned provider recipe. Both paths enforce exact origins, declared risk and postconditions.
Use an extension bridge for your existing signed-in Chromium profile, or a separate brw-owned browser for automation. Browser support and available features depend on the transport.
browser support
Choose the browser you use and the connection that fits the job.
Setup has named options for Chrome, Chromium, Edge, Brave, Vivaldi, Opera and Arc. brw uses the Chromium DevTools Protocol; installation details vary by browser and operating system.
Browser setup guide →The extension bridge uses an existing signed-in profile. Direct CDP runs a separate browser with headless mode and isolated contexts. The transport table below shows the differences.
Compare connections →A WebDriver BiDi prototype has exercised Firefox primitives, but it is not wired into brwd or exposed through brw tools. Safari also has no supported backend.
Firefox prototype findings →the fast loop
The normal path is semantic and compact: inspect only what the next action needs, act by ref, and read the returned delta. Once the flow is stable, move it into a recipe instead of asking a model to rediscover it forever.
Snapshot the actionable frontier or find one control by role, name, text or test id. brw returns stable refs like e17, not brittle selectors.
Click, type, fill, select, drag, upload or commit. The action returns URL, focus and changed elements. A successful click confirms dispatch; pair it with a wait or assertion of the application’s result before treating the task as complete.
Trace or draft the successful mechanics, validate the semantic targets and save a reviewed recipe. Next time, pass it directly or search, pin and run through a provider.
agent surfaces
When a page registers WebMCP tools, or a site publishes an MCP server, an API description, llms.txt or markdown, brw reports it and the agent uses it before driving the DOM. Native document.modelContext works on every transport, including your own signed-in Chrome.
Page tools return available slots; the DOM path reaches the details form for one selected slot. Neither path submits a booking.
6.7–7.7k result characters through page tools, about 55k through the form. Character counts are not billed tokens.
1.17–1.34 s through the page tools, 0.84–1.32 s through the form.
Reaching a bookable slot on revitt.co/book through its five WebMCP tools, against driving the form: three runs each, brw 0.15.2, 25 September 2026. Tool time was similar; the measured saving is in calls and returned text characters. Billed tokens depend on the agent and model. What brw does, and how to make a site work this way →
recipes
A brw recipe is a deterministic browser workflow. Pass the recipe object directly, run a reviewed file from your project, or use a provider with immutable version and digest pins. Every path executes beside the browser with origin, risk and postcondition checks.
Read the recipe architecture →brw_recipe_run { recipe, inputs }No provider or installation required. The result identifies the executed recipe by digest.
brw run --file .brw/recipes/catalog.1.0.0.jsonProvider recipes still use search, then run with id, version and digest. Inline recipes are not saved or indexed automatically.
v0.18 capabilities
Named extraction, read settle control and bounded UCP summaries require v0.18.0 or newer. Check the latest release before using them.
Recipes can select an exact section, a uniquely identified table or allowlisted structured fields. Named outputs return bounded artifact handles with source provenance. Section and table selectors reject ambiguous or incomplete sources. Structured captures check the declared source and required normalized fields; they do not prove that conflicting embedded records agree. Every capture enforces its output budget.
Extraction refuses recipes with runtime secrets. A provenance record identifies the source; it does not establish that the page is truthful.
Extraction contract →Use .brw/recipes/ for reviewed, sanitized files. Validate with brwctl recipe validate --file, then run the chosen file explicitly. There is no automatic directory scan.
Providers are optional. The HTTP provider contract can front Maix, Notion or Postgres through your adapter; those adapters are not bundled.
Repository and registry guidance →After an explicit readiness check, use settle_ms: 0 to skip the default sparse-page wait. Retained snapshot baselines let intermediate observations coexist with delta reads.
Keep model selection in your orchestrator: a smaller worker can execute bounded work while a larger planner reasons. Measure repair rates and total latency before choosing that split.
Measurements and limitations →the full surface
The default MCP catalogue starts with 14 tools and discloses more when the agent asks. Bounded reads and artifact handles keep large results out of the conversation until needed.
The fast everyday surface, built around stable refs and small observations.
Collapse browser work into fewer calls while preserving explicit checks.
Run reviewed workflows from your repository or an optional recipe provider.
The real browser stays visible, organised and under the operator's control.
See what the page, browser and server actually did.
Large or sensitive evidence stays beside the browser until explicitly read.
Need the smallest possible prompt? Use --mcp-tools auto, core or minimal. Every tool remains discoverable and directly callable.
bring your own model
brw itself needs no model service. The agent you already use can call its tools. v0.19.0 also bundles an optional Python reader adapter and worker, registered separately with your MCP client.
Your model reads bounded page content, chooses semantic controls and checks results. Proven work can run as a deterministic recipe without a model choosing each step.
Run the separately registered reader with a local or hosted model endpoint you configure. It returns a bounded answer with its source and trace. The worker still has processing and context costs; no hosted reader service is included.
A classifier such as Jev can rank supplied candidates or select relevant passages. It does not write answers. Use a generative worker, a classifier, both, or neither.
The adapter is packaged, but the model workflow remains exploratory. Passage selection introduced a factual regression in a small canary, so it is not enabled by default. The reader is separate from brw’s core MCP catalogue. Read the results and limitations →
proof + comparison
Smaller observations and deterministic execution reduce avoidable work. These measurements isolate specific costs; they do not establish a whole-task speedup or a ranking against competitors.
Auto mode reveals more tools on demand. Your agent can also use the CLI or HTTP API; schema size is one part of its context budget.
One fixture: an initial compact snapshot plus four compact deltas returned 1,884 characters, versus five full JSON snapshots. This is not a token or task-speed measurement.
Wikipedia searchbox extraction fell from 22.7 to 2.4 ms median. MDN and Hacker News measured 3.25× and 6.2×. These time the in-page extraction only, not a browser job.
One public-page canary: 30,035 source characters became a 236-character answer-and-source packet. The worker still reads evidence; this is not a total billed-token saving.
Measured before release on 1 October 2026. The role-filter optimization ships in v0.19.0. The optional reader is bundled and separately registered; its model workflow remains exploratory. Payload characters are not billed tokens. Machine, fixture and method are in the linked reports. Methods and caveats → · October measurements → · Wider competitor research →
choose the right layer
These tools overlap, but solve different problems. Start with the documented strengths below, then choose for your browser, workflow and hosting needs.
| Tool | Documented strengths | How brw compares |
|---|---|---|
| Playwright MCP ↗ | Accessibility snapshots, persistent or isolated sessions, and Chrome, Firefox, WebKit and Edge options. Also documents a CLI + skills path for coding agents. | Chromium-focused control with a CLI, MCP and HTTP API, compact observations and reviewed recipes. Use Playwright when Firefox or WebKit coverage is a requirement. |
| agent-browser ↗ | An agent-oriented browser CLI with semantic targeting, compact snapshots and snapshot deltas. | Overlapping tools for smaller observations, plus installed-profile bridges, tab leases and recipe execution. Compact refs and deltas are shared ideas, not exclusive features. |
| Stagehand ↗ | Model-assisted browser actions, action discovery and natural-language extraction into a supplied schema. | Deterministic reads for sections, tables, forms and embedded data. The optional reading-worker experiment is not equivalent to arbitrary typed semantic extraction. |
| Browser Use Cloud ↗ | Hosted browser agents and managed browser infrastructure, with a CDP connection for your own code. Browser Use also offers an open-source local agent library. | A browser-control layer you run and connect to your own agent. A provider interface can attach browser infrastructure; brw does not provide a hosted agent service. |
| Chrome DevTools MCP ↗ | Chrome performance traces and insights, network inspection, screenshots and console debugging with source-mapped stack traces. | Browser actions, console and network inspection, screenshots and artifacts. We have not established parity with DevTools performance analysis. |
| Claude in Chrome ↗ | An end-user assistant in Google Chrome, connected to Claude Code, Cowork and the browser side panel. Anthropic documents Chrome-only support. | An open control API for your choice of agent and Chromium browser. You supply the assistant; brw supplies the browser operations and repeatable workflows. |
Primary documentation checked 2 October 2026; each tool name links to its source. This is a feature comparison, not a matched benchmark. No overall speed or success-rate ranking has been established. Product names belong to their respective owners; brw is independent.
install
The installer puts brw under your home directory and hands off to brwctl setup, which starts the bridge daemon in the background, registers brw with your MCP client and installs the agent skill.
start heremacOS and Linux
$ curl -fsSL https://brw.donworks.co.uk/install.sh | shThat command runs a shell script fetched over the network, so read it first. install.sh is served from this site as plain text, with no caching, and is the same file the command executes.
~/Library/Application Support/brw on macOS or ~/.local/share/brw on Linux, and symlinks brw, brwd, brwctl, brwcheck and brw-devtools-mcp into ~/.local/bin. No sudo, nothing outside your home directory.brwctl setup.It reads no input, which is what makes the pipe safe. BRW_VERSION, BRW_INSTALL_DIR, BRW_BIN_DIR, BRW_BASE_URL, BRW_NO_SETUP and BRW_SKIP_ATTESTATION change what it does.
homebrewmacOS and Linux
brew install don-works/tap/brw installs the same tree into the formula prefix, which is then the app directory: brwctl doctor --app-dir "$(brew --prefix brw)". Run brwctl setup afterwards. The tap is bumped by the release workflow, so brew upgrade tracks releases.
macOS pkgAdmin and MDM installs
A universal .pkg that installs machine-wide under /usr/local. Take this route when you are deploying to someone else's machine, or when policy requires a package your MDM can ship. It needs administrator rights; the one-line installer does not.
linux.deb and .rpm
brw_<version>_linux_amd64.deb and the arm64 and .rpm equivalents, for systems that expect packages to come from the package manager. Installs to /usr/share/brw/.
windowspackages paused
Current releases do not publish Windows installers. Historical MSI files are not the current build; use macOS or Linux for the latest packaged release.
setupWhat brwctl setup does
Inside the pipe it is non-interactive: it prints the plan, performs it and exits. On a terminal it asks first. brwctl setup --dry-run lists every action without performing one. Nothing it writes is outside your home directory and no step uses sudo.
~/Library/Application Support/brw/browser-profiles.json on macOS and ~/.config/brw/browser-profiles.json on Linux, merging into an existing one rather than replacing it.127.0.0.1:17310 for control and 127.0.0.1:17311 for the bridge. If a service already drives that profile or holds those ports, it reports what it found and writes nothing.claude mcp add. --mcp-client codex or both covers Codex; --mcp-client none prints the mcpServers block for you to paste.~/.claude/skills/brw, ~/.agents/skills/brw and ~/.codex/skills/brw.thenConnect a browser
Loading the extension is the one step brwctl setup cannot do for you. The bridge drives a browser you are already signed into, so that browser needs the brw extension. One permanent extension id, trusted by the daemon with no configuration:
amocjcgddnoakjijfggdpnefdnboilpe
/etc/chromium/policies/managed/. macOS uses a configuration profile, Windows a .reg file or the matching GPO.chrome://extensions → Developer mode → Load unpacked → the extension/ folder. A Chrome Web Store build is being prepared for review. No listing exists yet, so load-unpacked is the Chrome path until one does.# setup prints this line with your workspace filled in
$ brwctl doctor --workspace brw-chrome-profile
# before the extension is loaded and the browser restarted,
# doctor reports it missing and exits non-zero. That is expected.# then check it end to end
$ curl -s 127.0.0.1:17310/api/browser/open \
-H 'content-type: application/json' \
-d '{"url":"https://example.com"}'
# a visible tab opened; read its controls
$ curl -s 127.0.0.1:17310/api/page/snapshot | jq# build from source instead
$ git clone https://github.com/Don-Works/brw.git
$ cd brw
$ task build
$ ./bin/brwd --mcp --http offRemote browsers, multi-profile policies and SSH-first setups are in the install docs.
transports
The extension bridge drives the browser you already use. Direct CDP drives a browser brw launches and owns. They differ in what they can do. The table compares these two common setups. The one-line installer sets up the bridge; add the other lane with brwctl setup --transport direct-cdp, and run both side by side as separate namespaces.
Chrome’s manual remote-debugging opt-in, an existing local CDP endpoint, and off-host browser providers are also supported. Download, file and session capabilities differ from a browser brw starts itself. See the full connection guide →
| Capability | Extension bridge | Direct CDP |
|---|---|---|
| The browser it drives | The Chrome, Chromium, Edge, Brave, Vivaldi, Opera or Arc you already have open and signed in. | A separate Chromium browser that brw launches, on a profile brw owns. |
| Where the logins come from | Sessions, cookies and passkeys that are already in that profile. | Sign in once with brwd --login; the profile keeps the session for later headless runs. |
| Chrome tab groups | Yes — chrome.tabGroups keeps the agent's tabs in one labelled group. | No. chrome.tabGroups is an extension API with no DevTools Protocol equivalent. |
| Incognito contexts | No. | Yes — brw_open_incognito opens an isolated context, brw_close_context disposes it. |
| Cookie tools | No. The extension refuses every cookie CDP method, HttpOnly included, to protect the signed-in profile. | Yes — brw_cookies lists, sets and deletes, HttpOnly cookies included. |
| Downloads | Files land in the browser's own download folder. Capturing the bytes as an artifact can need macOS Files & Folders consent; the metadata-only event does not. | Deterministic — files are staged in brw's private cache, no Downloads access needed. |
| Headless | No. --headless with --bridge is refused rather than ignored. | Yes, once the profile has been signed into. |
| How it starts | brwd --bridge, plus the extension loaded in that browser. | brwd --mcp --http off. No extension involved. |
brw_identity reports which transport a namespace is on, so an agent can check before it assumes a capability. Read the auth model.
trust
brw is young and small, and it asks for control of a browser you are signed into. Here is what is verifiable about a release today, and what is not yet.
Daemon, CLI and extension are in one public repository under one licence.
A checksum proves a file matches the release. An attestation proves which workflow and which commit built it.
Current macOS binaries are ad-hoc signed, which identifies no developer. Installers are unsigned and not notarised.
The repository’s pre-push hook runs task check. The release workflow builds, attests and publishes the tagged commit.
The daemon trusts that id with no configuration.
These refusals are implemented in the extension's service worker.
# the file matches the release
$ shasum -a 256 -c SHA256SUMS.txt
# the release came from this repository's workflow
$ gh attestation verify brw_<version>_macos_universal.pkg \
--repo Don-Works/brwBoth checks run against artifacts from the releases page. The workflow that produces and attests them is in the repository.
safety
brw uses a normal visible browser and a persistent user profile. It does not add stealth code, CAPTCHA bypass, MFA bypass, fraud-check bypass or consent bypass. The installed-profile extension refuses HttpOnly cookie and bulk storage access; explicit cookie tools exist only for dedicated direct-CDP profiles, and the extension privacy policy lists every refusal. Browser-control HTTP binds to loopback by default, recipes declare their risk, and mutating requests are guarded. For remote use, prefer stdio MCP over SSH so the profile stays on the machine that owns it. Released under AGPL-3.0 — free to use, change and build on, with improvements shared back. If that doesn't fit your business, talk to Revitt about a commercial licence.