npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

oc-browserless

v0.3.0

Published

Browserless plugin for OpenCode using puppeteer-core

Downloads

38

Readme

oc-browserless

npm version License: MIT

Browserless plugin for OpenCode using puppeteer-core.

Features

  • 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

Installation

Prerequisites

Install Bun if you haven't already:

curl -fsSL https://bun.sh/install | bash

After installation, restart your terminal or source your shell profile:

# For bash
source ~/.bashrc

# For zsh
source ~/.zshrc

# For fish
source ~/.config/fish/config.fish

Verify Bun installation:

bun --version

Global Installation

npm install -g oc-browserless

Project Installation

npm install oc-browserless

Configuration

Add to your opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["oc-browserless"]
}

Browserless Setup

Local Browserless

Using Docker:

docker run -p 3000:3000 -e "CONCURRENT=10" browserless/chrome:latest

Or install globally:

npm install -g browserless
browserless --port=3000

Then set environment variable:

export BROWSERLESS_URL=ws://localhost:3000

Remote Browserless

Sign up for browserless.io and get your API key:

export BROWSERLESS_URL=wss://your-browserless-instance.com
export BROWSERLESS_API_KEY=your-api-key

Environment Configuration

Copy the example environment file:

cp .env.example .env

Edit .env with your browserless configuration:

BROWSERLESS_URL=ws://localhost:3000
BROWSERLESS_API_KEY=your-api-key-if-using-remote

Development Setup

1. Clone Repository

git clone https://github.com/rh-id/oc-browserless.git
cd oc-browserless

2. Install Dependencies

bun install

This will install:

  • Runtime dependencies (puppeteer-core, @opencode-ai/plugin)
  • Development dependencies (ESLint, Prettier, TypeScript)

3. Build Project

bun run build

This will:

  1. Compile TypeScript files to JavaScript in dist/ directory
  2. Generate type declarations
  3. 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.

4. Test with OpenCode

Run opencode in the project directory:

opencode

The plugin is automatically loaded from .opencode/plugin/ directory.

Project Structure

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

Plugin Development

For contributors working on the plugin locally:

Local Testing Workflow

  1. Make your changes to src/plugin/browserless.ts

  2. Build the project:

    bun run build

    This compiles TypeScript and copies the output to .opencode/plugin/ directory

  3. 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 opencode in the project root automatically loads the plugin from .opencode/plugin/
  4. Test your changes:

    opencode

    The plugin is automatically loaded from .opencode/plugin/ directory

  5. Iterate:

    • Make changes to src/plugin/browserless.ts
    • Run bun run build to update .opencode/plugin/
    • Test with opencode

Project Structure for Development

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

Build Process

The bun run build command:

  1. Compiles TypeScript files to JavaScript in dist/ directory
  2. Generates type declarations (.d.ts)
  3. Copies compiled files to .opencode/ for local OpenCode testing

Note: Always run bun run build after making changes to test them locally.

Usage

The plugin provides the following tools for OpenCode:

Browse Web Pages

// Navigate to a URL and get content
{
  "tool": "browse",
  "args": {
    "url": "https://example.com"
  }
}

DuckDuckGo Search

// Search the web
{
  "tool": "search",
  "args": {
    "query": "TypeScript best practices"
  }
}

Returns:

{
  "success": true,
  "query": "TypeScript best practices",
  "html": "<html>...</html>"
}

Take Screenshot

// Capture screenshot
{
  "tool": "screenshot",
  "args": {
    "url": "https://example.com",
    "path": "./screenshot.png",
    "format": "png",
    "fullPage": true
  }
}

Generate PDF

// 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"
  }
}

Browser Lifecycle

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

API Reference

browse

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

Search using DuckDuckGo.

| Argument | Type | Required | Default | Description | | -------- | ------ | -------- | ------- | ------------ | | query | string | Yes | - | Search query |

screenshot

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 |

pdf

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.

Development

# Install dependencies
bun install

# Build
bun run build

# Test
bun test

# Lint
bun run lint

# Format
bun run format

Development Workflow

Linting:

bun run lint

Auto-fix linting issues:

bun run lint:fix

Check formatting:

bun run format:check

Auto-fix formatting:

bun run format

Type checking:

bunx tsc --noEmit

Testing:

bun test

CI/CD

Build Workflow

  • Runs on push and PR
  • Installs dependencies
  • Builds project
  • Uploads artifacts

Lint Workflow

  • Runs on push and PR
  • Lints code with ESLint
  • Checks formatting

Release Workflow

  • Runs on main branch
  • Uses release-please for automated versioning
  • Publishes to npm on release

Versioning

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)

Troubleshooting

Connection Issues

Error: "Failed to connect to browserless"

  • Check BROWSERLESS_URL environment variable
  • Ensure browserless instance is running
  • Verify WebSocket URL is correct (use ws:// or wss://)
  • Verify firewall/network settings

Verify browserless is running:

curl http://localhost:3000/health

Check WebSocket URL format:

  • Local: ws://localhost:3000
  • Remote: wss://your-browserless.com

Timeout Issues

Error: "Operation timed out"

  • Increase timeout in browser options
  • Check network connectivity
  • Verify URL is accessible

Browser Disconnected

Error: "Browser not connected" or connection failures

  • Check BROWSERLESS_URL environment variable
  • Ensure browserless instance is running
  • Each tool creates its own connection - no manual management needed
  • Try running the tool again if connection fails

TypeScript Errors

If you see TypeScript errors about missing types:

Before dependencies are installed (expected):

  1. Cannot find module 'puppeteer-core' → Run bun install
  2. Cannot find module '@opencode-ai/plugin' → Run bun install
  3. Cannot find name 'setTimeout' / URL / process / fetch → Will resolve after bun install

These are not actual errors - they're just TypeScript not being able to resolve types until dependencies are installed.

After dependencies are installed:

  1. Restart your TypeScript server in your IDE
  2. Clear Bun cache:
rm -rf node_modules
bun install

Build Errors

If build fails:

  1. Check TypeScript version:
bun --version
  1. Update dependencies:
bun update

Clean Scripts

The 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 reset

Use these when:

  • clean - After making changes to TypeScript files
  • clean:deps - When dependencies need reinstalling
  • clean:all - When you want a fresh start
  • reset - When troubleshooting build or cache issues

Troubleshooting Build Issues

If you encounter build errors:

# Option 1: Full reset
bun run reset

# Option 2: Manual clean and rebuild
rm -rf dist
bun run build

Donate / Sponsor

If you find this project useful and would like to support its continued development, consider making a donation or becoming a sponsor:

https://teer.id/rh-id

Your support helps maintain and improve the project. Thank you! ❤️

License

MIT © Ruby Hartono

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For issues and questions, please use the GitHub Issues page.