@playwright/cliSnapshots save to disk and every tool is on by default: network mocking, storage, tracing, test debugging.
$ playwright-cli route "**/*.jpg"
$ playwright-cli tracing-start
$ playwright-cli attach tw-abcdefSee why coding agents work better with `@playwright/cli` than with MCP, and run your first agent-driven browser session.
Playwright ships two ways to connect to the agent world: an MCP server and a CLI with a skill.
For a while, picking one was easy. In early 2026 the Playwright team made the case for the CLI, and the deciding factor was token usage. The same task could cost roughly 4× more tokens when using the MCP server. That number is outdated because two things changed:
These days, playwright-cli commands call the MCP tools under the hood (click runs browser_click). I compared the token consumption by running the same task three times:
@playwright/cliSnapshots save to disk and every tool is on by default: network mocking, storage, tracing, test debugging.
$ playwright-cli route "**/*.jpg"
$ playwright-cli tracing-start
$ playwright-cli attach tw-abcdef@playwright/mcpSnapshots save to disk, too. But only the core browsing tools are on. The testing toolbox is opt-in.
$ npx @playwright/mcp \
--caps=devtools,network,storage
# core tools only unless you opt inToken usage is a tie (here's the full comparison), so features make the difference. And even with a shared backend, the two don't have feature parity:
--caps.I recommend @playwright/cli if you use coding agents. If you're building your own agentic loop or your agent has no shell, MCP is still the way to go.
That's why we'll focus on the CLI and how you can use it to automate your daily Playwright tasks.
Three pieces make this work:
page.* call.Let's have a look at how these components work together.
You installed @playwright/cli and the skill in the prep lesson.
This lesson assumes @playwright/cli 0.1.19 or newer. Run playwright-cli --version to confirm. If you're behind, run npm install -g @playwright/cli@latest and re-run playwright-cli install in your project.
Also make sure that you have the CLI skills installed for your agent. Run playwright-cli install --skills to install them.
Open a terminal in your workshop project and point it at the workshop store:
$ playwright-cli open https://www.playwright-workshop.online/
### Browser `default` opened with pid 15970.
### Ran Playwright code
```js
await page.goto('https://www.playwright-workshop.online/');
```
### Page
- Page URL: https://www.playwright-workshop.online/
- Page Title: PWT Workshop
### Snapshot
- [Snapshot](.playwright-cli/page-2026-09-18T14-46-06-540Z.yml)
### Events
- New console entries: .playwright-cli/console-2026-09-18T14-46-05-785Z.log#L1
The CLI prints a few lines: the browser pid, the equivalent page.goto() call, the page URL and title, and a path to a snapshot file on disk. That's almost no tokens at all.
If you (or your agent) want to understand the page structure, ask the CLI for a snapshot. Call snapshot to print the YAML accessibility snapshot inline instead of saving it to disk:
$ playwright-cli snapshot
### Page
- Page URL: https://www.playwright-workshop.online/
- Page Title: PWT Workshop
### Snapshot
```yaml
- generic [active] [ref=e1]:
- navigation "Main" [ref=e2]:
- generic [ref=e3]:
- generic [ref=e4]:
- link "Go to home" [ref=e5] [cursor=pointer]:
- /url: /
- img "pwt logo" [ref=e7]
- list [ref=e8]:
...
...
The YAML lists every interactive element with a stable ref like e3, e15, e21. That's how the CLI addresses elements without dumping the full DOM into your context. Pick a ref from the snapshot and click it:
$ playwright-cli click e34
### Ran Playwright code
```js
await page.getByTestId('hero-product-grid').getByRole('link', { name: 'The Collection Snowboard:' }).click();
```
### Page
- Page URL: https://www.playwright-workshop.online/product/the-collection-snowboard-liquid/
- Page Title: The Collection Snowboard: Liquid | PWT Workshop
### Snapshot
- [Snapshot](.playwright-cli/page-2026-09-18T14-47-43-103Z.yml)
The CLI returns the action it ran as Playwright code, the resulting page context and snapshot.
Every CLI command prints the equivalent page.* call. Drive a flow once and you have the body of a test, line by line. Close the browser when you're done:
$ playwright-cli close
Browser 'default' closed
Now let the agent drive. Open your coding agent in your workshop project and prompt:
Open https://www.playwright-workshop.online/, search for snowboard, click the first snowboard
you can find. Use playwright-cli and run the CLI in --headed mode so I can
watch along.
Watch what happens. The agent reads .claude/skills/playwright-cli/SKILL.md first to learn the commands and the ref system. Then it runs the same loop you just did by hand: open, snapshot, fill, click.
The skill bundles task-specific reference docs
The playwright-cli skill covers the CLI commands, but also ships additional references/ docs. The agent pulls these in on demand when the task calls for it:
references/playwright-tests.md for running and debugging Playwright testsreferences/test-generation.md for generating tests from a recorded sessionBrowse .claude/skills/playwright-cli/references/ to see the full set and adjust your prompt so that the agent picks up these docs.
Every response carries the same two things you saw in your terminal: the Playwright code that just ran and the state of the resulting page. For the search flow, the agent collected these lines along the way:
await page.goto("https://www.playwright-workshop.online/");
await page
.getByRole("textbox", { name: "Search for products..." })
.fill("snowboard");
await page.getByRole("button", { name: "Search" }).click();
await page
.getByRole("link", { name: "The Collection Snowboard: Oxygen" })
.click();
That's everything an agent needs to write a Playwright test script. The printed code covers the actions, and the snapshots tell it what to assert on.
Send the agent through the full checkout
Could you just prompt the agent to complete the entire checkout flow for you? Could it be a conversation? Let's find out!
A few things to play with:
.playwright-cli/ and count the snapshot files. Each one is page structure the agent could have loaded into its context but didn't.Tell your agent to close the browser (playwright-cli close) when you're done.