Claude in Chrome only works in Chrome, and I use Firefox. So I built Firefox Agent Bridge, which gives Claude Code the same browser tools in Firefox. Then I spent two days and about 1,200 eval runs benchmarking it against Claude in Chrome and fixing whatever the traces showed, until it was faster and cheaper on all 16 tasks.
14.9s vs 25.5s
56k vs 119k
$0.058 vs $0.080
and cheaper
What it does
- Same tools as Claude in Chrome (
navigate,computer,find,read_pageand the rest), for Claude Code, Codex or the Claude desktop app. - The agent gets its own tab group and works in the background. It never takes focus or moves your cursor.
- A sidebar chat that runs Claude Code on your existing plan, plus a few things Chrome doesn’t have: ⌥-click an element to ask about it, teach a task by doing it once, start a task from the address bar or your phone.
- Password and card fields are masked before a screenshot or page read leaves the browser.
All 14 tools and what each does
The first eleven have the same names and arguments as Claude in Chrome. batch and replay_steps are the bridge’s own, and devtools is off unless you turn it on.
| Tool | What it does |
|---|---|
tabs_context_mcp | Lists the tabs in the session’s tab group |
tabs_create_mcp | Opens a background tab in the group |
tabs_close_mcp | Closes one of the session’s tabs |
navigate | Goes to a URL, back or forward, and returns once the page is parsed |
computer | Screenshot, zoom, click, hover, drag, type, key and scroll, by coordinate or element ref |
read_page | A compact text tree of the page’s roles and names, across every frame |
find | Keyword search over element names, roles and labels. Returns the best 8 matches |
get_page_text | The page’s readable text |
form_input | Sets one field, or several in one call |
javascript_tool | Runs a script in the page. The page’s CSP doesn’t block it |
file_upload | Fills a file input without opening the native picker |
batch | Runs up to 20 actions in one call and stops at the first that fails |
replay_steps | Replays a task you taught it, without the model, until a step doesn’t match |
devtools | Reads the console and network requests |
Agent Bridge vs the alternatives
Firefox already has a few ways to let software drive it, and Chrome has Claude in Chrome. None of them gave me an agent that works in my own logged-in Firefox while I keep using it.
- Smart Window, Mozilla’s AI mode, reads the tabs you share but can’t click or fill a form. It runs on Mozilla’s models, not the Claude plan I already pay for.
- Mozilla’s DevTools MCP is a debugging tool. It warns against pointing it at your regular profile, and it has nothing to show what the agent is doing or to stop it.
- Playwright MCP and WebDriver BiDi start a separate automation browser, so none of my logins come along.
- Claude in Chrome comes closest, but it only runs in Chrome and only with Claude. It is also slower and reads about twice the tokens, which the benchmark below measures.
That gap is why the bridge exists. Row by row:
| Firefox Agent Bridge | Claude in Chrome | Firefox Smart Window | Mozilla DevTools MCP | Playwright MCP | WebDriver BiDi | |
|---|---|---|---|---|---|---|
| Reach | ||||||
| Works in Firefox | ✓yes | ✕no | ✓yes | ✓yes | partlyits own Firefox build | ✓yes |
| Uses your real profile and logins | ✓yes | ✓yes | ✓yes | partlywarns against it | ✕noseparate browser | ✕noseparate session |
| Clicks, types and fills forms | ✓yes | ✓yes | ✕noplanned | ✓yes | ✓yes | ✓yes |
| Works in background tabs, never takes focus | ✓yes | partlywindow must be visible | –doesn't apply | partlyheadless | partlyheadless | partlyhidden tabs stop rendering |
| Sees and acts inside cross-origin iframes | ✓yes | partlyneeded workarounds | ✕no | partly | ✓yes | partlyclient picks the frame |
| Start a task from anywhere | ✓yesterminal, sidebar, address bar, phone | partlyside panel | partlyin the window | ✕noterminal | ✕noterminal | –doesn't apply |
| The agent | ||||||
| Bring your own subscription | ✓yesClaude or ChatGPT | partlyClaude only | ✕nofree, Mozilla's models | ✓yes | ✓yes | –doesn't apply |
| Choice of agent | ✓yesClaude Code, Codex, Claude desktop | ✕noClaude only | partlyMozilla's list | ✓yes | ✓yes | –doesn't apply |
| Runs locally, with your files and shell | ✓yes | partlythrough Claude Code | ✕no | ✓yes | ✓yes | –doesn't apply |
| Memory and skills carry across sessions | ✓yes | partly | partly | ✓yes | ✓yes | –doesn't apply |
| Same tools as Claude in Chrome | ✓yes | ✓yes | ✕no | ✕no | ✕no | ✕no |
| Measured time and input tokens per task | 14.9s, 56k | 25.5s, 119k | –doesn't apply | not measured | not measured | not measured |
| Safety and traceability | ||||||
| Passwords and cards masked before they leave the browser | ✓yes | ✕no | ✕no | ✕no | ✕no | ✕no |
| Shows which agent is driving which tabs | ✓yes | ✓yes | –doesn't apply | ✕no | ✕no | partlyone robot icon |
| Stop all, or disconnect one client | ✓yes | partlystop only | –doesn't apply | ✕no | ✕no | ✕no |
| Activity log of every call | ✓yes | ✕no | –doesn't apply | ✕no | ✕no | ✕no |
| Open source | ✓yes | ✕no | ✓yes | ✓yes | ✓yes | ✓yes |
| Past parity | ||||||
| Teach a task by doing it, replay without the model | ✓yes | partlyshortcuts | ✕no | ✕no | ✕no | ✕no |
| Point at an element to ask about it | ✓yes | ✕no | ✕no | ✕no | ✕no | ✕no |
| Live agent cam, save as GIF | ✓yes | partlyGIF tool | ✕no | ✕no | ✕no | ✕no |
| What it costs | ||||||
| Installs in a regular browser, signed | ✕noDeveloper Edition only | ✓yes | ✓yes | ✓yes | ✓yes | ✓yes |
| Built on stable, supported APIs | ✕no | ✓yes | ✓yes | ✓yes | ✓yes | ✓yes |
| Asks before acting on each site | partlyper action, opt-in | ✓yes | –doesn't apply | ✕no | ✕no | ✕no |
✓ yes partly ✕ no – doesn't apply
The last three rows are what the rest cost me.
Getting real clicks out of Firefox
Chrome extensions can send real input through chrome.debugger. Firefox extensions can’t, and a lot of sites ignore the untrusted events a normal extension can fire. So the bridge ships a WebExtension Experiment, privileged code that Developer Edition will load. It puts an actor in every frame and sends input from privileged code, so pages see real, trusted clicks and keystrokes.
One click, from the model to the page. Click a box to see what it does.
The catch is that it depends on internal APIs. I wrote up what WebDriver BiDi would need to do the same thing on stable ground.
The benchmark
16 tasks, 3 runs each per browser, same model (Sonnet 5.5) and prompt. Articles, lists, five-page comparisons, Wikipedia link chains, search, infinite scroll, forms, a date picker, a virtualized table and a dropdown inside an embedded frame.
| Median per task | Firefox, first run | Firefox, now | Claude in Chrome |
|---|---|---|---|
| Passed | 48/48 | 48/48 | 47/48 |
| Time | 19.1s | 14.9s | 25.5s |
| Input tokens | 60k | 56k | 119k |
| Cost | $0.062 | $0.058 | $0.080 |
| Per click | 697ms | 122ms | 161ms |
Median time per task, log scale. The frame dropdown went from Firefox's slowest task to the middle of the pack. Hover or tap a task for what it asks and its numbers.
Why it’s faster and cheaper
Three reasons, and the traces can separate them.
Tool calls return sooner. The model waits on every call, and Firefox’s come back faster:
| Mean per call | Firefox | Claude in Chrome |
|---|---|---|
| List the session’s tabs | 45ms | 1.9s |
A computer action (click, type, scroll) | 84ms | 1.4s |
| Run JavaScript in the page | 1.6s | 3.7s |
Every turn starts smaller. Claude in Chrome offers the model 22 tools and the bridge offers 13, and every tool’s definition is sent again on every turn. On the three article tasks both browsers made the same 4 calls over the same 5 turns and got the same text back, yet Chrome read about 5,500 more tokens on each turn. Across all 16 tasks a turn costs 8k input tokens in Firefox and 14.5k in Chrome. I think the longer tool list is most of that gap, though I can’t see Chrome’s definitions to count them. It’s also why devtools is opt-in here.
Fewer steps. This one wasn’t true at first. Where Firefox was behind in the first run, the traces showed why:
| Where Firefox was behind | Fix | Result |
|---|---|---|
| Five package pages or a long form took twice the calls | A batch tool and multi-field form_input | PyPI compare: 13 calls → 5 |
| Couldn’t see into MDN’s example, a cross-origin frame in a shadow root | find and read_page walk every child frame | 71 calls → 9 |
| Every click waited 500ms in case it opened a tab | Wait 100ms unless it targets a new tab, and skip the cursor animation in background tabs | 697ms → 122ms |
navigate waited for the load event | Return once the page is parsed | 1.9s → 0.6s |
Cost follows the tokens, but by less: 28% against 2.1x, because most of those extra tokens are cached reads, which are cheap.
Chrome’s find asks a model to match elements. It failed on 5 of its 15 calls here, and its tokens aren’t in Chrome’s counts, so Chrome’s real cost is a little higher than shown.
Ideas I tested and dropped
Each idea ran against the same tasks without it, before it got built or kept.
| Idea | What happened | Kept? |
|---|---|---|
| One sub-agent per page | 18–41% faster on five-page comparisons, at 2.75x the cost | For 4+ pages |
| Reader view before reading | Lost paragraphs on 6 of 22 sites (BBC kept a third) | No |
| Read the site’s JSON | Confidently answered 62. The answer was 41. | No |
| Hint Sonnet to batch its steps | Shown on 68 results; Sonnet didn’t batch any more | No |
A screenshot alias tool | Fake screenshot calls went to 0, other made-up tools went from 3 to 17 | No |
| Cap page text length | Slower, since long articles need the whole page | No |
Return from navigate once parsed | 0.6s instead of 1.9s per page, no passes lost | Yes |
The tool-wording changes did the least. How Sonnet behaves barely moved with anything I put in a description.
Which Claude model should drive it
Round 1 used six long tasks. Sonnet 5.5, Opus 5.5 and Fable 5.1 passed all 162 runs at every effort level, so it only told me about cost. Haiku 4.5 passed 10 of 18, and every failure ended with it saying it had succeeded.
Round 2 needed harder tasks. The first two drafts were still too easy because Sonnet just wrote JavaScript around them, so five of the six ban it. The tasks: count 582 table rows, read 167 star ratings shown as icons, solve an Evil sudoku, draw a 13-shape tldraw grid, work through UI Testing Playground’s tricky widgets, and apply the 2026 World Cup tie-break rules.
| Mean score, hard tasks | Low | Medium | High |
|---|---|---|---|
| Sonnet 5.5 | 0.935 | 0.930 | 0.994 |
| Opus 5.5 | 0.981 | 0.989 | 0.991 |
| Fable 5.1 | 0.991 | 1.000 | 1.000 |
- Sonnet high matched Opus at every effort level for about 0.7x the cost, so it’s now the sidebar default.
- Fable was the most reliable, 53 of 54, at 3–4x Sonnet’s cost.
- Effort mostly helps with rules. Over 216 more Sonnet runs, high passed 90% against low’s 80%, and nearly all of that gap is the World Cup task.
Sonnet 5.5 passes out of 18 per task: 6 runs on the plain tools, 12 with one small tool tweak on, at both effort levels. Hover or tap a task for what it asks.
Still open
- The Space fix has tests but I haven’t tried it by hand yet.
- Sonnet still makes up a
left_clickcall now and then.
To try it you need Firefox Developer Edition or Nightly, and a separate profile, because the install turns signature checks off for it. scripts/install.sh does the rest. It depends on internal APIs, so a Firefox update can break it.
Code, eval harness and every result file are in the repo, with the full tables in the eval README.