motion-explainer
Skill2 starsChanged 16 days agoMITView on GitHub
Use when the user asks for a motion graphic, animated explainer, or explainer video of a pull request, or of how something works ("make a video explaining X"). Renders it with Kit Langton's psychopomp engine and publishes the MP4 privately to files.vaut.dev.
- Reads credentials
2 other projects use a version of this.
Adopted by
Most recently taken up by
- mathruffian-dot/claude-motion-explainertheir own version, first seen Oct 20, 2026
- Robinnnnn/skillstheir own version, first seen Oct 15, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- mathruffian-dot/claude-motion-explainer★ 30same name
- Robinnnnn/skills★ 4same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository26 other files it gives its agents.
- instructions/AGENTS.mdAGENTS.md
- babysit-prSkill
- bambu-printSkill
- claude-code-subagentSkill
- claude-routerSkill
- codex-implementationSkill
- codex-reviewSkill
- file-prSkill
- fleet-execSkill
- full-sendSkill
- full-stopSkill
- handoffSkill
- html-communicationSkill
- jevSkill
- leaving-pr-commentsSkill
- mac-vmSkill
- merge-riskSkill
- modernizeSkill
- pull-upstreamSkill
- qa-ux-planSkill
- qa-ux-verifySkill
- shape-checkSkill
- shape-fixSkill
- sol-loopSkill
- t3-browserSkill
- vaut-file-hostingSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 2 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 27
If $PSY does not exist, tell the user to run fizz ship --rebuild kitlangton-psychopomp.
- Distinctive: line 72
Keep anything you could not verify out of the script.
- Very specific: line 143
If the item is missing, ask the user to run security add-generic-password -U -s elevenlabs -a api-key -w "$(op read …
- Distinctive: line 170
When the user asks for a voice the table does not cover, such as "an old woman", search the ElevenLabs Voice Library.
- Very specific: line 257
Add --force when you re-render a slug that is already published.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Motion explainer
Make a 1080p60 motion graphic that explains one pull request or one mechanism, in the style of Kit Langton's PR explainers (a dark stage of cards, wires, packets, and a particle orb; the bug plays, rewinds, and replays fixed; it ends on an annotated diff). Then publish it to Vaut.
The engine
Psychopomp is Kit's Rust motion
graphics engine. A Ship (fizz ship) clones it at a pinned commit, builds
it, and links ~/.local/share/psychopomp to that checkout.
PP=~/.local/share/psychopomp
PSY=$PP/target/release/psychopomp- If
$PSYdoes not exist, tell the user to runfizz ship --rebuild kitlangton-psychopomp. A plainfizz shipskips psychopomp when its pinned commit has not changed, even if the binary is gone. Do not clone or build it yourself. - The checkout is read-only. Do not edit, commit to, pull, or check out anything in it. If the engine cannot do something, work within it and tell the user what was missing.
$PSYhas no--help: an unknown argument renders a demo video to a file with that name.$PSY planwith no arguments prints the usage.
Read Kit's guidance first
Kit's skills are the authoring manual. Read them before writing a scene, and follow them except where the overrides below say otherwise:
$PP/.agents/skills/psychopomp/SKILL.mdandSTORY.md: the workflow and how to tell the story.$PP/.agents/skills/explainer-motion/SKILL.mdandTECHNIQUES.md: motion rules. Apply them to every beat.$PP/SCENE_PLANS.md(the "Make A Narrated Explainer Reel" section, and "Author With The Score DSL" under "Author With Typed Handles") and$PP/CONTEXT.md: the API and its terms.$PP/scenes/pr-walkthrough/src/stop_stage.rs: the #50042 film this style comes from. Copy its shape; do not start from a blank crate. It leans on helpers in the same crate (Pr,span,header,code_with, andcode_filminfilm.rs;PRSanddiffsinlib.rs), so copy those into your crate too.
Overrides
| Kit's skill says | Do this instead |
Author in $PP/scenes/<name>, add it to the workspace, cargo run -p | A standalone crate in ~/.local/share/psychopomp-scenes/<slug> (step 3) |
| Add missing features to the engine | Work within the engine; report the gap |
| Commit the scene and engine changes | Commit nothing; publish to Vaut (step 7) |
Narrate with Fish Audio, ElevenLabs, or say | ElevenLabs or say as in step 4; Fish Audio is not set up |
Plain, confident narration, no hype (STORY.md) | Keep the words plain, but direct an expressive delivery (step 4) |
Steps
- Establish the facts.
- Pull request: run
gh pr view <pr> --json number,title,body,urlandgh pr diff <pr>(add-R owner/repooutside its repo). Write one sentence each for the broken behavior, the fixed behavior, and the change. - Prompt: investigate the code it asks about until you can state the
mechanism in three to five steps, each backed by a
file:line. - Keep anything you could not verify out of the script.
- Pull request: run
- Storyboard one idea, 30 to 60 seconds.
- Pull request: before (the failure plays), rewind, after (the fix replays in the same space), then the change as an annotated diff.
- Mechanism with no fix: setup, the mechanism step by step, the payoff, then the code that does it.
- Slug:
<repo>-pr-<number>or a kebab-case topic, such asskills-pr-57orvaut-token-rotation. It is also the crate name, so use only lowercase letters, digits, and hyphens, starting with a letter (next.jsbecomesnextjs-pr-12).
Create the scene crate.
S=~/.local/share/psychopomp-scenes/<slug> mkdir -p "$S/src" && cp "$PP/Cargo.lock" "$S/"$S/Cargo.toml:[package] name = "<slug>" version = "0.1.0" edition = "2024" [workspace] [dependencies] anyhow = "1.0" psychopomp = { path = "../../psychopomp/crates/psychopomp" } serde_json = "1.0"The empty
[workspace]keeps the crate out of Kit's workspace, and the copied lockfile keeps every dependency at the engine's version. Havemain.rswrite the reel to$S/<slug>.reel.json(build paths fromenv!("CARGO_MANIFEST_DIR")). Media paths in a plan resolve relative to the plan file, so keepnarration/in$Snext to it.Kit's sound effects (
sfx::*) are named../../assets/..., which only resolves for a scene inside$PP/scenes. Re-root them before writing the reel, orplan renderfails with an ffmpegNo such file or directorythat names no file (plan validateand contact sheets do not catch it):let assets = root.join("../../psychopomp/assets").canonicalize()?; for segment in &mut reel.segments { for media in &mut segment.plan.media { if let Ok(relative) = media.path.strip_prefix("../../assets") { media.path = assets.join(relative); } } }Narrate. Kit's films time every beat to a spoken word. Write
$S/narration/script.jsonas his skill describes, then voice it withcd "$PP"first (narrate.ts writes the clips next to the script):- ElevenLabs, the default. The key is in the login keychain, copied
from 1Password, so reading it never prompts. Kit's
narrate.tsasks for 192 kbps audio, which this ElevenLabs plan rejects (HTTP 403: output_format_not_allowed), so run a copy that asks for 128 kbps:
If the item is missing, ask the user to runmkdir -p "$S/scripts" sed 's/mp3_44100_192/mp3_44100_128/' "$PP/scripts/narrate.ts" > "$S/scripts/narrate.ts" ELEVENLABS_API_KEY="$(security find-generic-password -s elevenlabs -a api-key -w)" \ bun "$S/scripts/narrate.ts" "$S/narration/script.json"security add-generic-password -U -s elevenlabs -a api-key -w "$(op read 'op://Personal/ElevenLabs API Key/credential')"(the same line updates it after a key rotation) rather than falling back to the draft voice. Start the script with"engine": "elevenlabs", "model": "eleven_v4", "voice": "<id>", "settings": { "stability": 0.2, "similarity": 0.65 }, "loudness": "linear", with the voice chosen as below. Low stability lets the voice follow the directions, and linear loudness keeps a whisper quieter than a shout (the default evens out the level within each clip). - Draft, when the user asks for a quick draft or ElevenLabs is
unavailable:
bun scripts/narrate.ts "$S/narration/script.json" --draft. It speaks with macOSsay(SAY_VOICE, default Samantha) and times words with a local Whisper throughuvx mlx-whisper(the first run downloads the model). The draft voice is slower, so 60 to 75 seconds is fine. Tell the user the video uses the draft voice. - No voice, only when the user asks: time beats in seconds instead of
phrases, as
$PP/scenes/hellodoes.
Pick a voice that fits the subject, unless the user names one:
Voice id Character Damian Vep3bcB7LhKa3wfjMiI6deep, intimate, dark George JBFqnCBsd6RMkjVDRZzbwarm British storyteller Brian nPczCjzI2devNBz1zQrbdeep, resonant narrator Tarquin 7cOBG34AiHrAzs842Rdiposh British, Received Pronunciation Clyde QMJTqaMXmGnG8TCm8WQGvintage radio announcer When the user asks for a voice the table does not cover, such as "an old woman", search the ElevenLabs Voice Library. Map the request to filters (
gender,age,accent,language,use_cases,descriptives) and addsearch=only for flavor they cannot express ("pirate"); free-text search alone returns poor matches:curl -s -H "xi-api-key: $(security find-generic-password -s elevenlabs -a api-key -w)" \ "https://api.elevenlabs.io/v1/shared-voices?gender=female&age=old&language=en&sort=usage_character_count_1y&page_size=10" \ | jq -r '.voices[] | select(.free_users_allowed) | [.voice_id, .name, .accent, .description] | @tsv'Pick the best match by its description. The first generation adds a library voice to the user's ElevenLabs account, so do not try voices you will not use.
Direct the delivery the way
$PP/scenes/psychopomp-intro/src/main.rsdoes: put a bracketed direction before every clause ([whispering, conspiratorial, slow] And when a server misbehaves... [screaming at the top of his lungs] YOU BLOW IT UP!!! [calm, sweet, matter-of-fact] And then you rewind it.). Contrast carries it: drop quiet before a reveal, break loud on the impact, snap back to calm. Put the loudest line on the biggest visual hit, usually the failure, and settle into relief on the fix. Capitals and!!raise intensity, and...adds a pause. At this stability a take can speak a direction or garble a word: check each.words.json, and re-voice a bad clip with--only <id>.Anchors match Whisper's transcript, not the script: it writes numbers as digits ("58") and splits brand names ("Eleven Labs"). Check the
.words.jsonfiles, or anchor with alternatives such as.at_any(&["237", "two hundred"]).Build the reel only once narration exists, and rebuild it after every narration or scene change, so its timings match the audio:
cargo run --release --manifest-path "$S/Cargo.toml" $PSY plan validate "$S/<slug>.reel.json"- ElevenLabs, the default. The key is in the login keychain, copied
from 1Password, so reading it never prompts. Kit's
Review before rendering. Get segment spans from
$PSY plan inspect "$S/<slug>.reel.json", then make contact sheets at each segment's before, switch, after, and code beats:cd "$PP" && bun scripts/sheet.ts "$S/<slug>.reel.json" t1,t2,... --theme neutral --shutter --out "$S/output/sheet.jpg"sheet.tsrebuilds the engine and writes frames to$PP/output, which is gitignored; that is the one expected write inside the checkout. Read the sheet and fix, then rebuild and check again:- text that overlaps, clips, or reads against the wrong chip, such as packet labels on a vertical wire against an orb name placed above the orb (put the name below), or a callout that lands on the orb
- file paths cut off in the editor tab
- footers that finish typing just as a cut hides them
- wires left showing after a rewind removes their card (reset the beam's
drawto 0; do not fade it)
A Zoom transition looks unfinished in a mid-zoom frame by design. Then render one segment (
$PSY plan render "$S/<slug>.reel.json" "$S/output/cue.mp4" --cue <scene-id> --theme neutral; it includes the transition into the next segment) and pull frames with ffmpeg at the packet, impact, and halo beats, where the stage looks different from the still sheets.Render.
$PSY plan render "$S/<slug>.reel.json" "$S/output/<slug>.mp4" --theme neutralThis takes about 4 seconds of render per second of video on an M5 Max. Done when
ffprobeshows 1920x1080, 60 fps, AAC audio, and the duration thatplan inspectreports, andffmpeg -i <mp4> -af ebur128=peak=true -f null -shows loudness near -16 LUFS with peaks under -1 dBFS.Publish to Vaut, privately, with a poster frame for links:
$PSY plan frame "$S/<slug>.reel.json" <seconds> "$S/output/<slug>-poster.png" --theme neutral --shutter vaut put --at videos/<slug>.mp4 "$S/output/<slug>.mp4" vaut put --at videos/<slug>-poster.png "$S/output/<slug>-poster.png"Add
--forcewhen you re-render a slug that is already published; the files keep their current visibility, so one the user made public stays public. Use--publiconly when the user asks. GitHub plays only videos uploaded to its own CDN, so a public video goes into a PR as a link, with the poster as an image.Report the video URL, the poster URL, the local path, the length, and the narration engine and voice.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

