Playwright CLI for Codex
Operate the browser through an evidence loop: preflight → choose session → observe → act → verify → record → clean up. The page, network, console, and generated artifacts are ground truth; command memory is not.
1. Preflight
Run these before the first browser action in a task:
$cliVersion = playwright-cli --version
playwright-cli --help
Version and help are read-only. playwright-cli list is not a pure preflight: it probes registered sessions and prunes registry entries it cannot reconnect to. Use it only when session inventory is needed, and do not describe that check as read-only.
If playwright-cli is missing, check for the official local CLI before installing anything:
npx --no-install playwright-cli --version
npx --no-install playwright-cli --help
Do not mistake a project's playwright or @playwright/test test runner for the standalone playwright-cli binary. If neither the global nor local binary exists, read references/installation.md. Installation changes the user's environment, so obtain authorization before installing Node.js, @playwright/cli, a managed browser, or any browser extension.
For a command with parameters, consult live help instead of guessing:
playwright-cli --help open
playwright-cli --help requests
references/commands.md is a generated cache of the installed package's machine-readable help.json. Run scripts/export-command-reference.ps1 -Check when the package version changes; regenerate only when the check reports drift.
The installed package's README, official Skill, and every bundled topic guide are mirrored under references/official/. Check that snapshot too:
$playwrightGuide = '<absolute path of the loaded playwright-cli-guide directory>'
& "$playwrightGuide\scripts\sync-official-guides.ps1" -Check
Resolve that path from the location used to load this SKILL.md; substitute the real absolute path before executing and do not assume another user's Windows account name or Codex home directory.
Use references/coverage.md to route a task to the curated workflow and the corresponding official guide. The official snapshot is verbatim and may show generic POSIX shell examples; use references/windows-powershell.md for the actual Windows invocation.
2. Translate the user's browser intent
Treat these modes as distinct. The user's wording selects the mode; do not substitute one merely because it is also visible or authenticated.
| User intent | Required mode |
|---|---|
| "接管/控制/操作我已经打开或已经登录的 Chrome"; user expects to click the browser's native Allow prompt | attach --cdp=chrome |
| Same intent for Microsoft Edge | attach --cdp=msedge |
| "使用我已安装的 Playwright 扩展/Playwright MCP Bridge" | attach --extension=chrome |
| "新开一个我能看到操作的浏览器/有头模式" | open <url> --headed |
| Fresh isolated automation | open |
| Reuse a dedicated automation login across restarts | open --persistent or open --profile=<path> |
Diagnose a paused --debug=cli Playwright test |
attach <tw-session> |
Takeover contract: in this Skill, "接管已经打开的 Chrome" means connecting to that same running Chrome instance and its existing tabs through Chrome DevTools Protocol (CDP). It does not mean launching another visible browser, and it does not mean using an extension. Use this exact shape:
$browserSession = 'chrome-takeover-' + [guid]::NewGuid().ToString('N').Substring(0, 8)
playwright-cli "-s=$browserSession" attach --cdp=chrome
playwright-cli "-s=$browserSession" tab-list
playwright-cli "-s=$browserSession" snapshot
Before attachment, tell the user to open chrome://inspect/#remote-debugging in the Chrome instance they want controlled and enable Allow remote debugging for this browser instance. The approval is Chrome's native remote-debugging permission, not a Codex extension prompt. A successful takeover must expose the user's pre-existing tabs or expected logged-in page; a blank new browser is not evidence of success.
Use attach --extension=chrome only when the user explicitly requests the Playwright browser-extension path. If CDP attachment fails, report the exact error and check the native remote-debugging permission first. Switching to an extension is a new integration choice and requires the user's explicit agreement.
Read references/workflows.md for the full attach, verification, failure-recovery, and ownership procedure.
3. Choose the session deliberately
Use a semantic named session for concurrent or multi-step work:
$browserSession = 'gsc-audit-' + [guid]::NewGuid().ToString('N').Substring(0, 8)
playwright-cli "-s=$browserSession" open 'https://example.com' --headed
open and attach stop an existing session with the same name before starting the replacement. A semantic name is not proof of ownership: add a unique task suffix, record the final name, and never reuse a session name owned by another task. If the user explicitly wants to resume a known session, run playwright-cli list --json, disclose its stale-registry pruning behavior, and confirm the exact session before acting.
Attached browsers have external ownership. End them with detach, which leaves the user's browser running. End sessions created by open with close.
Read references/workflows.md for persistent state, test debugging, network diagnosis, tracing, video, and advanced run-code branches.
4. Observe before acting
Capture the current page and use its refs:
playwright-cli "-s=$browserSession" snapshot
playwright-cli "-s=$browserSession" find 'Sign in'
Target in this order:
- Snapshot ref such as
e15 - Semantic Playwright locator such as
getByRole('button', { name: 'Submit' }) - Stable test id or CSS selector when semantics are unavailable
Refresh the snapshot after navigation, DOM replacement, tab changes, dialogs, or major state transitions. Refs describe a snapshot, not a permanent identity.
For large pages, use partial or bounded observations:
playwright-cli "-s=$browserSession" snapshot --depth=4
playwright-cli "-s=$browserSession" snapshot e34
playwright-cli "-s=$browserSession" find --regex '/sign (in|up)/i'
Use eval for information absent from snapshots:
playwright-cli "-s=$browserSession" eval 'el => el.getAttribute("data-testid")' e15
playwright-cli "-s=$browserSession" --raw eval '() => location.href'
Use generate-locator when converting a proven interaction into Playwright test code.
5. Act with the narrowest command
Prefer the dedicated command that expresses the action:
playwright-cli "-s=$browserSession" click e15
playwright-cli "-s=$browserSession" fill e21 'user@example.com'
playwright-cli "-s=$browserSession" fill e22 'value' --submit
playwright-cli "-s=$browserSession" select e30 'option-value'
playwright-cli "-s=$browserSession" upload 'C:\absolute\path\document.pdf'
- Use
fillto replace an input value. - Use
typeor keyboard commands when sequential key behavior matters. - Use
dropfor external drag data or files; usedragbetween two page elements. - Use
run-codeonly when no dedicated command expresses the task or when a multi-step atomic operation is safer. Its input must be one function expression; imports,require, and hidden side effects do not belong there.
PowerShell quoting, URLs containing &, JSON bodies, arrays, repeatable flags, paths, and raw output are covered in references/windows-powershell.md.
6. Verify the outcome
Match verification to the claim:
- Navigation: URL, title, and a fresh snapshot
- Form or UI action: resulting DOM state, visible message, value, checked state, or tab
- API-backed action:
requests, then the specificrequest/response command - Rendering: screenshot plus DOM or computed value when visual evidence alone is ambiguous
- Client failure:
console, request status/body, and trace when needed - Persistence: close/reopen or reload, then inspect storage and page state
Examples:
playwright-cli "-s=$browserSession" snapshot
playwright-cli "-s=$browserSession" --raw eval '() => location.href'
playwright-cli "-s=$browserSession" console warning
playwright-cli "-s=$browserSession" requests --filter '/api/'
playwright-cli "-s=$browserSession" request 3
Do not infer success from a click command returning successfully. Verify the user-visible or system-visible result.
7. Capture proportionate evidence
Use the smallest artifact that proves the result:
- Snapshot for structure and accessible state
- Screenshot for layout, clipping, responsive behavior, or visual handoff
- Network details for request/response claims
- Trace for multi-step debugging
- Video for a user-facing demonstration or temporal behavior
playwright-cli "-s=$browserSession" screenshot --filename='evidence.png' --full-page
playwright-cli "-s=$browserSession" tracing-start
playwright-cli "-s=$browserSession" tracing-stop
Use --raw for a bare result and --json for structured command responses. Save artifacts under the task or project output directory, not an unexplained working-directory default.
8. Respect side effects and secrets
- Treat form submissions, messages, purchases, indexing requests, deletes, and account changes as external writes. Perform only actions authorized by the user's request and confirm the resulting state.
- Treat storage-state files, cookies, request headers, and response bodies as potentially sensitive. Keep them out of Git and user-visible logs unless needed.
- Treat snapshots, screenshots, PDFs, traces, videos, downloads, and dashboard annotations as potentially sensitive too; they can contain credentials, personal data, DOM, headers, bodies, or account state. Put them in a deliberate task-owned output directory, keep them out of Git, and apply an explicit retention decision.
- Restrict file uploads to the intended files.
allowUnrestrictedFileAccessis a security-sensitive configuration branch. - Restore temporary routes and offline state before handoff.
- Use
delete-dataonly for a confirmed session whose profile the user wants removed. - Use
kill-allonly for stale or zombie Playwright processes after safer targeted closure fails.
9. Clean up according to ownership
For a session created by this task:
playwright-cli "-s=$browserSession" close
For an attached external browser:
playwright-cli "-s=$browserSession" detach
Also stop active tracing/video, remove temporary routes, and restore network state. Preserve a persistent profile or storage state when reuse was part of the task; report its location.
If this task started the detached Playwright dashboard with plain playwright-cli show, stop that dashboard with playwright-cli show --kill only after confirming it is task-owned and not shared. show --annotate operates on the selected session and does not create that detached dashboard daemon.
When the user explicitly asks for Playwright CLI, stay on the Playwright CLI path. Missing CLI is an installation/troubleshooting branch, not permission to invoke Codex Desktop Chrome control, a browser plugin, Computer Use, or node_repl. If the official CLI has a demonstrated limitation, report it and obtain agreement before changing browser-control mechanisms.
Reference routing
references/commands.md: every command, argument, and flag from installedhelp.jsonreferences/installation.md: clean-machine setup, verification, PATH recovery, and when a managed browser is or is not requiredreferences/coverage.md: coverage proof and topic-to-reference routingreferences/configuration.md: JSON configuration and environment variablesreferences/windows-powershell.md: quoting, paths, output capture, repeatable flags, and process handlingreferences/workflows.md: sessions, attach, storage, network, mocking, tests, trace, video, andrun-codereferences/official/README.md: verbatim installed-package feature and configuration guidereferences/official/upstream-playwright-cli.mdandreferences/official/references/: verbatim official Skill snapshot as ordinary reference material, plus every bundled task guidereferences/upstream.md: official source, version, license, and cache policy