Show HN: Shot-scraper video tool for recording YAML-defined webapp feature demos

simonw1 pts0 comments

Have your agent record video demos of its work with shot-scraper video

Simon Willison’s Weblog

Subscribe

Sponsored by: Depot — AI agents write code in seconds. CI shouldn't make them wait minutes. Try Depot CI

Have your agent record video demos of its work with shot-scraper video

30th June 2026

shot-scraper video is a new command introduced in today’s shot-scraper 1.10 release which accepts a storyboard.yml file defining a routine to run against a web application and uses Playwright to record a video of that routine. I’ve written before about the importance of having coding agents produce demos of their work; this is my latest attempt at enabling them to do that.

Here’s an example video created using shot-scraper video, exercising a still in development feature adding the ability to create new tables in Datasette from pasted CSV, TSV or JSON data:

That video was created by running this command:

shot-scraper video datasette-bulk-insert-storyboard.yml \<br>--auth datasette-demo-auth.json --mp4

(That --auth JSON file contains a cookie, as described here in the documentation.)

Here’s the datasette-bulk-insert-storyboard.yml file:

output: /tmp/datasette-bulk-insert-demo.webm<br>server:<br>- uv<br>- --directory<br>- /Users/simon/Dropbox/dev/datasette<br>- run<br>- datasette<br>- -p<br>- 6419<br>- --root<br>- --secret<br>- "1"<br>- /tmp/demo.db<br>url: http://127.0.0.1:6419/demo/tasks<br>viewport:<br>width: 1280<br>height: 720<br>cursor: true<br>wait_for: 'button[data-table-action="insert-row"]'<br>javascript: |<br>(() => {<br>let clipboardText = "";<br>Object.defineProperty(navigator, "clipboard", {<br>configurable: true,<br>get: () => ({<br>writeText: async (text) => {<br>clipboardText = String(text);<br>},<br>readText: async () => clipboardText,<br>}),<br>});<br>})();<br>scenes:<br>- name: Bulk insert existing table rows<br>do:<br>- pause: 0.8<br>- click: 'button[data-table-action="insert-row"]'<br>- wait_for: "#row-edit-dialog[open]"<br>- pause: 0.5<br>- click: ".row-edit-bulk-insert"<br>- wait_for: ".row-edit-bulk-textarea"<br>- pause: 0.5<br>- click: ".row-edit-copy-template"<br>- wait_for: "text=Copied"<br>- pause: 0.8<br>- fill:<br>into: ".row-edit-bulk-textarea"<br>text: |<br>title,owner,status,priority,notes<br>Prepare release video,Ana,doing,1,Recorded with shot-scraper<br>Check pasted CSV import,Ben,review,3,Previewed before inserting<br>Share the branch demo,Chen,queued,2,Bulk insert creates three rows<br>- pause: 0.8<br>- click: ".row-edit-save"<br>- wait_for: "text=Previewing 3 rows."<br>- pause: 1.2<br>- click: ".row-edit-save"<br>- wait_for: "text=3 rows inserted."<br>- pause: 1.0<br>- click: ".row-edit-cancel"<br>- wait_for: "text=Prepare release video"<br>- pause: 1.0<br>- name: Create a table from pasted CSV<br>open: http://127.0.0.1:6419/demo<br>wait_for: 'details.actions-menu-links summary'<br>do:<br>- pause: 0.8<br>- click: 'details.actions-menu-links summary'<br>- click: 'button[data-database-action="create-table"]'<br>- wait_for: "#table-create-dialog[open]"<br>- pause: 0.5<br>- fill:<br>into: ".table-create-table-name"<br>text: "launch_metrics"<br>- click: ".table-create-from-data"<br>- wait_for: ".table-create-data-textarea"<br>- pause: 0.5<br>- fill:<br>into: ".table-create-data-textarea"<br>text: |<br>metric_id,name,score,recorded_on<br>m001,Activation rate,87.5,2026-06-29<br>m002,Retention check,72.25,2026-06-30<br>m003,CSV import health,95,2026-07-01<br>- pause: 0.8<br>- click: ".table-create-save"<br>- wait_for: "text=Previewing 3 rows."<br>- pause: 1.2<br>- click: ".table-create-save"<br>- wait_for_url: "**/demo/launch_metrics"<br>- wait_for: "text=Activation rate"<br>- pause: 1.2

The video command documentation includes simpler examples, but for the purpose of this post I thought I’d go with something more comprehensive.

That demo YAML storyboard was constructed entirely by GPT-5.5 xhigh running in Codex Desktop, using the following prompt run inside my ~/dev/datasette checkout of this branch:

Review the changes on this branch.

cd to ~/dev/shot-scraper and run the command "uv run shot-scraper video --help"

Now use that new video command to record a video demo of the new features from this branch, including running a "uv run datasette -p 6419 --root --secret 1 /tmp/demo.db" development server so you can record the video against a demo DB that you first create.

Now that I’ve released the feature the prompt could say "run uvx shot-scraper video --help" instead and it should achieve the same result.

I really like this pattern where the --help output for a command provides enough detail that a coding agent can use it—it works kind of like bundling a SKILL.md file directly inside the tool. I used the same pattern for showboat and rodney.

How I built this

shot-scraper video started as an experimental prototype. shot-scraper is built on top of Playwright, and the key feature it needed was for Playwright to be able to record video of browser sessions with enough control to create the desired demo.

I first tried this a few years ago and found that the Playwright-produced videos included additional chrome that was useful for debugging a test failure but unwanted for a product demo.

They fixed that a while ago, but there were still some...

video pause shot scraper demo table

Related Articles