The side panel no longer brings its own browser tools into opencode. It is an
opencode client like the desktop app and TUI; agents drive the browser through
the `browse` MCP server (renamed from opencode-browser), and setup pairs the
extension with opencode instead of using a native messaging host.
Removed / replaced:
- The per-session browser attachment (session-browser, page, cdp, files,
profiling, analysis, diagnostics, preview): the panel no longer attaches
`browser.*` tools or writes instruction entries. Instead, each prompt sent
from the panel is preceded by a synthetic "Browser context" message
(resume: false) naming the page; a tab shared with agents comes with its
Chrome tab id. Sent only when the page or its sharing changed.
- The opencode plugin (site_scripts, browsing, browser.tabs.request) and its
relay-link: these are browse MCP tools now (site_scripts_*, browsing_*,
tabs_request), sent through the relay as `extension.request`
(POST /extension/request, 10-minute timeout for the user's answer).
tabs_request adopts the approved tab into the session.
- The native messaging host and service discovery: the extension keeps a list
of paired servers (background/servers.ts, chrome.storage.local). connect.html
redeems a one-time code from opencode's own pairing (POST /api/pair,
GET /auth/connect/:code -> 30-day token used as the password) and renews the
token a week before expiry. Loopback links pair right away; others ask.
Servers can also be added by hand with a code or the service password; the
directory menu switches, adds, and forgets servers.
- Permissions nativeMessaging, downloads, webNavigation.
Setup (cli/src/setup.ts):
- `install` writes the `browse` MCP entry (renaming the old one), removes the
old host and plugin, then runs `connect`.
- `connect` finds browsers/profiles with the extension (default browser
first; macOS-protected profiles are reported as unknown and asked about),
opens connect.html#server=&code= there via the browser's executable and
--profile-directory, opens the Web Store listing when missing, and prints
the link and code when headless (no TTY, SSH, no display, --no-open).
- The relay reports the extension's build in /extension/status; install
checks the build changed after asking for a reload, and says so (and skips
connect) when it didn't.
Fixed: the extension's runtime.reload closed its socket with code 1001,
which browsers reject (only 1000 or 3000-4999), so the reload threw and never
ran; every install since reported "Reloaded" while Helium kept the old
build. It closes with 1000 now.
Also: session_adopt / `session adopt --tab-id` adopt a tab by Chrome tab id;
"Share tab" above the composer lets agents use the current tab; agent guide
renamed to skills/browse; store listing and privacy policy updated.
Verified in the user's Helium: `connect --yes` detected Helium/Ryan (default),
Chrome unreadable (macOS privacy), Arc without the extension, opened the
connect page, which showed "Connected · This computer · 4102". Through the
browse MCP server: site_scripts_list, tabs_request (returned the tab id and
adopted it), session_adopt({ tabId }) (success, exclusivity error, unknown-tab
error). The synthetic message with metadata was accepted and stayed queued
(resume: false). A clean headless Chromium loads the build and the connect
page answers. Install now reports a stale reload instead of claiming success.
Typecheck (extension, cli), lint. Upstream relay suite: 871/888; the new
failures are the 9 MCP tests asserting the old server name.
Not yet verified: the panel UI (server menu, Share tab, composer flow).
The extension becomes "opencode Browser", the product that will also take over
Browser Control's extension, and the CLI command follows it.
Renamed:
- packages/open-extension -> packages/browser-extension (@opencode/browser-extension),
manifest name, panel copy, README, and agent-facing text.
- `opencode sidepanel` -> `opencode browser` (install/status/uninstall/host);
services/sidepanel.ts -> services/browser-extension.ts.
- Native host ai.opencode.sidepanel -> ai.opencode.browser; plugin id, file
(plugins/opencode-browser.ts), relay RPC (opencode-browser.relay), panel port,
session context keys, and cursor element id use "opencode-browser".
Install now:
- adds the Browser Control MCP server to opencode's global config (browser-control
on PATH, else npx @opencode-ai/browser-control), with
BROWSER_CONTROL_EXTENSION_ORIGINS so existing relays accept this extension;
skips it when a browser-control server is already configured;
- uses clack steps and, in a terminal, waits up to 3 minutes for the extension's
first connection; status also reports the Browser Control MCP server.
Verified: cli and extension typecheck, extension build, and root lint pass; in a
temp HOME/XDG, `opencode browser install` registered Helium, wrote the MCP entry
to opencode.json, started the service, and `status` reported all three.
Use the shared workspace version (2.0.22) like the other packages and drop the
test script: the package has no test files, and CI runs `turbo test
--affected`, where `bun test` with no tests would fail the job.
Verified: bun install leaves the lockfile consistent; typecheck and build pass.
Agents (and the user) can now extend websites with scripts that Open Extension
injects itself through chrome.userScripts, the API Tampermonkey uses, instead
of asking the user to install a userscript manager.
- Background stores scripts in chrome.storage.local, registers them in the
isolated USER_SCRIPT world, and reconciles registrations on startup. Drafts
may carry a // ==UserScript== header (@name, @description, @match,
@exclude-match, @run-at); unsupported keys become warnings.
- New opencode plugin (plugin/open-extension.ts) adds site_scripts.install /
list / get / set_enabled / remove tools. It relays each call over a new
open-extension.scripts RPC: the plugin emits a control event, the extension
claims the command once (so two browser profiles never both ask), runs it,
and returns the result. Without an open side panel the tools fail fast
after 8 seconds with instructions.
- Agent installs wait for the user's approval in any open side panel
(approvals message / approval.reply); a cancelled tool call withdraws it.
- Manifest gains the userScripts permission and <all_urls> host access,
which userScripts needs to inject into matched sites.
- host:install also bundles the plugin into ~/.config/opencode/plugins.
Verified: typecheck and build pass; the live server loaded the plugin and
exposed the site_scripts namespace; with no panel, list failed after 8s with
the instruction; in Chrome for Testing with user scripts allowed, an agent
install was approved, registered, and ran on example.com (data attribute set).
Side panel UI for approvals and script management follows separately.
Adds packages/open-extension, a Chromium MV3 extension ("Open Extension") that
lets opencode agents use real browser tabs from a side panel, modeled on the
ChatGPT extension's side chat.
- Background service worker implements the browser end of the built-in
opencode.browser plugin's experimental.browser RPC (attach v4, state,
command, result), the same contract the desktop pane implements with
Electron. Agents' browser.* tools now drive Chrome tabs via chrome.debugger.
- Tab access is limited to tabs the agent opens (grouped as "opencode") and
tabs the user explicitly shares; closing a shared tab only releases it.
- Page operations are ported from gui-extensions/src/browser/chromium.ts;
file uploads become page-side File objects. Downloads, traces, CPU/heap
profiles, Lighthouse, and preview report "unsupported" for now.
- Native messaging host (ai.opencode.open_extension) returns the background
service URL and password via `opencode service start/get password`;
`bun run host:install` registers it for installed Chromium browsers.
- The side panel is a placeholder; its UI lands separately.
Verified: bun typecheck and vite build pass; a live attach handshake against
the running service returned the attached control event and accepted state;
the installed host answered {ok,url,password} under a minimal environment.