Yesterday, I added scheduled posts to firehose. I let my coding agent write the release notes. It is fun to read the release notes like this, and see the screenshots. Do note that a coding agent might not care there is no navigation - it happily will remember the urls and navigate to them, so that is something you might want to double check with exploratory testing :-).
I’ve included the full skill below. It is not in the repository, it went straight to my home directory so I can use it in other porjects. This is the second project I have used it in. It helped me earlier do a fairly large archiectural spike for an RFP response, and include screenshots of a working application in the response document. Working software is still a great measure of progress.
Demo skill - let your agent generate demos with screenshots for you
name: demo description: >- Generate a living demo document proving a feature works. Uses showboat for Markdown assembly with captured command output and rodney for Chrome browser screenshots. Use when the user says “demo this”, “show me it works”, “create a demo”, or after /build completes. argument-hint: “<feature-name> [–scenario <description>] [–plan <path>]” user-invocable: true allowed-tools: Read, Write, Glob, Grep, Bash
Demo
Role: worker. This command generates a standalone Markdown demo document that proves a feature works, using showboat for document assembly and rodney for browser automation.
You have been invoked with the /demo command.
Parse Arguments
Arguments: $ARGUMENTS
-
Positional:
<feature-name>(required) — short name or description of the feature to demo -
--scenario <description>: Explicit demo scenario describing what to show. If omitted, infer from the plan and recent commits. -
--plan <path>: Path to the plan file. If omitted, searchplans/for the most recently modified.mdfile with statusimplementedorapproved.
Steps
1. Check tool availability
Verify showboat and rodney are installed:
showboat --help 2>/dev/null && echo "showboat: ok" || echo "showboat: missing"
rodney --help 2>/dev/null && echo "rodney: ok" || echo "rodney: missing"
If either tool is missing, tell the user:
One or more demo tools are missing. Install them with:
go install github.com/simonw/showboat@latest go install github.com/simonw/rodney@latest
Do not proceed until both tools are confirmed available.
2. Gather feature context
Build an understanding of what to demo from these sources (in priority order):
-
Explicit scenario (
--scenario): If provided, use as primary guide. - Plan file: Read the plan’s Goal, Acceptance Criteria, and completed Steps.
-
Recent commits: Run
git log --oneline -15andgit diff main...HEAD --statto identify changed files and commit messages. -
Route map: Cross-reference changed files against known LiveView routes in the router (
lib/hub_web/router.ex).
From these sources, produce a demo outline:
- Narrative: 2-3 sentence description of what the feature does
- Backend evidence: mix commands, test output, or database queries to run
- UI pages: which routes to visit and what to look for
- Interactions: any clicks, form fills, or navigation sequences to perform
If no plan exists and commits are ambiguous, ask the user for a brief description of what to demo.
3. Check dev server
curl -s -o /dev/null -w "%{http_code}" http://localhost:4000/ 2>/dev/null
If the server is not reachable:
The Phoenix dev server is not running. Start it now?
mix phx.server &
After starting, wait up to 10 seconds and verify connectivity. If it still fails, proceed with backend-only evidence (skip all browser screenshots) and note the limitation in the demo document.
4. Handle authentication
The app requires authentication for LiveView routes. Before capturing UI screenshots:
-
Ensure a demo user exists:
mix run -e " alias Hub.Accounts case Accounts.get_user_by_email(\"demo@example.com\") do nil -> Accounts.register_user(%{email: \"demo@example.com\", password: \"demodemo1234\"}) user -> {:ok, user} end " -
Log in via rodney:
rodney start rodney open http://localhost:4000/users/log-in rodney wait "input[name='user[email]']" rodney input "input[name='user[email]']" "demo@example.com" rodney input "input[name='user[password]']" "demodemo1234" rodney click "button[type='submit']" rodney waitidle
If login fails, warn and proceed with backend-only evidence.
5. Initialize the demo document
Slugify the feature name (lowercase, hyphens, no special chars). Then:
showboat init "demos/demo-$(date +%Y%m%d-%H%M%S)-<slug>.md" "Demo: <Feature Name>"
Store the demo file path for use in all subsequent steps.
6. Narrative introduction
showboat note <demo-file> "## Feature Overview
<2-3 sentence description derived from the plan or commits.>
**Branch**: $(git branch --show-current)
**Commits**: <N> commits ahead of main
**Plan**: <plan file path or 'none'>
"
7. Backend evidence
Capture backend proof via showboat exec. Always include relevant tests. Add narrative notes between evidence blocks explaining what each proves.
Test output (always include):
showboat note <demo-file> "## Test Suite"
showboat exec <demo-file> bash "mix test <relevant-test-files> --color"
showboat note <demo-file> "All <N> tests pass, confirming <specific criterion>."
Compilation check:
showboat note <demo-file> "## Compilation Check"
showboat exec <demo-file> bash "mix compile --warnings-as-errors"
Database state (if relevant to the feature):
showboat note <demo-file> "## Database State"
showboat exec <demo-file> bash "mix run -e '<query expression>'"
8. UI screenshots
For each UI page identified in step 2, navigate with rodney, screenshot, and embed via showboat.
Static page capture:
rodney open http://localhost:4000/<route>
rodney waitidle
rodney screenshot demos/screenshots/<feature>-<page-name>.png
showboat note <demo-file> "### <Page Name>
<What this page shows and why it proves the feature works.>"
showboat image <demo-file> ''
Interactive flow (form submissions, navigation):
showboat note <demo-file> "### Interactive Flow: <Flow Name>"
# Before state
rodney screenshot demos/screenshots/<feature>-before.png
showboat image <demo-file> ''
# Perform interaction
rodney click "<selector>"
rodney input "<selector>" "<value>"
rodney click "<submit-selector>"
rodney waitidle
# After state
rodney screenshot demos/screenshots/<feature>-after.png
showboat image <demo-file> ''
9. Acceptance criteria checklist
If a plan file exists, map each acceptance criterion to evidence:
showboat note <demo-file> "## Acceptance Criteria Verification
- [x] <Criterion 1> -- see Test Suite output above
- [x] <Criterion 2> -- see <Page Name> screenshot
- [x] <Criterion 3> -- see Database State output
"
If no plan, summarize what was demonstrated and what it proves.
10. Clean up
rodney stop 2>/dev/null || true
11. Report results
Display:
## Demo Complete
- **Document**: demos/<filename>.md
- **Screenshots**: <N> captured in demos/screenshots/
- **Evidence**: <N> backend commands, <N> UI screenshots
- **Acceptance criteria**: <N>/<M> demonstrated
Error Handling
-
Tools not installed: Show
go installcommands. Do not proceed without them. - Dev server not running: Offer to start. If startup fails, produce backend-only demo and note the limitation.
- Authentication failure: Proceed with backend-only evidence. Note skipped UI screenshots in the document.
- Screenshot failure: Log the error as a note in the demo document, continue with remaining screenshots.
- No plan found: Infer from git commits and changed files. Ask the user for a description if commits are ambiguous.
-
Rodney/Chrome crash: Run
rodney stopthenrodney startto reset. Retry once. If it fails again, degrade to backend-only.
Integration
-
/buildcan suggest running/demoafter a successful build -
/prcan invoke/demoto generate evidence before or after PR creation -
/planproduces the acceptance criteria this command verifies visually -
Beads (
bd) can reference demo documents as task completion evidence -
Reads plan files from
plans/directory (same format as/build)