Headless browser automation for OpenCode using Playwright. Gives OpenCode the ability to navigate, screenshot, extract content, and interact with any web page programmatically.
- Full browser control — Launch, navigate, click, fill, scroll, hover, select
- Content extraction — HTML, text, markdown, links, images, forms, tables, accessibility tree
- Media capture — Screenshots (full page or element), PDF generation
- Network & console — Capture requests/responses, console logs, performance metrics
- Storage management — localStorage, sessionStorage, cookies
- JavaScript execution — Run arbitrary code in page context
- Multiple sessions — Run parallel browser instances with isolated contexts
- Headless by default — Fast, lightweight, CI/CD ready
Tell your OpenCode agent:
Install opencode-browser-plugin from https://github.com/kenanwahbeh/opencode-browser-plugin into my OpenCode config
The agent will automatically edit your config file (.opencode/opencode.json for project, or ~/.config/opencode/opencode.jsonc for global) and add the plugin to the "plugin" array. Then restart OpenCode — the plugin downloads and installs on startup.
Project config (.opencode/opencode.json):
{
"plugin": ["https://github.com/kenanwahbeh/opencode-browser-plugin"]
}Global config (~/.config/opencode/opencode.jsonc):
{
"plugin": ["https://github.com/kenanwahbeh/opencode-browser-plugin"]
}Then restart OpenCode — the plugin downloads and installs on startup.
git clone https://github.com/kenanwahbeh/opencode-browser-plugin
cd opencode-browser-plugin
npm ci
npx playwright install chromium
bun run buildAdd to your OpenCode config:
{
"plugin": ["/absolute/path/to/opencode-browser-plugin"]
}Once installed, use the tools in your OpenCode session:
// Launch a browser session
const { sessionId } = await browser_launch({
viewport: { width: 1920, height: 1080 },
});
// Navigate to a page
await browser_navigate({
sessionId,
url: "https://example.com",
waitUntil: "networkidle",
});
// Extract content
const { html, text, links, images, forms, tables } = await browser_content({
sessionId,
type: "all",
});
// Take a screenshot
const screenshot = await browser_screenshot({ sessionId, fullPage: true });
// Click and interact
await browser_click({
sessionId,
selector: "button.submit",
waitForNavigation: true,
});
await browser_fill({
sessionId,
selector: "input[name=email]",
value: "user@example.com",
});
// Generate PDF
const pdf = await browser_pdf({ sessionId, format: "A4" });
// Close when done
await browser_close({ sessionId });| Tool | Description |
|---|---|
browser_launch |
Launch a new headless browser session |
browser_navigate |
Navigate to a URL |
browser_screenshot |
Capture screenshot (full page or element) |
browser_pdf |
Generate PDF of page |
browser_content |
Extract HTML, text, markdown, links, images, forms, tables |
browser_click |
Click an element |
browser_fill |
Fill input/textarea/select |
browser_select |
Select dropdown options |
browser_hover |
Hover over element |
browser_scroll |
Scroll page or element |
browser_wait |
Wait for selector, URL, or condition |
browser_evaluate |
Execute JavaScript in page |
browser_network |
Capture network requests |
browser_console |
Get console logs |
browser_accessibility |
Get accessibility tree |
browser_storage |
Manage localStorage/sessionStorage/cookies |
browser_close |
Close browser session |
browser_list |
List active sessions |
The plugin accepts optional configuration via OpenCode config:
{
"plugin": [[
"https://github.com/kenanwahbeh/opencode-browser-plugin",
{
"defaultViewport": { "width": 1920, "height": 1080 },
"defaultUserAgent": "Mozilla/5.0 ...",
"defaultLocale": "en-US",
"defaultTimezoneId": "UTC"
}
]]
}- Node.js 20+
- Bun 1.2+
- OpenCode with plugin support
- A Playwright Chromium browser (
npx playwright install chromium)
If your CI image provides Chromium outside Playwright's cache, set
OPENCODE_BROWSER_EXECUTABLE_PATH to its executable path before starting OpenCode.
opencode-browser-plugin/
├── src/
│ └── plugin.ts # Main plugin entry point
├── test/
│ └── plugin.test.ts # Contract and regression tests
├── dist/
│ └── plugin.js # Built output (ESM, generated)
├── package.json
├── tsconfig.json
└── package-lock.json
The plugin uses Playwright's Chromium in headless mode. Each session maintains its own Browser, Context, and Page for isolation, and records console messages, page errors, and failed requests for debugging.
# Install dependencies deterministically
npm ci
# Build plugin
bun run build
# Type check
bun run typecheck
# Run tests
bun test
# Watch mode (rebuild on change)
bun run devMIT