When I started building Dramaturg, I just wanted a quick way to run Playwright commands without setting up a Node.js project. Type click "Submit", see it happen. Simple.
But then I kept going. And going. And now it has a full JS debugger — breakpoints, step-through, scope inspection — all running inside a Chrome side panel.
What is Dramaturg?
It's a Chrome extension that gives you a Playwright-powered REPL directly in your browser. No backend server, no IDE, no npx playwright test. Just open the side panel and start automating.
It has two input modes:
Keyword mode (.pw) — human-friendly commands:
goto https://demo.playwright.dev/todomvc
fill "What needs to be done?" "Buy groceries"
verify-text "1 item left"
JavaScript mode — full Playwright API:
await page.goto('https://example.com');
const title = await page.title();
console.log(title);
await expect(page.locator('h1')).toBeVisible();
Both modes run against your real browser session — cookies, auth, extensions, everything. This is the biggest difference from tools like Playwright MCP that launch isolated browser instances.
The debugger that nobody asked for (but I needed)
Once I had JS mode working, I found myself writing multi-line scripts and wanting to step through them. So I built a debugger.
Set breakpoints by clicking the gutter. Hit Debug instead of Run. The script pauses, and you get:
- Step Over / Step Into / Step Out / Continue — floating toolbar, just like VS Code
- Variables tab — auto-expands local, block, closure, and script scope variables
- Expandable object tree — arrays, objects, Maps, Promises — drill into any value
All powered by Chrome's Debugger API (CDP). The extension creates a debug session against its own service worker, sets breakpoints, and catches Debugger.paused events. No external debugger needed.
Here's what it looks like paused inside a function:
function greet(name) {
const message = "Hello, " + name + "!"; // ← breakpoint here
console.log(message);
return message.length;
}
const result = greet("World");
The Variables tab shows:
▾ Local
name: "World"
message: "Hello, World!"
▾ Script
result: 13
How it works under the hood
The extension runs playwright-crx in a service worker — this is a Chromium-specific build of Playwright that uses chrome.debugger instead of CDP WebSocket. Commands execute directly in the browser process.
For the debugger, the flow is:
- User clicks Debug → extension creates a CDP debug session targeting its own service worker
- Breakpoints are set via
Debugger.setBreakpoint - Code executes via
Runtime.evaluatewithawaitPromise: true -
Debugger.pausedevent fires → extension readscallFrames[0].scopeChain - Scope variables displayed in the Variables tab via
Runtime.getProperties
The key trick: the script runs in the service worker context, where page, expect, and crxApp are globals. So await page.click('button') actually drives the attached browser tab.
Console — Chrome DevTools, but for Playwright
The console works like Chrome DevTools — type a command, see the result inline. But instead of raw JavaScript, you can use Playwright's keyword commands.
> snapshot
Returns the page's accessibility tree as an expandable tree view — click to drill into nodes, no more scrolling through walls of text.
> goto https://example.com
Navigated to "Example Domain"
> await page.title()
"Example Domain"
> await page.evaluate(() => document.querySelectorAll('a').length)
1
The console auto-detects what you're typing:
-
click "Submit"→ runs as a.pwkeyword command -
await page.locator('h1').textContent()→ runs as Playwright API
Results show as expandable object trees — arrays, objects, Maps, Promises — just like Chrome DevTools. Click to expand nested properties.
Recorder — watch commands write themselves
Click the Record button, then interact with the page normally. Every click, form fill, and navigation is captured and written to the editor in real time.
Recording works in both modes:
- In
.pwmode → generates keyword commands:click "Submit",fill "Email" "test@example.com" - In JS mode → generates Playwright API:
await page.getByRole('button', { name: 'Submit' }).click()
Stop recording, clean up the script if needed, hit Run. Instant test.
Pick Element — point and click locators
Finding the right selector is half the battle. Click the Pick Element button (crosshair icon), then hover over any element on the page. You'll see:
- A blue highlight overlay around the element
Click to pick it. The console shows locators and assertions in both formats:
locator
js: await page.getByRole('link', { name: 'Get started' }).highlight();
pw: highlight link "Get started"
assertion
js: await expect(page.getByRole('link', { name: 'Get started' })).toContainText('Get started');
pw: verify-element link "Get started"
Copy whichever format you need — ready to paste into your script or test.
More features
-
Snapshot tree —
snapshotrenders the accessibility tree as an expandable tree view (not raw text). -
Autocompletion — ghost-text suggestions for both
.pwcommands and Playwright API methods. - Side panel or popup — opens as a side panel by default; switch to popup window in Options if you prefer a floating window.
-
MCP server — pair with
@playwright-repl/mcpto let Claude or other AI agents drive your browser.
Why not just use Playwright Test?
You absolutely should for production tests. Dramaturg is for the exploration phase:
- Quickly test a selector before putting it in your test suite
- Debug a flaky test by stepping through it interactively
- Record a user flow and convert it to a test
- Let an AI agent generate and run tests on your real session
Think of it as Chrome DevTools Console, but with Playwright superpowers.
Try it
- Chrome Web Store: Dramaturg
- GitHub: playwright-repl
-
CLI:
npm install -g playwright-repl
Top comments (0)