pen # defaults: stdio, localhost:9222
pen --cdp-url http://localhost:9222 --log-level debug
pen --allow-eval --project-root /my/projectPEN prints PEN ready to stderr and waits for an MCP client on stdin/stdout. In normal use your IDE launches it automatically — you don't run it by hand.
| Flag | Default | Purpose |
|---|---|---|
--cdp-url |
http://localhost:9222 |
CDP endpoint |
--transport |
stdio |
stdio, http, or sse |
--addr |
localhost:6100 |
Bind address for HTTP/SSE |
--allow-eval |
false |
Enable pen_evaluate (executes JS in browser) |
--auto-launch |
true |
Auto-launch a debug browser if CDP not found |
--project-root |
. |
Sandbox for source tool file paths |
--log-level |
info |
debug / info / warn / error |
--stateless |
false |
Stateless HTTP mode (no session tracking) |
--version |
— | Print version and exit |
Both -flag and --flag work.
For network-accessible use instead of stdio:
pen --transport http --addr localhost:6100Serves MCP at http://localhost:6100/mcp. The sse transport works the same way.
PEN automatically launches a debug browser when no CDP endpoint is found. Just run:
penThis automatically:
- Detects an installed Chromium browser (Chrome, Edge, or Brave)
- Launches it with a separate debug profile — your existing browser is untouched
- Adds
--no-first-runand--no-default-browser-checkto suppress prompts - Waits for the CDP port to become available
- Connects and is ready to go
Your normal browser (tabs, bookmarks, logged-in sessions) is completely unaffected. PEN opens a separate, clean Chrome window alongside it.
To disable auto-launch: pen --auto-launch=false
If you prefer to launch the browser yourself, use --user-data-dir to avoid conflicts with your existing browser:
macOS:
open -a "Google Chrome" --args --remote-debugging-port=9222 --user-data-dir=/tmp/pen-debug-profile --no-first-runWindows (PowerShell):
& "C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222 --user-data-dir="$env:TEMP\pen-debug-profile" --no-first-runLinux:
google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/pen-debug-profile --no-first-run &Why
--user-data-dir? Chrome's--remote-debugging-portflag is silently ignored when Chrome is already running. The--user-data-dirflag forces a completely separate instance that works alongside your existing browser.
Verify: http://localhost:9222/json should return a JSON array of open tabs.
Your editor spawns PEN as a child process. Configure once, then forget about it. Auto-launch is on by default — no browser setup needed.
VS Code — .vscode/mcp.json:
{
"servers": {
"pen": {
"command": "pen",
"args": ["--project-root", "${workspaceFolder}"]
}
}
}Cursor — .cursor/mcp.json in your project (or ~/.cursor/mcp.json for global):
{
"mcpServers": {
"pen": {
"command": "pen",
"args": ["--project-root", "${workspaceFolder}"]
}
}
}Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"pen": {
"command": "pen",
"args": ["--project-root", "/absolute/path/to/project"]
}
}
}If pen isn't on PATH, use the full binary path in the command field.
git clone https://github.com/edbnme/pen.git && cd pen
go build -o pen ./cmd/pen # Linux / macOS
go build -o pen.exe ./cmd/pen # WindowsNeeds Go 1.23+. Dependencies download automatically.
PEN connects to a local browser via CDP. CDP is locked to localhost — that's a security choice, not a bug.
# Install Chrome (Debian/Ubuntu)
apt-get install -y google-chrome-stable
# Launch headless
google-chrome --headless --no-sandbox --disable-gpu \
--remote-debugging-port=9222 --remote-debugging-address=127.0.0.1 &
# Run PEN
pen --cdp-url http://127.0.0.1:9222FROM golang:1.23-bookworm AS builder
WORKDIR /app
COPY . .
RUN go build -o pen ./cmd/pen
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y google-chrome-stable --no-install-recommends \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/pen /usr/local/bin/pen
CMD ["sh", "-c", "google-chrome --headless --no-sandbox --disable-gpu --remote-debugging-port=9222 --remote-debugging-address=127.0.0.1 & sleep 2 && exec pen --cdp-url http://127.0.0.1:9222"]Use a real process manager (supervisord, etc.) in production instead of backgrounding Chrome with &.
Forward a remote CDP port to localhost:
ssh -L 9222:localhost:9222 user@server
pen --cdp-url http://localhost:9222- Never expose port 9222 to the network
--no-sandboxonly in containers, not bare metal--allow-evalonly in trusted environments- Always set
--project-rootin production
The pen_lighthouse tool runs full Lighthouse audits against your page. It requires the Lighthouse CLI installed separately:
npm install -g lighthouseIf Lighthouse isn't installed, all other PEN tools work normally — pen_lighthouse will just return a helpful error telling you how to install it.
| Problem | Fix |
|---|---|
CDP connect failed: connection refused |
Browser not running or wrong port. Check http://localhost:9222/json. |
invalid CDP URL |
PEN only allows localhost / 127.0.0.1 |
no targets found |
Open at least one tab |
pen: command not found |
Binary not on PATH — use full path or install via Homebrew/Scoop |
| Rate limit errors | Wait the cooldown or restart PEN |
Heap snapshot exceeded 2 GB limit |
Heap too large. Use pen_heap_sampling for lower-overhead alternative |
Trace file exceeded 500 MB limit |
Reduce categories or use shorter duration |
Domain lock errors (e.g. already in use) |
Wait for the current operation to finish (error shows who holds it) |
| IDE doesn't see tools | Restart IDE after editing MCP config |