Skip to content
Agentmart
Submit a tool

vs-explain-pr

Make a short narrated video explainer of an open PR from its base...head diff, finished body, and evidence media, then add it to the PR body.

Skill by vltansky

IndexedMIT
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/vltansky-vs-explain-pr

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Make a short narrated video explainer of an open PR from its base...head diff, finished body, and evidence media, then add it to the PR body. Composed by /vs-ship-it after the PR is open (a background agent); also direct when the user types /vs-explain-pr or asks for a video of a PR. Reuses the vs-explain-video kit; produces one 1280x720 mp4 under 10 MB in a marked body block.

Use cases: agent-building

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found
Runs as
Node.js package

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/vs-explain-pr

What's inside

Skill name
vs-explain-pr
Description
Make a short narrated video explainer of an open PR from its base...head diff, finished body, and evidence media, then add it to the PR body. Composed by /vs-ship-it after the PR is open (a background agent); also direct when the user types /vs-explain-pr or asks for a video of a PR. Reuses the vs-explain-video kit; produces one 1280x720 mp4 under 10 MB in a marked body block.
License
MIT
Instructions
194 lines in SKILL.md · view on GitHub

Before installing

  • Ships executable scripts

Files (10)

  • SKILL.md
  • openai.yaml · agents/
  • attach.mjs · scripts/
  • finish.mjs · scripts/
  • lint.mjs · scripts/
  • pr-video.mjs · scripts/
  • prep.mjs · scripts/
  • diff-first.eval.ts · test/
  • explain-pr.eval.ts · test/
  • explain-pr.static.eval.ts · test/

SKILL.md (first lines)

# Explain a PR in a video

A 45-75 second narrated video of one PR: the problem in a sentence or two, then
the real example (the PR's own screenshots and recordings), what changed, the
result, and where to look in review. It runs after the PR is open, so CI and
reviewers never wait for it. The video adds to the PR body; it never replaces
the written proof.

## Flow Contract

- **Kind:** Building block
- **Inputs:** PR number and repo, head SHA, base ref (the diff is
  `<base>...<head>`), the final PR body file, and the record-flow manifest(s)
  or media files ship-it used. Nothing else: no conversation.
- **Outputs:** `final.mp4` (1280x720, 75 seconds or less, under 10 MB) under
  `~/.vs/$PROJECT_ID/videos/pr-<N>/`, and one `<!-- vs:video -->` block in the
  PR body
- **Status:** `VIDEO_ATTACHED`, `VIDEO_READY` (direct use, not attached),
  `GATE_FAILED`, or `BLOCKED_TOOLING` (with the install step)
- **Consumers:** `/vs-ship-it` Step 4b (one fresh-context background agent);
  direct user invocation
- **Skip conditions:** No open PR. A PR the ship-it rubric marks too small.

Run every step yourself in this agent. Do not start more agents.

## 1. Check the tools

`node <skill-dir>/../vs-explain-video/scripts/preflight.mjs "$WORK"`. Exit 2:
report `BLOCKED_TOOLING` with its `next` text and stop. The PR stays as it is.
The renderer is fframes, as in explain-video: with `fframes.warmable`, run
`fframes.mjs doctor --warm` once; when `renderer` is `playwright`, use the
fallback steps (`scenes.js`) and carry the FALLBACK warning to the handoff.
`fframes.mjs init` records the renderer in `$WORK/renderer.json`; if fframes
fails later, run `fframes.mjs fallback "$WORK" --reason "<why>"` first, so
`lint.mjs` runs the fallback's page checks. A fallback sticks: a later `init`
keeps it, and only `init --fframes` switches back.

## 2. Scaffold and bring the media in

```bash
WORK="$HOME/.vs/$PROJECT_ID/videos/pr-<N>"
node <skill-dir>/../vs-explain-video/scripts/init.mjs "$WORK"
node <skill-dir>/../vs-explain-video/scripts/fframes.mjs init "$WORK"
node <skill-dir>/scripts/prep.mjs "$WORK" --manifest before=<before manifest.json> --manifest after=<after manifest.json>
```

Use `--still <name>=<file>#<caption>` and `--clip <name>=<file>#<caption>` for
media that did not come from record-flow. `prep.mjs` copies stills, transcodes
every recording to H.264 mp4 (webm seeks badly), cuts each clip's first and
last frame, and writes `media.json`. Do not open the media files. The captions
in `media.json` say what each one shows. A PR without media gets a
motion-only video; say so in the handoff.

## 3. Write the beats from the diff, then the PR body

The diff says what changed. The body says why, and holds the proof and the
media. Ship-it writes the body from a chat that can lose context, so the body
can miss a change. Do not read the conversation. Start from the diff:

```bash
node <skill-dir>/../vs-explain-video/scripts/diff.mjs "$WORK" --base origin/<base> --head <head SHA>
```

It writes `diff.json`: each changed file, with tests, lockfiles, version
bumps, and generated files marked minor. With no checkout, save
`gh pr diff <N> --repo <owner/name>` to a file and pass `--patch <file>` (keep
`--head <head SHA>`). A blocked run deletes `diff.json`.
Read the diff of each file that is not minor and write one line per change:
what it does. Then read the body file and `media.json` for the why, the
proof, and the media. The body must not contradict the diff. Write
`script.json` (format: the explain-video example) with one scene per role, in
this order, and set `"role"` on each:

`problem` → `before` → `change` → `after` → `risk`

| Role | Source | Beats |
| --- | --- | --- |
| `problem` | Body: TL;DR line 1, What problem / scenario | 1-2 beats: who is blocked and the cost |
| `before` | Body: **Before** proof | The real example: `"still"` or `"clip"` from `media.json` |
| `change` | The diff's change list; body: What was done | One mechanism, as pseudocode or a short flow |
| `after` | Body: **After** proof | Same example, same framing: `"still"` or `"clip"` |
| `risk` | Body: Review map Risk/Review, Review focus, Still unverified | Where to look first and what is not proven |

A change the diff shows and the body does not name gets a beat in `change`,
or in `risk` as "also changes" when it is small. Set `"covers"` on each scene
to the files it explains, by the exact path in `diff.json` (no directories).
Put each file you leave out in the top-level `"skip"`, with a reason of 3 or
more words. An empty diff blocks (exit 2): get the right head, never go on.

Start with the problem, then lead with the example: from `before` on, the same
user, report, or request moves through every scene. 75 seconds or less in
total (about 150 words a minute); a beat has 24 words or fewer. Write in STE
([../vs-internal-shared/references/ste-writing.md](../vs-internal-shared/references/ste-writing.md)).
Never claim more than the diff and the body prove: cut a beat the diff does
not show. Carry `Still unverified` into `risk`.

Run `node <skill-dir>/scripts/lint.mjs "$WORK" --no-page --head <head SHA>`. It
also checks `diff.json`: it must be for that head, and a changed file that no
scene covers or skips, or a `covers` entry that is not a changed file, fails. Exit 1: fix the named problems first.

## 4. Narrate

`node <skill-dir>/../vs-explain-video/scripts/narrate.mjs "$WORK/script.json" --dry-run`,
then `check-ste.mjs` on `narration.md`, then run narrate without `--dry-run`.
Use the voice and engine it picks; no voice audition. When its summary says
the words were not checked (no whisper), you must say "words not checked" in
the handoff and pass `--words-unchecked` to `attach.mjs`. Never drop it.

## 5. Write the scenes

`ff/src/main.rs` follows the explain-video rules
([../vs-explain-video/references/motion-craft.md](../vs-explain-video/references/motion-craft.md)).
Two kit helpers show the PR's media:

- `s.still("media/<name>.png", x, y, w, h, tf)` draws a card with the screenshot
  fitted inside. Animate it like any block (`s.rise`, `s.pop`, `.dim`).
- `s.clip("media/<name>.mp4", x, y, w, h, tf)` plays the recording in its slot from
  0.7 s into the scene to 0.45 s before its end: its first frame before, its
  last frame after. Draw chips after it to put them on top. Size the slot to the clip's aspect

From vltansky/vs, MIT.

More from vltansky/vs

Signals

Stars
0
Forks
1
Open issues
1
Last commit (this folder)
Oct 24, 2026 (4 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from vltansky

Cite this page

vs-explain-pr skill. Agent Mart. https://agentmart.dev/skills/vltansky-vs-explain-pr (last updated 2026-10-24)