| name | playwright-skill |
| description | Browser automation for web projects using playwright-cli |
| version | 2.0.0 |
| allowed-tools | Bash(playwright-cli:*), Bash(bin/open), Bash(bin/close), Bash(bin/click-css), Bash(bin/fill-css), Bash(bin/upload), Bash(bin/auth-save), Bash(bin/auth-load), Bash(bin/context), Bash(bin/inject-capture), Bash(bin/cache-query) |
Playwright Skill v2
Browser automation using playwright-cli (Microsoft's official Playwright CLI). No daemon management required — the browser starts and stops automatically.
1. Session Startup & Isolation
Always start with bin/open (not bare playwright-cli open):
bin/open --headed
playwright-cli goto <url>
bin/open derives a session name from the current directory (e.g. my-project), appends a short agent identifier when running under Claude Code, and starts the browser under that named session. All other bin/ scripts resolve the session automatically.
Session isolation: When CLAUDE_SESSION_ID is set (automatic in Claude Code), each agent gets its own session name (e.g. my-project-a1b2c3d4) and session file. Parallel agents never interfere with each other. If a session is already open for this agent, bin/open closes it first to prevent orphaned Chrome processes — other agents' sessions are unaffected.
Before opening a new session, check if you already have one:
playwright-cli list
If your session is already listed and open, skip bin/open and use it directly.
At the end of a task, clean up with:
bin/close
This closes the browser and removes the session tracking file. If the browser is stuck use playwright-cli kill-all instead.
Overriding the session name:
bin/open --headed --session my-custom-name
2. Reading Snapshots
After every command, stdout contains a link to the current accessibility tree:
### Snapshot
- [Snapshot](.playwright-cli/page-<timestamp>.yml)
Always read the snapshot file to see what's on the page:
Read .playwright-cli/page-<timestamp>.yml
The snapshot contains all interactive elements with [ref=eN] identifiers used for clicking, filling, and hovering.
3. Core Commands
Navigation
playwright-cli goto <url>
playwright-cli go-back
playwright-cli go-forward
playwright-cli reload
Interacting with Elements (use ref from snapshot)
playwright-cli click <ref>
playwright-cli fill <ref> <value>
playwright-cli type <text>
playwright-cli press <key>
playwright-cli hover <ref>
playwright-cli select <ref> <val>
Observation
playwright-cli snapshot
playwright-cli screenshot
Dialogs
playwright-cli dialog-accept
playwright-cli dialog-dismiss
Session Management
bin/close
playwright-cli kill-all
playwright-cli list
Escape Hatch
playwright-cli run-code '<async page => { }>'
4. CSS Selector Fallbacks
Use these when ARIA-ref commands fail — for example, when framework-rendered elements are outside the main ARIA tree.
Modal dialogs — often rendered as DOM portals:
bin/click-css "[data-modal-confirm]"
bin/click-css "button[data-dismiss]"
Hidden file inputs — often hidden from accessibility tree:
bin/upload "input[type=file]" /path/to/file.pdf
Framework event targets — ARIA-ref clicks don't always fire framework event handlers:
bin/fill-css "[data-field=email]" "user@example.com"
bin/click-css "[data-action=save]"
See skill/CONFIG.md for project-specific selector patterns.
5. Auth Profiles
Auth profile names and base URLs are defined in skill/worktrees.json (gitignored).
See skill/CONFIG.md for setup instructions.
Save after authenticating:
bin/auth-save <profile-name>
Restore on a new session:
bin/open --headed
playwright-cli goto <baseUrl>
bin/auth-load <profile-name>
playwright-cli goto <baseUrl>/dashboard
Profiles are stored in .playwright-skill/auth/ and gitignored.
6. Recovery
| Problem | Solution |
|---|
| Browser stuck / daemon hung | playwright-cli kill-all then bin/open --headed |
| No session open (bin/context error) | bin/open --headed |
| Auth expired | bin/auth-load <profile> then reload |
| Element ref not found | playwright-cli snapshot then read the new snapshot file |
| Modal/portal not clickable from ARIA tree | Use bin/click-css with CSS selector |
| End of task cleanup | bin/close |
7. run-code Examples
playwright-cli run-code 'await page.waitForSelector(".loading-complete")'
playwright-cli run-code 'await page.evaluate(() => window.dispatchEvent(new Event("refresh")))'
playwright-cli run-code 'await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight))'
playwright-cli run-code 'console.log(await page.locator("table tbody tr").count())'
8. Context Capture & QA Workflow
Three tools integrate ResponseBuilder and CacheStore into the v2 skill, enabling rich page diagnostics.
Tools
| Command | Description |
|---|
bin/context [--screenshot] | Capture full page context → compact TrimmedResponse JSON on stdout |
bin/inject-capture | Inject browser-side console + fetch/XHR patching |
bin/cache-query <cmd> [args] | Query cached data by ID and type |
bin/context
Collects context from three sources and stores it in .playwright-skill/cache/:
playwright-cli snapshot — accessibility tree (YAML)
playwright-cli console / playwright-cli network — native browser logs
playwright-cli run-code — page URL, title, HTML, cookies, injected captures
Outputs a TrimmedResponse (~200 tokens) with:
pageState — URL, title, auth status, error flag
cacheRef.id — reference ID to retrieve full context later
cacheRef.available — list of available data types
bin/context
bin/context --screenshot
bin/inject-capture
Patches console.*, window.fetch, and XMLHttpRequest in the browser to capture events in window.__capturedConsole and window.__capturedRequests. These are merged with playwright-layer captures by bin/context.
Idempotent — safe to run multiple times. Only captures events after injection.
bin/inject-capture
bin/cache-query
Retrieves full context stored by bin/context.
bin/cache-query query <id> snapshot
bin/cache-query query <id> html
bin/cache-query query <id> console
bin/cache-query query <id> network
bin/cache-query query <id> screenshot
bin/cache-query list
bin/cache-query stats
bin/cache-query clear
bin/cache-query clear <id>
Typical QA Workflow
bin/open --headed
playwright-cli goto http://localhost:8000
bin/auth-load <profile>
bin/inject-capture
playwright-cli click e5
playwright-cli fill e7 "search term"
playwright-cli press Enter
bin/context --screenshot
bin/cache-query query <id> console
bin/cache-query query <id> network
bin/cache-query query <id> snapshot
bin/cache-query query <id> screenshot
bin/close
Multi-project / parallel agent note: When running under Claude Code, each agent automatically gets an isolated session via CLAUDE_SESSION_ID. Direct playwright-cli commands (goto, click, fill, etc.) work as-is when only one session is open. If multiple sessions are active, prefix with -s=<session> — e.g. playwright-cli -s=my-project-a1b2c3d4 goto <url>. The session name is printed when you run bin/open.
Reading Console Errors
bin/cache-query query <id> console | python3 -c "
import sys, json
msgs = json.load(sys.stdin)
errors = [m for m in msgs if m['type'] == 'error']
for e in errors:
print(e['text'])
"