For years, showing that a change worked meant clicking through the app myself and describing what I saw in a bug report or a pull request. Sometimes I would record the walkthrough, but that was just as manual: I drove the clicks, I narrated nothing, and the recording went stale the moment the code changed. Either way a reviewer had to take my word for it or repeat the clicks on their own machine, and nobody could tell which screen or which number I had actually been looking at.
I wanted something different: a video a stakeholder could watch in about a minute, where the thing that matters is circled and explained, and that an agent could produce on its own while I kept working. So I built a Claude Code skill for it, called annotated-demo-video. It came out of a run where I needed eight verified bug videos in one sitting, and I was not going to click through eight flows by hand and write them up.
What it
produces.
Here is one of the skill's own examples. It is a checkout bug where the subtotal ignores quantities, shown first as broken and then fixed, recorded from a small sample app with made-up cart data.
Every frame has the element that matters ringed, the rest of the page dimmed, and a caption card with a step count like "3 / 12", a short title, and a sentence or two. The same frames come out three ways: an MP4, a self-contained HTML player with a step rail and chapters, and a contact sheet, which is a single image with every frame laid out in a grid.
How it
works.
I tell the agent what to show in plain words: the flow, the bug, or the screens a pull request touches. The agent turns that into a storyboard: a JSON file with a title card and a list of steps. Each step has some actions to perform (click this, fill that, go to this page) and a shot that says which element to ring and what the caption says. Finding the selectors, seeding the demo data, and filling in the clicks between frames is the agent's job, not mine.
{
"selector": "#subtotal",
"title": "Subtotal reads {{ #subtotal }}",
"body": "The lines add up to $222.00. The subtotal drops the ×3 and the ×2."
}
A recorder script runs the storyboard against the real, running app
in a full Chromium browser through Playwright. Before each shot it
injects a small overlay script that draws the ring and the caption
card. Captions can pull live values straight off the page: in the
snippet above, {{ #subtotal }}
is replaced with whatever the subtotal actually reads at the moment
the shot is taken. The recorder writes a folder of frames and a
manifest, a small file listing each frame and its caption.
A finishing script then crops the frames, builds the contact sheet, stitches the MP4 with crossfades, and writes the HTML player with autoplay and light and dark modes. The same storyboard against the same app state gives the same frames every time, so a video is something I can regenerate, not something I have to remake. There is also an adapter that does the same thing from inside a Rails system test, which is handy when the setup needs fixtures and a signed-in user.
In practice I rarely run any of this myself. The skill tells the main agent to hand production to a subagent. I give it one sentence about the scene and the data it needs, and it comes back with the sheet, the video and the player.
What I
learned.
- 01Never scroll. My early videos used timed scrolls, and on a short page they overshot and parked on empty whitespace. It looked broken. Now the recorder never scrolls at all. It takes a full-page screenshot and clips it at the spot that centres the target element.
- 02Hold each frame for its reading time. A fixed three seconds per frame is too long for "Cart page" and too short for a two-sentence explanation. Each frame is held for a small base plus its word count at a reading pace, clamped to a sensible range.
- 03Read live values, never hardcode them. A caption that types the number in by hand will eventually disagree with the screen behind it. Pulling the value off the page at shot time makes the caption and the pixel the same fact.
- 04Be honest about what cannot be filmed. Some bugs live in a field the UI never shows, or in an API response, or in something that is missing. Before recording, the skill sorts a bug into one of four buckets: you can see it in the UI, you can show it as a state change, it is not filmable, or it is structural, like a schema or concurrency problem with no single frame to point at. The last two get written up, not filmed.
- 05Verify with the contact sheet. Before anyone sees a video, the agent reads the contact sheet and re-checks any claimed state in the database. If a frame rings the wrong thing, it fixes the storyboard and records again.
- 06Keep the assets out of the repo. Everything gets built in a scratch folder under
/tmp/demos. Videos are for the conversation about a change, not part of the change.
The takeaway.
The thing I care about most is not the polish. It is that the video is reproducible and checked. When the code changes, the agent runs the storyboard again. When a reviewer asks what happened, I send a sixty second link instead of a paragraph.
Try
Describe the demo, then let an agent film it.
If you are still proving changes by clicking through them yourself, recorded or not, try handing the next one to an agent as a storyboard. The skill is on GitHub.