Tandem
A hardened, multi-agent fork of opencode-browser by Benjamin Shafii.
Browser automation for AI agents via Chrome extension + Native Messaging. Works with Claude Code, OpenCode, Cursor, Windsurf, VS Code Copilot, Gemini CLI, Codex, and any MCP-compatible agent.
Runs inside your existing Chrome session — shares your logins, cookies, and bookmarks. No separate profiles, no re-authentication.
Agent tabs open in a dedicated Tandem window (cyan tab group) so your browsing is never interrupted.
Why not Playwright / DevTools?
Chrome 136+ blocks --remote-debugging-port on your default profile. DevTools-based tools trigger a security prompt every time. This project uses Chrome's Native Messaging API — the same approach Anthropic uses for Claude in Chrome — so automation works silently against your live session.
Installation
npx @felixisaac/tandem install
The installer:
- Copies the extension to
~/.tandem/extension/ - Opens Chrome so you can load the unpacked extension
- Registers the native messaging host (registry on Windows,
NativeMessagingHostson macOS/Linux) - Optionally updates your agent config file
Agent Setup
After installing, the server lives at ~/.tandem/server.js. Configure your agent:
Claude Code
claude mcp add -s user browser -- node ~/.tandem/server.js
Adds the server globally — available in every Claude Code session.
OpenCode
Add to opencode.json (project) or ~/.config/opencode/opencode.json (global):
{
"mcp": {
"browser": {
"type": "local",
"command": ["node", "~/.tandem/server.js"],
"enabled": true
}
}
}
Cursor
Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json (project):
{
"mcpServers": {
"browser": {
"command": "node",
"args": ["~/.tandem/server.js"]
}
}
}
Restart Cursor after saving.
Windsurf
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"browser": {
"command": "node",
"args": ["~/.tandem/server.js"]
}
}
}
VS Code + GitHub Copilot
Add to .vscode/mcp.json (workspace) or open MCP: Open User Configuration from the command palette:
{
"servers": {
"browser": {
"type": "stdio",
"command": "node",
"args": ["~/.tandem/server.js"]
}
}
}
Reload the window after saving (Ctrl+Shift+P → Developer: Reload Window).
Gemini CLI
Add to ~/.gemini/settings.json:
{
"mcpServers": {
"browser": {
"command": "node",
"args": ["~/.tandem/server.js"]
}
}
}
Codex CLI (OpenAI)
Add to ~/.codex/config.toml:
[mcp_servers.browser]
command = "node"
args = ["~/.tandem/server.js"]
Available Tools
| Tool | Description |
|---|---|
browser_snapshot | Start here. Accessibility tree with CSS selectors — low token cost (200–1500 tokens) |
browser_screenshot | Visual capture — use only when layout matters (500–3000 tokens) |
browser_navigate | Navigate to a URL |
browser_click | Click an element by CSS selector |
browser_type | Type text into an input |
browser_keyboard | Send key events (Enter, Escape, Tab, ctrl+a, …) |
browser_wait_for_selector | Wait for element to appear — essential for SPAs |
browser_scroll | Scroll page or element into view |
browser_wait | Wait for a fixed duration (capped at 30s) |
browser_execute | Run JavaScript via chrome.debugger — works on all pages including CSP-strict sites |
browser_status | Show connection status + current tab claims |
browser_list_claims | List per-session tab ownership claims |
browser_claim_tab | Claim a specific tab for this session |
browser_release_tab | Release a claimed tab |
browser_open_tab | Open and claim a fresh agent tab for this session |
browser_get_tabs | List all open tabs |
browser_new_tab | Open a new tab in the agent window |
browser_close_tab | Close a tab |
browser_switch_tab | Focus a tab (use to hand off to user) |
browser_new_window | Open a new browser window |
Per-tab Ownership
Tandem enforces per-session tab claims so multiple agents can share one Chrome session without stepping on each other.
- If you omit
tabId, Tandem auto-creates (once) and reuses a default agent tab per MCP client session. - If you pass an explicit
tabId, Tandem will reject the call if that tab is claimed by another session. - Use
browser_open_tabto open a tab that is automatically claimed for your session. - Claims expire after inactivity (
TANDEM_CLAIM_TTL_MS, default 5 minutes). Debug withbrowser_status/browser_list_claims.
Agent Instructions
See AGENTS.md for full behavioral guidance:
- Snapshot-first workflow (token efficiency)
- Waiting for dynamic elements before clicking
- Hand-off pattern for login walls / CAPTCHAs
- Error recovery table
- Security rules and prompt injection protection
Claude Code users: see CLAUDE.md.
Architecture
src/server.js— MCP server; exposes tools, enforces rate limits, routes to hostsrc/host.js— Native messaging host; bridges socket ↔ Chrome, handles authextension/background.js— Service worker; executes Chrome APIs, runs JS viachrome.debugger
Multiple agents can share one browser session simultaneously.
Security model
The agent acts as you inside your real Chrome session. The trust boundary is the URL space, not the JS the agent runs.
- URL blocklist — banking, email, OAuth, password managers, crypto blocked by default. Extend via
~/.tandem/blocklist.txt(one regex per line,#for comments). The host pushes updates to the extension on reconnect. - Socket auth — 256-bit token rotated on every host start. Server reads token fresh on each connect.
- Prompt injection — agents are instructed never to act on instructions in page content (see AGENTS.md). This remains an unsolved problem industry-wide; the URL blocklist is your safety net.
browser_execute— runs arbitrary JS as you viachrome.debugger. No content filter (regex blocklists are trivially bypassable); 50KB result cap as DoS guard. Don't run untrusted agents.- Logging —
~/.tandem/logs/host.logredactscode,text, and URL query strings; rotates at 5MB; dir is0700.
Known limitation (Windows): the named pipe has the default ACL (Everyone). Any process running as the same Windows user can connect. Token rotation per host start limits exposure. Run only agents you trust.
Platform Support
| Platform | Status |
|---|---|
| Windows | ✓ (named pipe, registry) |
| macOS | ✓ |
| Linux | ✓ |
Uninstall
npx @felixisaac/tandem uninstall
Then remove the extension from Chrome and optionally delete ~/.tandem/.
Logs
~/.tandem/logs/host.log
License
MIT — forked from benjaminshafii/opencode-browser