Co-Pilot
Updated 24 days ago

playwriter

Rremorses
2.7k
remorses/playwriter
80
Agent Score

💡 Summary

Playwriter enables browser automation using the Playwright API with an extension and CLI.

🎯 Target Audience

Web developers looking to automate testingQA engineers needing to streamline browser interactionsData analysts wanting to scrape web data efficientlyDevOps professionals automating deployment tasksEducators teaching web automation techniques

🤖 AI Roast:Powerful, but the setup might scare off the impatient.

Security AnalysisHigh Risk

Risk: High. Review: shell/CLI command execution; outbound network access (SSRF, data egress); API keys/tokens handling and storage; filesystem read/write scope and path traversal; dependency pinning and supply-chain risk. Run with least privilege and audit before enabling in production.

Installation

  1. Install Extension from Chrome Web Store

  2. Click extension icon on a tab → turns green when connected

  3. Install the CLI and start automating the browser:

    npm i -g playwriter playwriter -s 1 -e "await page.goto('https://example.com')"
  4. Add skill to your agent:

    npx -y skills add remorses/playwriter

Quick Start

playwriter session new # creates stateful sandbox, outputs session id (e.g. 1) playwriter -s 1 -e "await page.goto('https://example.com')" playwriter -s 1 -e "console.log(await accessibilitySnapshot({ page }))" playwriter -s 1 -e "await page.locator('aria-ref=e5').click()"

CLI Usage

Each session has isolated state. Browser tabs are shared across sessions.

# Session management playwriter session new # creates stateful sandbox, outputs id (e.g. 1) playwriter session list # show sessions + state keys playwriter session reset <id> # fix connection issues # Execute (always use -s) playwriter -s 1 -e "await page.goto('https://example.com')" playwriter -s 1 -e "await page.click('button')" playwriter -s 1 -e "console.log(await page.title())"

Create your own page to avoid interference from other agents:

playwriter -s 1 -e "state.myPage = await context.newPage(); await state.myPage.goto('https://example.com')"

Multiline:

playwriter -s 1 -e $' const title = await page.title(); console.log({ title, url: page.url() }); '

Examples

Variables in scope: page, context, state (persists between calls), require, and Node.js globals.

Persist data in state:

playwriter -e "state.users = await page.$$eval('.user', els => els.map(e => e.textContent))" playwriter -e "console.log(state.users)"

Intercept network requests:

playwriter -e "state.requests = []; page.on('response', r => { if (r.url().includes('/api/')) state.requests.push(r.url()) })" playwriter -e "await Promise.all([page.waitForResponse(r => r.url().includes('/api/')), page.click('button')])" playwriter -e "console.log(state.requests)"

Set breakpoints and debug:

playwriter -e "state.cdp = await getCDPSession({ page }); state.dbg = createDebugger({ cdp: state.cdp }); await state.dbg.enable()" playwriter -e "state.scripts = await state.dbg.listScripts({ search: 'app' }); console.log(state.scripts.map(s => s.url))" playwriter -e "await state.dbg.setBreakpoint({ file: state.scripts[0].url, line: 42 })"

Live edit page code:

playwriter -e "state.cdp = await getCDPSession({ page }); state.editor = createEditor({ cdp: state.cdp }); await state.editor.enable()" playwriter -e "await state.editor.edit({ url: 'https://example.com/app.js', oldString: 'const DEBUG = false', newString: 'const DEBUG = true' })"

Screenshot with labels:

playwriter -e "await screenshotWithAccessibilityLabels({ page })"

MCP Setup

Using the CLI with the skill (step 4 above) is the recommended approach. For direct MCP server configuration, see MCP.md.

Visual Labels

Vimium-style labels for AI agents to identify elements:

await screenshotWithAccessibilityLabels({ page }) // Returns screenshot + accessibility snapshot with aria-ref selectors await page.locator('aria-ref=e5').click()

Color-coded: yellow=links, orange=buttons, coral=inputs, pink=checkboxes, peach=sliders, salmon=menus, amber=tabs.

Comparison

vs Playwright MCP

| | Playwright MCP | Playwriter | |---|---|---| | Browser | Spawns new Chrome | Uses your Chrome | | Extensions | None | Your existing ones | | Login state | Fresh | Already logged in | | Bot detection | Always detected | Can bypass (disconnect extension) | | Collaboration | Separate window | Same browser as user |

vs BrowserMCP

| | BrowserMCP | Playwriter | |---|---|---| | Tools | 12+ dedicated tools | 1 execute tool | | API | Limited actions | Full Playwright | | Context usage | High (tool schemas) | Low | | LLM knowledge | Must learn tools | Already knows Playwright |

vs Antigravity (Jetski)

| | Jetski | Playwriter | |---|---|---| | Tools | 17+ tools | 1 tool | | Subagent | Spawns for each browser task | Direct execution | | Latency | High (agent overhead) | Low |

vs Claude Browser Extension

| | Claude Extension | Playwriter | |---|---|---| | Agent support | Claude only | Any MCP client | | Windows WSL | No | Yes | | Context method | Screenshots (100KB+) | A11y snapshots (5-20KB) | | Playwright API | No | Full | | Debugger/breakpoints | No | Yes | | Live code editing | No | Yes | | Network interception | Limited | Full | | Raw CDP access | No | Yes |

Architecture

+---------------------+     +-------------------+     +-----------------+
|   BROWSER           |     |   LOCALHOST       |     |   MCP CLIENT    |
|                     |     |                   |     |                 |
|  +---------------+  |     | WebSocket Server  |     |  +-----------+  |
|  |   Extension   |<--------->  :19988         |     |  | AI Agent  |  |
|  +-------+-------+  | WS  |                   |     |  +-----------+  |
|          |          |     |  /extension       |     |        |        |
|    chrome.debugger  |     |       |           |     |        v        |
|          v          |     |       v           |     |  +-----------+  |
|  +---------------+  |     |  /cdp/:id <--------------> |  execute  |  |
|  | Tab 1 (green) |  |     +-------------------+  WS |  +-----------+  |
|  | Tab 2 (green) |  |                               |        |        |
|  | Tab 3 (gray)  |  |     Tab 3 not controlled      |  Playwright API |
+---------------------+     (no extension click)      +-----------------+

Remote CLI

Run CLI from a different machine (devcontainer, VM, SSH) while Chrome runs on your host.

On host:

playwriter serve --token <secret>

From remote:

playwriter --host 192.168.1.10 --token <secret> session new playwriter --host 192.168.1.10 --token <secret> -s 1 -e "await page.goto('https://example.com')"

Or with env vars:

export PLAYWRITER_HOST=192.168.1.10 export PLAYWRITER_TOKEN=<secret> playwriter -s 1 -e "await page.goto('https://example.com')"

Security

  • Local only: WebSocket server on localhost:19988
  • Origin validation: Only our extension IDs allowed (browsers can't spoof Origin)
  • Explicit consent: Only tabs where you clicked the extension icon
  • Visible automation: Chrome shows automation banner on controlled tabs
  • No remote access: Malicious websites cannot connect

Playwright API

Connect programmatically (without CLI):

import { chromium } from 'playwright-core' import { startPlayWriterCDPRelayServer, getCdpUrl } from 'playwriter' const server = await startPlayWriterCDPRelayServer() const browser = await chromium.connectOverCDP(getCdpUrl()) const page = browser.contexts()[0].pages()[0] await page.goto('https://example.com') await page.screenshot({ path: 'screenshot.png' }) // Don't call browser.close() - it closes the user's Chrome server.close()

Or connect to a running server:

npx -y playwriter serve --host 127.0.0.1
const browser = await chromium.connectOverCDP('http://127.0.0.1:19988')

Troubleshooting

View relay server logs to debug issues:

playwriter logfile # prints the log file path # typically: /tmp/playwriter/relay-server.log (Linux/macOS)

The relay log contains extension, MCP and WebSocket server logs. A separate CDP JSONL log is also created alongside it (see playwriter logfile). Both are recreated on each server start.

Example: summarize CDP traffic counts by direction + method:

jq -r '.direction + "\t" + (.message.method // "response")' /tmp/playwriter/cdp.jsonl | uniq -c

Known Issues

  • If all pages return about:blank, restart Chrome (Chrome bug in chrome.debugger API)
  • Browser may switch to light mode on connect (Playwright issue)
5-Dim Analysis
Clarity8/10
Novelty8/10
Utility9/10
Completeness8/10
Maintainability7/10
Pros & Cons

Pros

  • Integrates seamlessly with Playwright
  • Supports complex browser automation tasks
  • Isolated session management for safety
  • Extensive CLI commands for flexibility

Cons

  • Requires installation of a browser extension
  • May have a learning curve for new users
  • Limited to local browser automation
  • Potential issues with browser state management

Related Skills

pytorch

S
toolCode Lib
92/ 100

“It's the Swiss Army knife of deep learning, but good luck figuring out which of the 47 installation methods is the one that won't break your system.”

agno

S
toolCode Lib
90/ 100

“It promises to be the Kubernetes for agents, but let's see if developers have the patience to learn yet another orchestration layer.”

nuxt-skills

S
toolCo-Pilot
90/ 100

“It's essentially a well-organized cheat sheet that turns your AI assistant into a Nuxt framework parrot.”

Disclaimer: This content is sourced from GitHub open source projects for display and rating purposes only.

Copyright belongs to the original author remorses.