I've been using playwright-cli — Microsoft's command-line tool that gives AI agents browser automation skills via the Playwright MCP daemon. It's brilliant for agents: one command, one process, one result. But for humans, every command spawns a brand-new Node.js process — connect to the daemon, send one message, disconnect, exit. That's 50–100ms overhead per command.
I wanted something faster. Something interactive. Something designed for humans instead of AI agents — a persistent session with instant feedback.
So I built playwright-repl — a REPL that reuses playwright-cli's command vocabulary and MCP daemon architecture, but replaces the one-shot client with a persistent socket connection. Same wire protocol, same daemon, same browser commands — just a better interface for interactive use.
What does it look like?
$ playwright-repl --headed
pw> goto https://demo.playwright.dev/todomvc/
pw> fill "What needs to be done?" "Buy groceries"
pw> press Enter
pw> fill "What needs to be done?" "Write tests"
pw> press Enter
pw> check "Buy groceries"
pw> verify-text "1 item left"
✓ Text "1 item left" is visible
No imports. No async/await. No page.locator(). Just type what you want the browser to do.
Why not just use Playwright's codegen?
Playwright's codegen is great for generating test code. But sometimes you don't want code — you want to explore.
- Debugging a login flow? Type commands and see what happens.
- Building a demo? Record the session and replay it.
- Running a smoke test in CI? Pipe a
.pwfile and check the exit code.
playwright-repl sits between "clicking around manually" and "writing a full test suite." It's the exploratory middle ground.
Text locators: just say what you see
The thing I'm most proud of is text locators. Instead of inspecting elements for CSS selectors or waiting for a snapshot to get element refs, you just use the text you see on screen:
pw> click "Get Started"
pw> fill "Email" "test@example.com"
pw> fill "Password" "secret123"
pw> click "Sign In"
pw> check "Remember me"
pw> select "Country" "Japan"
Under the hood, it tries multiple strategies — getByText, getByRole('button'), getByRole('link'), getByLabel, getByPlaceholder — with a fallback chain. Case differences don't matter because role matching is case-insensitive.
You can also use element refs from snapshot output if you prefer precision:
pw> snapshot
- heading "todos" [ref=e1]
- textbox "What needs to be done?" [ref=e8]
pw> click e8
pw> fill e8 "Buy groceries"
Record and replay
This is where it gets really useful. Record your browser session as a .pw file:
pw> .record smoke-test
⏺ Recording to smoke-test.pw
pw> goto https://demo.playwright.dev/todomvc/
pw> fill "What needs to be done?" "Buy groceries"
pw> press Enter
pw> verify-text "1 item left"
pw> .save
✓ Saved 4 commands to smoke-test.pw
The .pw file is just plain text:
# CI smoke test
goto https://demo.playwright.dev/todomvc/
fill "What needs to be done?" "Buy groceries"
press Enter
verify-text "1 item left"
Replay it any time:
# Headless (CI mode)
playwright-repl --replay smoke-test.pw --silent
# With a visible browser
playwright-repl --replay smoke-test.pw --headed
# Step through interactively
playwright-repl --replay smoke-test.pw --step --headed
These .pw files are human-readable, diffable, and version-controllable. Commit them alongside your code. Run them in CI. Share them with teammates who don't write JavaScript.
Assertions built in
No test framework needed. Verify state inline:
pw> verify-text "1 item left"
✓ Text "1 item left" is visible
pw> verify-element heading "todos"
✓ Element heading "todos" is visible
pw> verify-value "Email" "test@example.com"
✓ Value matches
If an assertion fails, you get a clear error — and in replay mode, the process exits with code 1. That's all CI needs.
50+ commands, short aliases
Every command has a short alias for quick typing:
| You type | It does |
|---|---|
g https://example.com |
Navigate to URL |
s |
Accessibility tree snapshot |
c e5 |
Click element ref e5 |
f "Email" "me@test.com" |
Fill a form field |
p Enter |
Press a key |
ss |
Take a screenshot |
vt "hello" |
Verify text is visible |
back |
Go back in history |
The full list includes interaction (click, fill, type, press, hover, drag), inspection (snapshot, screenshot, eval, console, network), storage (cookies, localStorage, sessionStorage), tabs, dialogs, network routing, and more.
How it works under the hood
playwright-repl stands on the shoulders of playwright-cli and the Playwright MCP architecture. It reuses:
-
The MCP daemon from
playwright@1.59+— browser launch, CDP communication, all 50+ tool handlers -
The command vocabulary from playwright-cli —
click,fill,snapshot,screenshot, etc. - The wire protocol — newline-delimited JSON over Unix socket / Windows named pipe
The REPL is just a thin, persistent client that:
- Parses your input (alias resolution + argument parsing)
- Sends a JSON message over the socket (identical format to playwright-cli)
- Displays the result
Because the socket stays open, there's zero startup overhead per command. The daemon doesn't care whether the message came from playwright-cli, the REPL, or an AI agent — the wire messages are identical. playwright-repl adds the human-friendly layer on top: text locators, recording, replay, assertions, and aliases.
Use it in CI
# .github/workflows/smoke.yml
jobs:
smoke-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx playwright install chromium
- run: npx playwright-repl --replay tests/smoke.pw --silent
The --silent flag suppresses the banner. The process exits 0 on success, 1 on failure. That's it.
Get started
npm install -g playwright-repl
npx playwright install
playwright-repl --headed
Then type goto https://demo.playwright.dev/todomvc/ and start exploring.
Chrome DevTools extension
We're also building playwright-repl-extension — a Chrome DevTools panel that brings the same REPL experience into the browser. Open DevTools, switch to the "Playwright REPL" tab, and type commands directly. It also includes an action recorder that captures your clicks and form fills as .pw commands.
The extension is standalone (no Node.js daemon needed) — it uses Chrome's chrome.debugger API to drive the inspected page via CDP.
- GitHub: stevez/playwright-repl-extension
Links
- npm: playwright-repl
- GitHub: stevez/playwright-repl
- Chrome extension: stevez/playwright-repl-extension
- Inspired by: microsoft/playwright-cli
playwright-repl is MIT licensed and works on Linux, macOS, and Windows. Contributions welcome!

Top comments (0)