Generate a presentation-worthy screenshot deck of the current product — discovers the aspects worth showing (the CLI's `--help`, the web app's routes, the library's quickstart), captures each with the *right tool per surface* (project's existing browser driver for web — Selenium-Java if none / Playwright for Node-Python / VHS for CLI / Freeze for code snippets), and assembles a captioned, narrative-ordered deck under `presentation/` ready to walk through in a meeting, paste into slides, or se...
Scanned 9/5/2026
Install to Claude Code
npx -y skills add alexmond/alexmskills --skill screenshot-tour --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Screenshot Tour?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/alexmond-screenshot-tour)More formats (shields.io, HTML) on the badges page.
---
name: screenshot-tour
description: Generate a presentation-worthy screenshot deck of the current product — discovers the aspects worth showing (the CLI's `--help`, the web app's routes, the library's quickstart), captures each with the *right tool per surface* (project's existing browser driver for web — Selenium-Java if none / Playwright for Node-Python / VHS for CLI / Freeze for code snippets), and assembles a captioned, narrative-ordered deck under `presentation/` ready to walk through in a meeting, paste into slides, or send to stakeholders. Use when the user asks for "presentation screenshots", "a demo deck", "screenshots for a slide deck", "show what this does", "presentation of the product", or is preparing to demo/pitch the project. Works on CLIs, web apps, libraries, and TUIs.
---
# Screenshot Tour
> **Try it:** `/screenshot-tour:screenshot-tour` — or say "build a presentation deck of this product".
> Not `screenshot-sweep`, which *audits* a capture you already have for defects.
> This one *produces* a deck. If a tour capture shows something broken, that is a
> sweep finding — file it, don't put it in the deck.
A *presentation deck* is not a screenshot — it's the **set of aspects** a stranger needs to see to understand what the product does, ordered as a narrative they can follow without you talking over it. A single capture answers "what does it look like"; a deck answers "what does it do, end to end, in the moments that matter." The skill's job is to make sure the deck is **complete enough** to substitute for a 5-minute live demo, and **consistent enough** that every image reads as one product.
The deliverable is the deck itself — a numbered set of images plus a one-page manifest under `presentation/`. Slide-deck export, README integration, and docs-site embedding are *optional follow-ups* (see the bottom of this file), not part of the core loop.
## Boundaries
Invoke proactively when the user is preparing a demo, stakeholder meeting,
release announcement, or pitch and there are no captures in `presentation/`.
Not for: single ad-hoc screenshots (plain `Bash` or a screenshot skill), visual
regression testing (Chromatic / Playwright tests), or documentation-site
illustrations — that's a downstream consumer of the deck, not its goal.
## Files this skill owns
- `presentation/plan.md` — the editable tour plan (numbered aspects + capture method per aspect); user-gated before any capture runs.
- `presentation/tour.md` — the final manifest with each image + caption, ordered for narrative.
- `presentation/recipes/*.tape` (CLI products) or `*.spec.ts` (web products) — the per-aspect capture scripts. Re-runnable.
- `presentation/NN-<slug>.{png,gif}` — the captures themselves, numbered for ordering.
- `presentation/contact-sheet.png` — optional 1-image overview of the whole deck (5×N grid).
- `.claude/screenshot-tour/log.md` — the per-run log (one entry per tour run); the skill graduates patterns out of this into a `## Screenshot tour` block in the repo's `CLAUDE.md`.
The shipped `log.md` in this plugin is a read-only seed; the live, append-only log lives at the consuming repo's `.claude/screenshot-tour/log.md`.
## The three phases
### 1. Discover — propose the tour plan
Read the repo and propose 5–12 aspects worth capturing. **Don't capture anything yet.** Sources, in order:
1. **README** — the *promised* aspects. If the README has a "Features" section, every bullet is a candidate. The hero animation/screenshot (if any) tells you the headline framing.
2. **Entry points** — for CLIs, the binary's `--help` (top-level + per-subcommand `--help`); for web apps, the route table (Spring `RequestMapping`, Next/Remix `pages/`, Django `urls.py`, etc.); for libraries, the public API surface in the entry module + example/sample/quickstart files.
3. **`docs/`** — if there's a docs site, its top-level nav is the canonical list of aspects.
4. **What the audit is asking for** — if `evolving-claude-md` has surfaced any "graduated to Conventions" patterns, those are usually load-bearing aspects.
5. **Recent CHANGELOG / git log** — last 1–2 releases tell you what's *new* and worth foregrounding.
Write `presentation/plan.md` with this shape:
```markdown
# Screenshot tour plan — <product>
> Edit freely before approving. Each aspect = one image. Reorder for narrative; cut anything that won't read in a 30-second skim of the deck.
## Aspects
1. **hero** — opening shot (`<what it shows>`) — *capture: VHS / Playwright / Freeze / manual*
2. **install** — install command + first run output — *capture: VHS*
3. **<feature-1>** — `<one-line caption that will appear under the image>` — *capture: <method>*
...
N. **outcome** — the payoff (a chart, a digest, a finished workflow) — *capture: <method>*
## Capture defaults
- product-type: <cli | web | library | tui | mixed>
- dimensions: <e.g. 1200×800 for web; 1200×720 for VHS>
- theme: <e.g. Dracula for VHS; system-light for web>
- output dir: presentation/
```
**Pre-check every aspect for an affordance trap.** A shot that renders a
setup prompt ("requires an AI model", "no data yet") or a thin demo dataset
captures the *affordance*, not the *payoff* — and quietly weakens the deck.
For each aspect, ask: *what will actually render if I capture this right
now?* When the answer is a prompt or an empty state, say so in `plan.md` on
that aspect's line — e.g. *"renders the setup prompt unless a completed
result is seeded first"* or *"demo dataset has 6 rows; point at the richer
dataset for more impact"* — so the user can opt into seeding before capture
instead of discovering the weak shot in the finished deck.
**Stop and ask the user to confirm the plan before phase 2.** A 12-aspect tour costs real time to capture; the cheapest way to throw work away is to capture the wrong aspects.
### 2. Capture — execute the plan, one aspect at a time
For each aspect in `plan.md`, run the matching capture method. Each method ships its own recipe file under `presentation/recipes/` so the tour is re-runnable on the next release. When a project's own screenshot tooling does the capturing, the recipe is a one-line wrapper that invokes it — **never leave `recipes/` empty or absent while the repro command lives only in prose**; an empty dir tells the next runner the tour isn't re-runnable when it is.
**Use the right tool per surface.** Don't try to screenshot a web app with VHS or a terminal session with Playwright.
#### CLI / TUI → VHS (Charmbracelet)
The standard for terminal demos. Tape-file syntax → PNG / GIF / MP4. Renders text with a fixed-width font and known cell width, so column alignment survives.
Install: `go install github.com/charmbracelet/vhs@latest` (also brew, scoop, nix, apt). Requires `ttyd` + `ffmpeg` in `$PATH`.
Minimal tape file (`presentation/recipes/02-install.tape`):
```
Output ../02-install.png
Require myproduct
Set FontSize 18
Set Width 1200
Set Height 720
Set Theme "Dracula"
Type "myproduct install"
Sleep 200ms
Enter
Sleep 2s
Screenshot ../02-install.png
```
Then: `vhs presentation/recipes/02-install.tape`.
For animated aspects (a multi-step demo worth as a GIF, not a still): change `Output ../02-install.gif` and drop the explicit `Screenshot` call (VHS records the whole run).
Cheat sheet of useful tape commands: `Type "..."`, `Enter [n]`, `Sleep <dur>`, `Ctrl+C`, `Backspace [n]`, `Tab`, `Hide` / `Show` (toggle recording mid-tape), `Set TypingSpeed 50ms`, `Set PlaybackSpeed 2`. Full reference: <https://github.com/charmbracelet/vhs>.
#### Web app → use the browser-driver your project already uses
**Don't introduce a new automation stack just to take screenshots.** A second driver in the repo is a maintenance liability and the recipes will rot the moment nobody runs them between releases. The right tool is the one your existing test suite already uses; the skill ships recipes for the three common cases.
##### Selenium / Selenide (Java / Kotlin / JVM)
Default for Java projects. If the repo already has Selenium WebDriver, Selenide, or Playwright-Java as a test dependency, reuse it. Reuses the project's WebDriverManager, browser, and viewport conventions; recipes land in `src/test/java/.../screenshots/` so the build runs them.
Minimal recipe (`src/test/java/.../screenshots/DashboardTourTest.java`):
```java
@Test
void dashboard() throws IOException {
var dim = new Dimension(1440, 900);
driver.manage().window().setSize(dim);
driver.get(System.getenv().getOrDefault("BASE_URL", "http://localhost:8080"));
driver.findElement(By.linkText("Dashboard")).click();
new WebDriverWait(driver, Duration.ofSeconds(10))
.until(d -> ((JavascriptExecutor)d).executeScript(
"return document.readyState").equals("complete"));
var png = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
Files.copy(png.toPath(), Path.of("presentation/03-dashboard.png"),
REPLACE_EXISTING);
}
```
Selenide variant (shorter): `Selenide.screenshot(OutputType.FILE)` returns the file directly, no `TakesScreenshot` cast.
Full-page captures: Selenium's `getScreenshotAs` is viewport-only. For full-page on Chrome/Edge use the CDP command:
```java
var screenshot = ((HasCdp) driver).executeCdpCommand(
"Page.captureScreenshot", Map.of("captureBeyondViewport", true));
Files.write(Path.of("presentation/03-dashboard.png"),
Base64.getDecoder().decode((String) screenshot.get("data")));
```
Tips:
- One JUnit test class per aspect (`DashboardTourTest`, `SettingsTourTest`, …) — a failure in aspect 7 should not block aspects 8–12.
- Annotate the tour class with `@Tag("screenshots")` and gate it from CI by default (`-DexcludedGroups=screenshots`) — you want to *run* them on release prep, not on every PR.
- Pin viewport in `@BeforeAll` so the whole deck shares dimensions.
- For demo data, seed via the app's normal API in `@BeforeAll` so the deck doesn't drift session-to-session.
##### Playwright (Node / Python — optional)
Use if the project's test stack is already Node/Python or you genuinely need cross-browser (Chromium + Firefox + WebKit) coverage. Playwright's `screenshot({fullPage: true})` handles full-page natively (no CDP gymnastics) and the action vocabulary (click/type/hover/select_option/press_key/drag/wait/navigate/evaluate/fill_form/handle_dialog/file_upload/resize/hide) is the richest for scripted tours.
Install (Node): `npm i -D @playwright/test && npx playwright install chromium`. Python: `pip install playwright && playwright install chromium`. Java has `Playwright-Java` if you want the action vocab without leaving the JVM.
```typescript
import { test } from '@playwright/test';
test('dashboard', async ({ page }) => {
await page.setViewportSize({ width: 1440, height: 900 });
await page.goto(process.env.BASE_URL ?? 'http://localhost:3000');
await page.getByRole('link', { name: 'Dashboard' }).click();
await page.waitForLoadState('networkidle');
await page.screenshot({
path: 'presentation/03-dashboard.png',
fullPage: true,
});
});
```
##### Cypress / WebDriverIO / TestCafe / shot-scraper / etc.
If that's what the repo uses, use that. Cypress: `cy.screenshot('03-dashboard', {capture: 'fullPage'})`. WDIO: `browser.saveFullPageScreenshot(...)`. [`shot-scraper`](https://shot-scraper.datasette.io/) (Python, Playwright-backed) is the lightest-weight option for one-off captures without a test framework. The skill's contract is "one recipe per aspect, numbered, lands in `presentation/`" — *how* the recipe runs is up to the project.
##### Selection rule
1. Project already has a browser driver in `pom.xml` / `package.json` / `requirements.txt` → use that.
2. No existing driver, but it's a Java repo → Selenium-Java + Selenide (matches the wider ecosystem).
3. No existing driver, Node/Python repo → Playwright (best DX for fresh installs).
4. No existing driver, one-off capture only → `shot-scraper` (zero project footprint).
#### Code snippet / config / output → Freeze (Charmbracelet)
For aspects where the value *is* the code (a config file, an API call, a CLI output transcript), pretty-print to PNG with window chrome.
Install: `go install github.com/charmbracelet/freeze@latest` (also brew, scoop, nix). Pure static — no runtime, no terminal needed.
```
freeze --language=yaml \
--theme=github \
--window \
--output presentation/05-config.png \
config/application.yml
```
Or pipe live: `myproduct analyze --hints | freeze --language=ansi -o presentation/06-hints.png`.
Carbon (<https://carbon.now.sh>) and Ray.so are browser alternatives — use Freeze for scripted/reproducible captures.
#### Manual (the fallback)
Some aspects only a human can capture cleanly — mobile UI, OS dialogs, hardware. Don't simulate them; write a one-paragraph checklist in `plan.md` ("open Settings → Profile, capture 1200×800") and the user supplies the file. Mark `*method: manual*` in the plan.
#### Format rules (apply across all methods)
- **PNG for stills** (no JPEG; JPEG artifacts murder small text). GIF/WEBM/MP4 for animated aspects only.
- **One consistent set of dimensions** per deck (e.g. all web shots 1440×900, all VHS shots 1200×720). The deck reading as *one product* matters more than each shot being perfectly tight.
- **Numbered prefixes** (`01-`, `02-`, …) so file order = deck order.
- **No dev clutter** — close DevTools, hide notification banners, clear test fixtures, mask secrets. The deck represents the product, not the dev environment.
- **Host hygiene on every surface, not just shell recipes.** Any URL that will
be *rendered into pixels* — a Freeze'd CLI transcript, a VHS `Type` line, a
visible browser address bar — goes through the same substitution as the
recipes: the project's documented public URL, or a neutral placeholder like
`https://example.invalid`, never whatever instance the capture ran against.
A hostname baked into a committed PNG is invisible to every text-based
secret scanner — parameterizing only the recipe was the miss behind this rule.
- **Light theme by default** for screenshots in READMEs and docs (better print legibility); dark variants under `presentation/dark/` if needed.
### 3. Assemble — write the manifest + (optional) contact sheet
After capture, write `presentation/tour.md`:
```markdown
# <Product> — tour
A 30-second look at <product> across <N> aspects.
**Lead with:** 01-hero · 03-<core-flow> · NN-outcome <!-- the 3-shot subset
for a skim, a forum post, or a social embed — pick the images that carry the
story alone -->
## 1. Hero

<one-sentence what it does>
## 2. Install

<one-sentence install pitch>
...
## N. Outcome

<one-sentence why it matters>
---
Generated by [screenshot-tour](https://www.alexmond.org/alexmskills/screenshot-tour.html). Re-run with `/screenshot-tour:screenshot-tour`.
```
Three template rules, pinned after real decks diverged on each:
- **The attribution link is canonical** — exactly the URL above, always; two
URLs for one skill reads as two tools.
- **The repro command lives in the footer, only** — never duplicated into the
header note.
- **Every deck marks the "Lead with:" 3-shot subset** — a skim or a forum post
gets one or two images; say which carry the story.
**Order for narrative**, not for capture-method or alphabetical. A good order: *Hero → Install → 2–3 core flows → Advanced/outcome → What's next*.
**Contact sheet (optional)** — a single PNG with all captures laid out in a 5×N grid. Useful for slide-deck section openers. Generate via ImageMagick:
```bash
magick montage presentation/[0-9]*.png \
-tile 5x -geometry 240x160+8+8 -background '#0e1117' \
presentation/contact-sheet.png
```
## Quality bar — would this deck land?
Before finishing, gut-check the deck against three questions:
1. **Does the hero shot answer "what is this"?** If a reader skips everything else, they should know what the product does from image 1 alone.
2. **Could you swap any two adjacent images without losing the story?** If yes, the order is too arbitrary — re-narrate.
3. **Is anything *clearly* missing?** Walk the README's Features section and the `--help`/route table again. The audit step exists because the discovery phase always misses 1–2 aspects.
If any answer is "no", iterate on the *plan* (don't re-capture; re-design).
## Optional follow-ups (not run by default)
The deck under `presentation/` is the deliverable. These are **opt-in** consumers — only do them when the user asks.
- **Slide-deck export** — re-package the deck as a Keynote / PowerPoint / Google Slides / Reveal.js / Marp slide per aspect, with each caption as the speaker note. Closest to the skill's intended use; one-line CLI for Reveal.js / Marp from the manifest. Reach for this first when the user says "I'm presenting Friday."
- **README integration** *(later)* — propose a README diff that adds the hero image + a `See full tour →` link to `presentation/tour.md`. Skip unless the user asks for it.
- **Antora / docs-site page** *(later)* — render the deck as a docs-site page under the project's docs component. Skip unless the user asks for it.
Don't auto-run any of these.
## What goes into `## Screenshot tour` in the repo's CLAUDE.md (graduation)
After 2–3 successful runs in the same repo, lift the stable bits into a `## Screenshot tour` block in `CLAUDE.md` so the next run starts there:
```markdown
## Screenshot tour
- product-type: cli + library
- standard dimensions: 1200×720 (VHS), 1000×600 (Freeze)
- theme: Dracula (VHS), GitHub Light (Freeze)
- output dir: presentation/
- standard recipes: presentation/recipes/*.tape (re-runnable)
- canonical aspects (always capture): hero, install, <feature-1>, <feature-2>, outcome
```
Graduated entries are pruned from `.claude/screenshot-tour/log.md` (the log keeps the *variance*, the block keeps the *invariants*).
## The per-run log
Append one entry per tour run to `.claude/screenshot-tour/log.md`:
```
## <run-id> <yyyy-mm-dd> <repo>
- product-type: <cli | web | library | tui | mixed>
- aspects-planned: <n> aspects-captured: <m> aspects-fallback: <k>
- tools-used: <vhs (n), playwright (m), freeze (k), manual (j)>
- gotchas: <e.g. `ttyd` missing in container; Playwright headless DPR=1 too small; VHS wayland incompatibility>
- steering: <what the user edited in the plan — added X, cut Y, reframed Z>
- outcome: <committed-at <path> | partial | abandoned>
- graduated: <what lifted to the `## Screenshot tour` block this run, if any>
```
The log is how the skill *learns*. After 3 runs in the same repo: stable capture methods graduate to the CLAUDE.md block; failed methods get a `do-not-try` note; the canonical-aspects list grows.
## Common failure modes (read before running)
- **Skipping the plan-confirmation gate.** Capturing first, narrating after, makes the deck a collection of pretty images that don't tell a story. The plan is the deck; the captures are the body.
- **Mixing capture mechanisms within one frame.** Don't paste a VHS PNG next to a Playwright PNG with mismatched padding/borders — the deck stops reading as one product. Pick per *deck*, not per *aspect*.
- **Animated GIFs for everything.** A GIF for the hero is great; 12 GIFs in a README is unreadable. Default to PNG; reach for GIF/MP4 only when motion is the point.
- **No light/dark consistency.** Pick one and stick with it across the deck.
- **Secrets in screenshots.** API keys, tokens, real customer data. Always run a pass that masks before committing. The skill should remind the user before capture starts.
- **No `Require` lines in VHS tapes.** A tape that runs against a stale `$PATH` silently captures the wrong product version. Always declare what binaries the tape depends on.
- **One huge spec file for Playwright.** Splits the deck into per-aspect spec files — a failure in aspect 7 should not block aspects 8–12.
## Provenance & inspiration
This skill's capture strategies stand on:
- **Charmbracelet VHS** — <https://github.com/charmbracelet/vhs> (CLI tape recordings)
- **Charmbracelet Freeze** — <https://github.com/charmbracelet/freeze> (code/output stills)
- **Playwright** — <https://playwright.dev> (web tours)
- **Carbon** — <https://carbon.now.sh> (pretty code, browser alternative)
- **awesome-readme** — <https://github.com/matiassingers/awesome-readme> (README conventions)
The *tour* layer (discovery → plan → capture → assemble → graduate) is original to this skill.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!