Browserless plugin for OpenCode using puppeteer-core.
- Web Browsing: Navigate and browse web pages with content extraction and security certificate information
- DuckDuckGo Search: Search the web with raw HTML content
- Screenshots: Capture screenshots in PNG, JPEG, and WebP formats
- PDF Generation: Convert HTML or URLs to PDF documents
- Browser Lifecycle Management: Automatic browser connection management
Install Bun if you haven't already:
curl -fsSL https://bun.sh/install | bashAfter installation, restart your terminal or source your shell profile:
# For bash
source ~/.bashrc
# For zsh
source ~/.zshrc
# For fish
source ~/.config/fish/config.fishVerify Bun installation:
bun --versionnpm install -g oc-browserlessnpm install oc-browserlessAdd to your opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["oc-browserless"]
}Using Docker:
docker run -p 3000:3000 -e "CONCURRENT=10" browserless/chrome:latestOr install globally:
npm install -g browserless
browserless --port=3000Then set environment variable:
export BROWSERLESS_URL=ws://localhost:3000Sign up for browserless.io and get your API key:
export BROWSERLESS_URL=wss://your-browserless-instance.com
export BROWSERLESS_API_KEY=your-api-keyCopy the example environment file:
cp .env.example .envEdit .env with your browserless configuration:
BROWSERLESS_URL=ws://localhost:3000
BROWSERLESS_API_KEY=your-api-key-if-using-remotegit clone https://github.com/rh-id/oc-browserless.git
cd oc-browserlessbun installThis will install:
- Runtime dependencies (
puppeteer-core,@opencode-ai/plugin) - Development dependencies (ESLint, Prettier, TypeScript)
bun run buildThis will:
- Compile TypeScript files to JavaScript in
dist/directory - Generate type declarations
- Copy compiled files to
.opencode/for local OpenCode testing
Note: The .opencode/ directory is used for local development with OpenCode. When the package is published to npm, only the dist/ directory is included.
Run opencode in the project directory:
opencodeThe plugin is automatically loaded from .opencode/plugin/ directory.
oc-browserless/
├── .github/workflows/ # CI/CD workflows
│ ├── build.yml # Build and test
│ ├── lint.yml # Linting and formatting
│ └── release.yml # Automated releases
├── .husky/ # Git hooks
│ └── pre-commit # Pre-commit lint-staged
├── .opencode/ # OpenCode plugin files (compiled for local dev)
│ ├── plugin/ # Compiled plugin
│ │ └── browserless.js # Plugin entry point (all code)
│ └── package.json # Dependencies for local dev
├── dist/ # Compiled output (published to npm)
│ └── plugin/
│ ├── browserless.js # Compiled plugin
│ ├── browserless.d.ts # Type declarations
│ ├── browserless.js.map # Source map
│ └── browserless.d.ts.map # Type source map
├── scripts/ # Build scripts
│ └── build-copy.js # Build copy script
├── src/ # Source code (TypeScript)
│ └── plugin/
│ └── browserless.ts # Complete plugin (all code, ~613 lines)
├── Configuration Files
│ ├── .gitignore
│ ├── .gitattributes
│ ├── eslint.config.cjs
│ ├── .prettierrc
│ ├── .env.example
│ ├── .release-please-manifest.json
│ ├── opencode.json
│ ├── package.json
│ └── tsconfig.json
└── Documentation
├── README.md
├── CONTRIBUTING.md
└── LICENSE
For contributors working on the plugin locally:
-
Make your changes to
src/plugin/browserless.ts -
Build the project:
bun run build
This compiles TypeScript and copies the output to
.opencode/plugin/directory -
The
.opencode/directory is used for local development with OpenCode:- It contains the compiled plugin code
- When the package is published to npm, only the
dist/directory is included - Running
opencodein the project root automatically loads the plugin from.opencode/plugin/
-
Test your changes:
opencode
The plugin is automatically loaded from
.opencode/plugin/directory -
Iterate:
- Make changes to
src/plugin/browserless.ts - Run
bun run buildto update.opencode/plugin/ - Test with
opencode
- Make changes to
src/plugin/
└── browserless.ts # Source code (edit this)
dist/plugin/ # Compiled output (published to npm)
├── browserless.js
├── browserless.d.ts
└── browserless.js.map
.opencode/plugin/ # Local dev copy (for testing with opencode)
└── browserless.js # Same compiled code as dist/plugin/browserless.js
The bun run build command:
- Compiles TypeScript files to JavaScript in
dist/directory - Generates type declarations (
.d.ts) - Copies compiled files to
.opencode/for local OpenCode testing
Note: Always run bun run build after making changes to test them locally.
The plugin provides the following tools for OpenCode:
// Navigate to a URL and get content
{
"tool": "browse",
"args": {
"url": "https://example.com"
}
}// Search the web
{
"tool": "search",
"args": {
"query": "TypeScript best practices"
}
}Returns:
{
"success": true,
"query": "TypeScript best practices",
"html": "<html>...</html>"
}// Capture screenshot
{
"tool": "screenshot",
"args": {
"url": "https://example.com",
"path": "./screenshot.png",
"format": "png",
"fullPage": true
}
}// Generate PDF from URL
{
"tool": "pdf",
"args": {
"url": "https://example.com",
"path": "./output.pdf",
"format": "A4",
"printBackground": true
}
}
// Generate PDF from HTML
{
"tool": "pdf",
"args": {
"html": "<html><body><h1>Hello World</h1></body></html>",
"path": "./output.pdf"
}
}All browser operations automatically manage their own connections:
- No manual start/stop required - tools handle this internally
- Each tool execution creates an isolated browser instance
- Browser sessions are NOT persistent across tool calls
- Browserless supports multiple concurrent connections automatically
- Each tool operates in isolation with no shared state
- No connection reuse - each operation creates fresh browser instance
Navigate to and browse web pages.
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
| url | string | Yes | - | URL to navigate to |
Returns:
{
"success": true,
"url": "https://example.com",
"title": "Example Domain",
"content": "<html>...</html>",
"certificate": {
"issuer": "CN=DigiCert Inc",
"protocol": "TLS 1.3",
"subjectName": "CN=example.com",
"subjectAlternativeNames": ["example.com", "www.example.com"],
"validFrom": 1234567890,
"validTo": 1234567890
}
}The certificate field is null for HTTP connections or when security details are unavailable.
Search using DuckDuckGo.
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
| query | string | Yes | - | Search query |
Capture page screenshots.
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
| url | string | No | - | URL to screenshot |
| path | string | No | - | Output file path |
| format | enum | No | png | Format: png, jpeg, webp |
| fullPage | boolean | No | false | Full page screenshot |
| quality | number | No | - | Quality for jpeg/webp (0-100) |
| viewportWidth | number | No | - | Viewport width |
| viewportHeight | number | No | - | Viewport height |
Generate PDF from HTML or URL.
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
| html | string | No* | - | HTML content |
| url | string | No* | - | URL to convert |
| path | string | No | - | Output file path |
| format | enum | No | A4 | Paper format |
| printBackground | boolean | No | true | Print backgrounds |
| landscape | boolean | No | false | Landscape mode |
| marginTop | string | No | 0cm | Top margin |
| marginBottom | string | No | 0cm | Bottom margin |
| marginLeft | string | No | 0cm | Left margin |
| marginRight | string | No | 0cm | Right margin |
*Either html or url is required.
# Install dependencies
bun install
# Build
bun run build
# Test
bun test
# Lint
bun run lint
# Format
bun run formatLinting:
bun run lintAuto-fix linting issues:
bun run lint:fixCheck formatting:
bun run format:checkAuto-fix formatting:
bun run formatType checking:
bunx tsc --noEmitTesting:
bun test- Runs on push and PR
- Installs dependencies
- Builds project
- Uploads artifacts
- Runs on push and PR
- Lints code with ESLint
- Checks formatting
- Runs on main branch
- Uses release-please for automated versioning
- Publishes to npm on release
Uses automated versioning with release-please:
feat:→ Minor version bump (1.x.0)fix:→ Patch version bump (x.x.1)BREAKING CHANGE:→ Major version bump (2.0.0)
Error: "Failed to connect to browserless"
- Check
BROWSERLESS_URLenvironment variable - Ensure browserless instance is running
- Verify WebSocket URL is correct (use
ws://orwss://) - Verify firewall/network settings
Verify browserless is running:
curl http://localhost:3000/healthCheck WebSocket URL format:
- Local:
ws://localhost:3000 - Remote:
wss://your-browserless.com
Error: "Operation timed out"
- Increase timeout in browser options
- Check network connectivity
- Verify URL is accessible
Error: "Browser not connected" or connection failures
- Check
BROWSERLESS_URLenvironment variable - Ensure browserless instance is running
- Each tool creates its own connection - no manual management needed
- Try running the tool again if connection fails
If you see TypeScript errors about missing types:
Before dependencies are installed (expected):
Cannot find module 'puppeteer-core'→ Runbun installCannot find module '@opencode-ai/plugin'→ Runbun installCannot find name 'setTimeout'/URL/process/fetch→ Will resolve afterbun install
These are not actual errors - they're just TypeScript not being able to resolve types until dependencies are installed.
After dependencies are installed:
- Restart your TypeScript server in your IDE
- Clear Bun cache:
rm -rf node_modules
bun installIf build fails:
- Check TypeScript version:
bun --version- Update dependencies:
bun updateThe project includes several clean scripts for easy cleanup:
# Clean build output only
bun run clean
# Clean build output and dependencies
bun run clean:deps
# Clean build output and all dependencies
bun run clean:all
# Full reset: clean everything, reinstall dependencies, and rebuild
bun run resetUse these when:
clean- After making changes to TypeScript filesclean:deps- When dependencies need reinstallingclean:all- When you want a fresh startreset- When troubleshooting build or cache issues
If you encounter build errors:
# Option 1: Full reset
bun run reset
# Option 2: Manual clean and rebuild
rm -rf dist
bun run buildIf you find this project useful and would like to support its continued development, consider making a donation or becoming a sponsor:
Your support helps maintain and improve the project. Thank you! ❤️
MIT © Ruby Hartono
Contributions are welcome! Please feel free to submit a Pull Request.
For issues and questions, please use the GitHub Issues page.