opencode/packages/plugin-browser
2026-09-04 14:06:03 +10:00
..
script refactor(browser): keep contracts inside the plugin package 2026-09-04 14:06:02 +10:00
src docs(browser): specify screenshot visibility requirements 2026-09-04 14:06:03 +10:00
test refactor(browser): keep contracts inside the plugin package 2026-09-04 14:06:02 +10:00
package.json refactor(browser): keep contracts inside the plugin package 2026-09-04 14:06:02 +10:00
README.md docs(browser): specify screenshot visibility requirements 2026-09-04 14:06:03 +10:00
tsconfig.build.json
tsconfig.json
tsconfig.test.json refactor(browser): keep contracts inside the plugin package 2026-09-04 14:06:02 +10:00

Browser plugin

@opencode-ai/plugin-browser exposes the desktop browser through Code Mode. The server owns tools, invocation scope, and permissions; the desktop owns tabs, CDP, captured traffic, evaluations, and capture files. Core only registers the plugin. Neither endpoint imports the other's implementation.

const tab = await tools.browser.tabs.open({ url: "https://example.com" })
return await tools.browser.snapshot({ tabID: tab.id })

All page operations require a tabID returned by browser.tabs.open/list. Focus selects the visible Review tab, not an implicit command target. Discover current signatures with search({ namespace: "browser" }). Screenshots require a focused, visible tab; call browser.tabs.focus first.

Tools

  • Tabs: tabs.list, tabs.open, tabs.focus, tabs.close.
  • Navigation: navigate, back, forward, reload, stop, frames.
  • Observation: snapshot, find, evaluate, wait, screenshot.
  • Input: click, hover, drag, fill, fill_form, select, check, press, scroll, dialog.
  • Files: files.upload, files.drop, files.list, files.get.
  • Diagnostics: console, network.list, network.get.
  • Performance: trace.start, trace.stop, trace.analyze, cpu.start, cpu.stop, cpu.analyze.
  • Memory: heap.snapshot, heap.summary, heap.query, heap.object, heap.compare.
  • Audits: lighthouse (accessibility, SEO, best practices).

The source of truth for inputs, descriptions, and outputs is Browser.Operations in @opencode-ai/plugin-browser/rpc.

RPC

The plugin-owned contract is @opencode-ai/plugin-browser/rpc. This entrypoint contains only schemas and descriptions; it does not load the server plugin or filesystem code. The desktop subscribes to control events before starting attach with version: 2. The attachment call stays pending for its lifetime. A matching attached event is the readiness barrier.

  • state publishes the authoritative tab inventory.
  • control announces a request ID or cancellation; it never broadcasts arguments, script source, file bytes, or browser results on the server-wide event feed.
  • command retrieves the pending request through authenticated RPC.
  • result completes it. The plugin validates the selected operation's output.

The connection ID is correlation, not separate client authentication. Requests are bound to their attachment and tab. Disconnect, replacement, session movement, and unload fail outstanding work. Calls are not replayed automatically: a lost response does not prove that a click or evaluation never happened.

Files and remote servers

Upload paths are server-local. File bytes cross RPC and the desktop writes its own temporary copy. Captures/downloads travel back as bounded bytes and are saved to server-local temporary files. Returned files[].path values refer to that server; bytes are not included in the model's structured output. Images are also attached for the model to inspect. Temporary exports are not deleted on plugin reload, so a returned path remains usable; they follow the host's temporary-file lifetime.

Each transfer is limited to 5 MiB total. There is no shared filesystem assumption, resumable transfer service, new socket, or object store. Browsing uses the desktop's network: its localhost is not the remote server's localhost.

Remote endpoints can use HTTPS and the existing server credentials. A reverse proxy must allow long-lived event and attachment requests; the attachment RPC stays open rather than sending response-body heartbeats.

Lighthouse audits use snapshot mode without changing device emulation or adding an embedded report screenshot; use browser.screenshot for images. Trace exports contain the target renderer process, not the whole desktop application. A tab process change or trace-buffer loss is reported as an incomplete capture. Heap summaries report shallow size, not computed retained size, and do not prove leaks.

All page-derived data is untrusted, including structured outputs. Schema validation does not make page text an instruction or grant it authority.

Per-URL and server-file permission checks belong to the final permission layer (#46530). This base plugin layer intentionally does not enforce those rules.

Disable through normal configuration:

{ "plugins": ["-opencode.browser"] }