Skip to main content
/tayyab/portfolio — zsh
tayyab
TA
// dispatch.read --classified=false --access-level: public

Playwright CLI Debugger (--debug=cli): The 1.59 Feature Nobody Is Using Yet

April 10, 2026 EST. READ: 9 MIN #Quality Assurance

Of all the Playwright 1.59 additions, --debug=cli is the one nobody's writing about. The official notes mention it once, in the context of agent workflows: "coding agents can now run npx playwright test --debug=cli to attach and debug tests over playwright-cli." Most QA engineers skipped it because they don't have an AI agent driving their tests.

That's a missed opportunity. The CLI debugger is also the cleanest way to debug a failing test from a terminal — useful when you're SSH'd into a CI machine, when you're remote-pairing, or when you just don't want to launch the GUI Inspector for the third time today. After two weeks of using it on real projects, here's what it actually does and when I reach for it.

Table of Contents

What --debug=cli Actually Does

You start a test with the flag:

npx playwright test tests/checkout.spec.ts --debug=cli

The test runs to its first action and pauses, dropping you into an interactive prompt:

[playwright-cli] Paused at tests/checkout.spec.ts:8
  await page.goto('/checkout');

>

From the prompt you can step through the test, inspect locators, run arbitrary expressions in the page context, and see logs as they happen. No browser GUI needed.

Compare that to the GUI Inspector (--debug alone), which opens a window that hovers over your code editor. The Inspector is great for visual debugging. The CLI debugger is great for everything else.

When to Reach for the CLI Debugger Over the GUI Inspector

Three cases I now reach for CLI:

1. Tests on a remote machine

You SSH into a CI runner that just failed a test. The runner doesn't have a display. The Inspector won't help. --debug=cli works perfectly over SSH.

2. When you don't want to leave the terminal

If you're already in tmux/Vim/Emacs flow, alt-tabbing to the Inspector breaks concentration. The CLI debugger keeps you in the terminal.

3. Scripted debugging sessions

The CLI debugger is, well, a CLI. You can pipe commands to it, save sessions, replay them. The Inspector is a GUI; you can't automate its workflow.

The Commands That Matter

The most-used commands in the prompt:

CommandWhat it does
n or nextStep over the next action
c or continueContinue until next pause/breakpoint/end
page.url()Run a Playwright expression in the test context
locator.count()Run any locator method inline
locate <text>Search the page for elements containing text
screenshotSave a PNG of current state
traceDump the current trace to disk
varsList variables in current scope
q or quitExit and end the test

Sample session:

[playwright-cli] Paused at tests/checkout.spec.ts:14
  await page.getByRole('button', { name: 'Pay' }).click();

> locate Pay
Found 2 elements:
  1. button[role="button"][aria-label="Pay"] @ /checkout
  2. div.help-text:has-text("Pay safely with...") @ /checkout

> page.getByRole('button', { name: 'Pay' }).count()
1

> n
[playwright-cli] Stepped to tests/checkout.spec.ts:15
  await expect(page).toHaveURL(/\/thank-you/);

> page.url()
'http://localhost:3000/checkout?error=card_declined'

> q

That session just diagnosed the bug: the Pay button click submitted, but the response was a decline, not a success. The redirect didn't fire. Took 30 seconds in the CLI debugger versus 5 minutes in the trace viewer.

Scripted Debugging: The Pattern AI Agents Use

The reason 1.59 shipped this is that AI agents need a way to debug failing tests programmatically. The healer agent (see my agents post) attaches via the CLI debugger, runs commands, reads outputs, and decides what to patch.

You can use the same pattern manually. Save a debug script:

# debug-checkout.txt
locate Pay
page.getByRole('button', { name: 'Pay' }).count()
n
page.url()
screenshot
q

Pipe it in:

npx playwright test tests/checkout.spec.ts --debug=cli < debug-checkout.txt

The session runs non-interactively, dumps the output, exits. Useful for: "every time this test fails, run this diagnostic script" — wire it into your CI's failure-handling step.

Debugging a Failed CI Run Remotely

This is the workflow I use most. A test fails in GitHub Actions. The trace viewer is helpful but I want to actually run a few commands against the failing state.

Steps:

  1. SSH into the runner (Actions has action-tmate for this).
  2. Navigate to the failed test directory.
  3. Re-run with --debug=cli.
  4. Step through to the failure point.
  5. Inspect locators, page state, network state.
  6. Hypothesize the cause, test the hypothesis with another command.
  7. Exit, fix the bug, push.

Total time on the runner: usually under 10 minutes. With the GUI Inspector this workflow is impossible without forwarding X11 (don't bother).

Difference vs PWDEBUG=1

PWDEBUG=1 opens the GUI Inspector. --debug=cli opens the terminal debugger. They're alternative entry points to the same underlying debugging system; pick based on environment:

  • Local dev with GUI: PWDEBUG=1
  • SSH/CI/headless: --debug=cli
  • Scripted/automated: --debug=cli with input redirection

You can use both in the same project. They're not mutually exclusive.

FAQs

Does this work in headed and headless modes?

Both. The CLI debugger doesn't care about browser visibility — it pauses execution and lets you inspect either way.

Can I set breakpoints at specific lines?

Yes — await page.pause() in your test code creates a breakpoint that the CLI debugger respects (just like the GUI Inspector).

Does it work with multiple workers?

Run with --workers=1 when debugging. Multiple workers + interactive debugger don't compose.

Can I see network activity?

Yes — page.requests() shows the request log up to the current point. page.responses() shows responses.

What about console logs from the page?

Type console in the prompt to see captured console messages from the page.

Can I evaluate JavaScript in the page?

page.evaluate(() => window.someGlobal) works — same syntax as in test code, evaluated against the live page.

Does it integrate with the trace viewer?

Yes — trace command saves the current state to a trace file you can open in the viewer. Useful for sharing the state with a teammate.

What about IDE integration?

VS Code's Playwright extension has its own debug protocol that works with breakpoints in the editor. The CLI debugger is for terminal-first workflows; IDE users will mostly use the extension.

Can I use this in CI to gather diagnostic info on every failure?

Yes. Write a debug script that captures the diagnostic info you care about, run it conditionally on test failure, attach the output to your CI artifacts. Cleaner than just trace files because you can include any expression you want.

Will the CLI debugger be deprecated when the agents mature?

Unlikely. The agents use it as their backbone. As long as agents are part of Playwright, the CLI debugger stays.

Wrap-Up

The CLI debugger is one of those features that quietly changes your workflow if you let it. It's not a replacement for the trace viewer or the GUI Inspector — it's a third option that fits the gap they don't cover. For terminal-first debugging, remote CI sessions, and scripted diagnostics, it's now my default.

If your team is exploring 1.59's features and wants help wiring them into your debug workflow, that's part of what I cover in framework engagements. Or book a free call.

Related reading:

Tayyab Akmal
// author

Tayyab Akmal

AI & QA Automation Engineer

6 years of catching critical bugs in fintech, e-commerce, and SaaS — then building the Playwright and Selenium automation that prevents them from shipping again.

// feedback_channel

FOUND THIS USEFUL?

Share your thoughts or let's discuss automation testing strategies.

→ Start Conversation
Available for hire