ADR 001: Local Playwright browse daemon β
Status β
Accepted
Context β
Agents and CLI tools need a real browser for visual QA, screenshots, console/network capture, and light DOM automation. Alternatives considered:
- Embed Playwright only inside MCP long-lived process β couples browser lifecycle to one client; harder to reuse from shell scripts and second terminal.
- Remote browser farm β extra cost, latency, and secrets handling for typical local dev.
- Puppeteer-only β viable, but Playwrightβs cross-browser story and API fit agent βdrive the pageβ workflows well.
Decision β
Run a local HTTP server (src/browse-server.ts) that:
- Launches Chromium via Playwright on demand (
POST /session/start). - Protects mutating routes with Bearer token auth (
Authorization: Bearer <token>);GET /healthstays unauthenticated for probes. - Exposes focused endpoints (navigate, click, fill, screenshot, refs refresh, console/network buffers) documented in REST and MCP API Surface.
CLI entry: cm browse start (options align with .cm/config.yaml β browse: and env CM_BROWSE_TOKEN).
Consequences β
- Positive: Any client (CLI, agent, CI helper) can use the same contract; token is easy to rotate per project.
- Positive: Visual flows (
cm qa-visual) share one daemon instead of spawning browsers per call. - Negative: Operators must install browser binaries (
npx playwright install chromium) and keep token out of client-side code. - Operational: Port conflicts and
401when token mismatches β see Browse daemon runbook.
Related β
- Browse daemon runbook
- Skill:
skills/cm-browse/SKILL.md