Let your AI agent capture its changes with the Playwright CLI
A picture is worth a thousand words, also when you're reviewing a pull request. In our project, the coding agent uses the Playwright CLI to record UI changes, verify them, and attach them to the pull request.
The ideas and experience in this post are my own. AI helped with the writing and the examples, and I reviewed and edited the article before publishing.
Agents write code faster than we can review it. In our project, most pull requests are now opened by an agent. The diff helps us review the implementation. To check the behavior, someone still had to pull the branch locally, start the application, and click through the flow. Even with a preview environment, the reviewer still has to click through the flow manually to see the result.
We moved that step to the agent. When a change affects the UI, the agent starts the application, records the flow, and captures screenshots of key states. It inspects these captures before presenting them to the developer and attaching them to the pull request.
In this blog post, I share why we're doing this, how the Playwright CLI makes it possible, and what it looks like in practice.
Why
Our pull request template has a "Proof it works" section, where the author shows how they verified the change with screenshots and recordings. This gives reviewers something concrete to check and encourages authors to review their own work first.
For UI changes, a screenshot says more than a paragraph claiming that the change works, and it's also more fun. The reviewer can see the result at a glance, without having to imagine it from a description or run the application.
That lets the reviewer focus on the change: does it do what was asked, does it look right, and what needs a closer look?
At first, we only asked for screenshots. We later added recordings to show what happens between states: what was clicked, what appeared, and in what order. Recordings expose bugs that a screenshot can miss, like jumping focus, a flash of empty content, or a dialog that doesn't show. They also give reviewers more context and make entire flows easier to share.
The captures also help the agent catch its own mistakes. They can reveal issues that tests miss, even when all tests are green. We now require the agent to inspect every screenshot before presenting it, so it can fix these issues before review.
This is the same division of work that I described in Keep Agentic AI Simple: the agent implements, and the team verifies. The captures make the verification cheaper for the team, and keep the agent honest. As a bonus, the recordings also give us something concrete to show to stakeholders, which ties in with Sprint Zero is about building momentum.
Playwright CLI
I'm a big fan of Playwright. The Playwright CLI makes this workflow practical: it's built for coding agents, drives its own browser, and returns compact text that helps the agent understand what happened after each action.
The CLI can also attach to a browser that's already running, such as your own Chrome or Edge, through the Playwright extension or Chrome DevTools Protocol (CDP). It can read console messages, inspect network requests, and work with cookies and local and session storage. That makes it useful for debugging a failing flow or mocking an API response with the route command too.
In Vibe testing with Playwright, I explored the Playwright MCP server. These days, I prefer the CLI. As I mentioned in Keep Agentic AI Simple, MCP servers bloat the agent's context window, while a CLI tool with a skill only loads what's needed. The agent already knows its way around CLI tools, which also makes the workflow faster.
Installation
We install the CLI as a development dependency, so every developer and every agent uses the same version:
pnpm-D
The package also ships with an Agent Skill that teaches the agent how to use its commands. Install it in the repository with:
pnpm--skills
This command installs the skill instructions and reference guides locally in your repository, so supported agents can discover and load them.
Example
Let's try this with the TodoMVC demo. We'll record a short flow using the same steps our agent follows: start recording before the first step, add a callout for each action, introduce each step with a chapter card, and take a screenshot at the end of each step.
The video commands below use the Screencast API to record the agent's browser interactions.
pnpmpnpm--size=1280x720pnpmpnpm--description=pnpmpnpm--submitpnpm--filename=e2e/test-results/review/add-todo/todo-added.pngpnpm--description=pnpmpnpm--filename=e2e/test-results/review/add-todo/todo-completed.pngpnpmpnpm
The accessibility snapshot gives the agent refs to interact with page elements. It lists buttons, textboxes, and checkboxes as structured text, with their names and states.
In this flow, the initial snapshot identifies the textbox as e8, which the agent uses in the fill command above:
-generic [ref=e6]:---contentinfo [ref=e9]:-paragraph [ref=e10]:
After adding the todo, the agent reads the updated snapshot to find the checkbox, which is e16 in this session.
The snapshots guide the agent through these interactions, and the recording lets the reviewer follow along. Each chapter opens with a card over a blurred page to explain what's about to happen and what to look for.
During each chapter, annotations show what the agent is doing. A callout names the action, the target is highlighted, and an animated pointer moves to it.
At the end of each chapter, the agent takes a screenshot of the result. These screenshots give the reviewer a closer look at each state and let the agent check how the page looks before attaching them to the pull request.
Keep recordings short
The browser stays open between commands. Each CLI command starts a separate process that connects to it, adding a pause to the recording after every action. For longer flows, use run-code --filename=<script>.js with page.screencast to control the pacing. The CLI's skill recommends this approach for recordings used as proof of work. The same flow takes about 10 seconds in a single script, including action callouts, compared to 23 seconds with separate commands:
If you want to run this example manually, save the function below as record-todo.js.
The recording script
record-todo.jsasync(page)=>{const=;await.setViewportSize{:1280,:720};await.evaluate()=>.clear;await.reload;const=.getByRole,{:};await.waitFor;await..start{:${},:{:1280,:720},};try{await..showActions;await..showChapter,{:,:1500,};await.fill;await.press;await.getByText,{:true}.waitFor;await.waitForTimeout1000;await.screenshot{:${}};await..showChapter,{:,:1500,};const=.locator.filter{:};await.getByRole.check;await.getByText,{:true}.waitFor;await.waitForTimeout1000;await.screenshot{:${}};}finally{await..hideActions;await..stop;}}
Then run these commands from the project root:
pnpmpnpm--filename=record-todo.jspnpm
Into the pull request
When opening the pull request, the agent uses the GitHub CLI to upload the screenshots and recording, without committing them to the repository. It also writes the description, so we don't have to prepare it or upload the captures manually.
First, the agent writes the pull request description to a temporary Markdown file, /tmp/pr-body.md. It includes the screenshots using their local file paths, with alt text that explains what to look for:
##Proof it works![]()![]()
Next, the agent opens the pull request. The --body-file option reads the description from that Markdown file, and each --attach option uploads one of the captures:
gh--title--body-file\--attach\--attach\--attach
For the two screenshots, the CLI replaces the local paths in the description with the uploaded URLs, keeping the alt text. The recording isn't mentioned in the Markdown file, so the CLI adds it at the end of the description, where GitHub displays it as a video player.
For more details, see Attaching files with GitHub CLI. PNG, JPEG, GIF, SVG, MP4, MOV, and WebM files are supported. To add files to an existing pull request, use gh pr edit <number> --attach <file>.
Making it the default
We added the workflow to AGENTS.md and the evidence requirements to the pull request template to make captures part of every UI change. If the agent can't create them, it has to say so.
These are our project-specific instructions in AGENTS.md (slightly shortened):
AGENTS.md###Validation evidence--``-``-````````-``-``
And this is the relevant part of the pull request template, which is the same for humans and agents:
.github/pull_request_template.md##Proof it works<!-- A description is a claim; this section is the evidence. Reviewers should nothave to take your word for it. New behavior comes with a test that fails without this change. -->********-``-``````
Lessons from our project
A few things we ran into while setting this up:
- Signing in. Our normal sign-in flow uses Entra ID with multi-factor authentication, so the agent can't sign in on its own. We use an environment variable to start the application in end-to-end mode, just like our Playwright tests. This swaps the identity provider for an in-repo stand-in that signs the browser in as a test user. Everything else stays real, including the API and a throwaway database.
- Checking the video. The agent extracts a few frames with ffmpeg to inspect the recording with its image tools. When ffmpeg isn't available, it can open a small HTML page with a
<video>element, seek to a few points in time, and take screenshots. This lets it check the chapter cards, callouts, and final states. - Pacing. Chapter cards, timed overlays, and action callouts already wait for their duration. Our first recordings added extra pauses after them, so most of the video was spent waiting. Only add a pause when the viewer needs time to inspect a completed state.
- Preserving captures. Running the end-to-end test suite empties the test results folder, including the captures. Create the captures after the test run, or copy the files to another location first.
- Content Security Policy. The chapter cards and callouts are injected into the page using inline styles, which are blocked by our nonce-based CSP. That's why the review browser is opened with the config file below. Its
contextOptionsaccept any browser context option. We setbypassCSP, together withignoreHTTPSErrorsfor the development certificate, and a viewport of 1280 by 720.
.playwright/cli.config.json{"browser":{"contextOptions":{"bypassCSP":true,"ignoreHTTPSErrors":true,"viewport":{"width":1280,"height":720}}}}
Benefits
Less setup for reviewers. I can review a UI change from the pull request, on any device. The alt text tells me what to look for, the screenshots show the states, and the recording shows the flow. For small changes, I might not even look at the code.
Earlier feedback for the agent. By checking the captures, the agent can catch visual mistakes before asking for review, even when the tests pass. It's the same feedback loop as the logs and traces in Improve your AI coding agent with runtime context from Aspire MCP, but applied to the UI.
Reusable evidence. Recordings can be shared with stakeholders. We can also reuse the same captures in release notes and demos.
The best part is that this workflow doesn't need extra infrastructure. The CLI sits next to our Playwright tests, and the attachments live on GitHub. The shared instructions set the same expectations for humans and agents, including reporting a missing capture.
For a broader approach to reviewing agent-written code, I recommend reading How the Claude Code team does code review. Their risk-based review resonates with how our team works and, in combination with the visual captures, helps us focus our attention where it matters most. Give it a read!
Tips from readers
After sharing this post, I received a few useful tips:
- Record before and after. Record the same flow before and after the change, so reviewers can compare the behavior directly.
- Add screenshot diffs. Compare the before and after screenshots and include a diff image that highlights the changed pixels. This makes small visual changes easier to spot. Use the same viewport and test data for both captures to keep the comparison useful.
- Try agent-browser. Readers also suggested agent-browser from Vercel Labs as an alternative for reducing token consumption. Its snapshot filters can limit the output to interactive elements, remove empty structural elements, or focus on a specific part of the page, so the agent has less context to read.
Conclusion
Screenshots show the outcome, recordings show the flow, and inspecting both helps the agent catch mistakes before review. For small changes with little risk, this evidence may be enough to review the change without looking at the code. When the code needs a closer look, the captures give the reviewer context by showing how the change behaves in the running application.
If you want to try this out yourself, install the Playwright CLI, make sure the agent can sign in, and add the workflow to your AGENTS.md file and pull request template.
For me, this means less time setting up and clicking through the application, and more time delivering value.
Related articles
- Sprint Zero is about building momentum
- Improve your AI coding agent with runtime context from Aspire MCP
- Keep Agentic AI Simple: A Practical Workflow for Software Development
- Vibe testing with Playwright
Feel free to update this blog post on GitHub, thanks in advance!
Enjoying the blog?
Support my work
If you enjoyed this post and found it useful, consider supporting my work. It helps me keep creating and sharing content like this. Thank you!