con un clic
playwright-skill
Browser automation for web projects using playwright-cli
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
Browser automation for web projects using playwright-cli
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
Architectural compliance and code quality rules for Node.js + TypeScript projects (Vue 3 frontend, Express + Socket.IO backend). Provides systematic review criteria for security, code organization, error handling, and project-specific conventions. Use when auditing code quality.
Mutation testing strategies and test-improvement patterns for TypeScript projects using Stryker Mutator with a Vitest runner. Provides guidance on interpreting mutation reports and improving tests to achieve higher kill rates. Use when analyzing mutation testing results.
Risk identification and test prioritization framework for Node.js + TypeScript projects (Vue 3 + Express + Socket.IO). Provides systematic approach to identifying potential issues and prioritizing testing efforts. Use when analyzing features for QA review.
Parses specification documents (EARS, Given-When-Then, SHALL clauses, user stories, tasks) from multiple layouts into a structured intermediate representation, then maps requirements to tests bidirectionally. Use when verifying implementation against a spec, auditing requirement coverage, or computing a traceability matrix.
Vitest testing patterns and templates for Node.js + TypeScript projects (Express backend, Vue 3 frontend). Provides comprehensive test writing guidance for unit, integration, component, and property-based tests. Use when generating or improving tests for the harness-visualizer.
Indexes, searches, and injects project spec files as agent memory. Use when starting work on a spec-driven project, searching for relevant specs, recalling past design decisions, archiving spec changes, or checking spec history. Supports both directory-style specs (specs/<name>/requirements.md|design.md|tasks.md) and flat-style specs (.claude/specs/active/<name>.md).
| 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) |
Browser automation using playwright-cli (Microsoft's official Playwright CLI). No daemon management required — the browser starts and stops automatically.
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 # see all open sessions
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
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.
playwright-cli goto <url> # navigate to URL
playwright-cli go-back # browser back
playwright-cli go-forward # browser forward
playwright-cli reload # reload page
playwright-cli click <ref> # click element
playwright-cli fill <ref> <value> # fill input (clears first)
playwright-cli type <text> # type text (appends)
playwright-cli press <key> # press key: Enter, Tab, Escape, Control+A
playwright-cli hover <ref> # hover to reveal menus/tooltips
playwright-cli select <ref> <val> # select dropdown option
playwright-cli snapshot # capture accessibility tree
playwright-cli screenshot # take screenshot
playwright-cli dialog-accept # accept alert/confirm/prompt
playwright-cli dialog-dismiss # dismiss dialog
bin/close # close browser session + clean up session file (preferred)
playwright-cli kill-all # force-kill all playwright-cli daemons (use when stuck)
playwright-cli list # list all open sessions
playwright-cli run-code '<async page => { }>' # run arbitrary Playwright JS
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.
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> # profile names from skill/worktrees.json
Restore on a new session:
bin/open --headed
playwright-cli goto <baseUrl> # baseUrl from skill/worktrees.json
bin/auth-load <profile-name>
playwright-cli goto <baseUrl>/dashboard
Profiles are stored in .playwright-skill/auth/ and gitignored.
| 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 / framework component not clickable | Use bin/click-css with a CSS selector |
| Action has no visible effect | Tail your server log for a swallowed exception (see §9) |
| Page blank or error after action | Tail your server log for a swallowed exception (see §9) |
| End of task cleanup | bin/close |
# Wait for a specific element
playwright-cli run-code 'await page.waitForSelector(".loading-complete")'
# Dispatch a framework event (example: a global pub/sub or framework bus)
playwright-cli run-code 'await page.evaluate(() => window.dispatchEvent(new CustomEvent("refresh")))'
# Scroll to bottom
playwright-cli run-code 'await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight))'
# Get element count
playwright-cli run-code 'console.log(await page.locator("table tbody tr").count())'
Three tools integrate ResponseBuilder and CacheStore into the v2 skill, enabling rich page diagnostics.
| 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/contextCollects 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 logsplaywright-cli run-code — page URL, title, HTML, cookies, injected capturesOutputs a TrimmedResponse (~200 tokens) with:
pageState — URL, title, auth status, error flagcacheRef.id — reference ID to retrieve full context latercacheRef.available — list of available data typesbin/context # text/ARIA capture only
bin/context --screenshot # also capture PNG screenshot
bin/inject-capturePatches 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
# → {"success":true,"hasCapture":true}
bin/cache-queryRetrieves full context stored by bin/context.
bin/cache-query query <id> snapshot # accessibility tree YAML
bin/cache-query query <id> html # full page HTML
bin/cache-query query <id> console # console messages JSON
bin/cache-query query <id> network # network requests JSON
bin/cache-query query <id> screenshot # base64-encoded PNG
bin/cache-query list # JSON array of all cached entries
bin/cache-query stats # entry count, total size, max entries
bin/cache-query clear # clear all entries
bin/cache-query clear <id> # clear one entry
# 1. Start browser and navigate
bin/open --headed
playwright-cli goto http://localhost:8000
bin/auth-load <profile>
# 2. Inject browser-side capture (optional but recommended)
bin/inject-capture
# 3. Perform actions (click, fill, navigate...)
playwright-cli click e5
playwright-cli fill e7 "search term"
playwright-cli press Enter
# 4. Capture full context
bin/context --screenshot
# Read cacheRef.id from the TrimmedResponse output
# 5. Diagnose issues
bin/cache-query query <id> console # check for JS errors
bin/cache-query query <id> network # check API responses
bin/cache-query query <id> snapshot # review page structure
bin/cache-query query <id> screenshot # view page visually (base64 PNG)
# 6. Clean up
bin/close
Multi-project / parallel agent note: When running under Claude Code, each agent automatically gets an isolated session via
CLAUDE_SESSION_ID. Directplaywright-clicommands (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 runbin/open.
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'])
"
When a page action fails silently (form doesn't submit, page goes blank, modal doesn't respond), the cause is often a server-side exception that Playwright can't see. The framework's error page often renders HTML that the accessibility tree can't meaningfully parse.
Set PLAYWRIGHT_SERVER_LOG in your environment (or per-project worktrees.json notes) to the path of your server log, then use the patterns below. The default examples assume $PLAYWRIGHT_SERVER_LOG.
Quick check — last 30 lines of the log:
tail -30 "$PLAYWRIGHT_SERVER_LOG"
Search for recent exceptions today:
grep -A 5 "$(date +'%Y-%m-%d')" "$PLAYWRIGHT_SERVER_LOG" \
| grep -A 5 "Exception\|Error\|Traceback\|SQLSTATE" \
| tail -40
Read only new lines since a known size:
# Before testing
wc -l "$PLAYWRIGHT_SERVER_LOG" # e.g., 1500 lines
# After a failure
tail -n +1501 "$PLAYWRIGHT_SERVER_LOG"
Drop a marker into the log so you can easily find new exceptions afterward:
echo "[$(date +'%Y-%m-%d %H:%M:%S')] QA-TEST-START" >> "$PLAYWRIGHT_SERVER_LOG"
# ... run tests ...
grep -A 9999 "QA-TEST-START" "$PLAYWRIGHT_SERVER_LOG" | tail -50
The patterns vary by framework — recognize the family rather than the exact string. Some recurring ones:
| Log Pattern | Likely Cause |
|---|---|
SQLSTATE[23505] / UNIQUE constraint failed | Unique constraint violation (duplicate insert) |
SQLSTATE[42703] / column ... does not exist | Missing migration |
SQLSTATE[23502] / NOT NULL constraint | Missing required field |
undefined method / NoMethodError / AttributeError | Method/attribute doesn't exist on model/class |
Class "..." not found / NameError / ImportError | Missing import or wrong namespace |
null / None / nil property access | Missing related record on an optional relationship |
Method Not Allowed / 405 | Wrong HTTP verb (GET vs POST) |
If PLAYWRIGHT_SERVER_LOG is unset, try the standard path for your stack:
| Framework | Path |
|---|---|
| Laravel | storage/logs/laravel.log |
| Rails | log/development.log |
| Django (DEBUG) | console — pipe it to a file |
| Express / Node | stdout — pipe to a file or use pino/winston sink |
| Symfony | var/log/dev.log |
| Phoenix | _build/dev/lib/<app>/ebin console — pipe to a file |