Direct an animated film of about two minutes from a software repository's Git history. Select real commits, releases and reverts; develop the story, character and visual style; build an outline, cast sheet, storyboard and HTML review studio; then render a 4K/60fps MP4 after approval. Use for repository or product promos, launches, anniversaries, release stories, codebase timelines, character-led project histories, and requests such as "make a video about our project" or "show how this product grew." Not for UI screen recordings, slide decks, or commit-statistics charts.
78
98%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
The user gives you a GitHub link. You direct a film of about two minutes on how that product grew up. The git history is the footage: it supplies the order, the dates and the proof. Your job is to turn it into a story a newcomer enjoys and learns from: what the product is, how it got here, what it can do for them.
Directing means you make the calls and show them, and the user approves. You own three things:
A mascot hatching and walking along the timeline is one form, not the only
one. The same growth can be staged as something growing in place, a machine
being built, game levels, a user's days, or a form the product suggests
(references/forms.md). Choose for each product.
The engine in engine/ (MIT, adapted from alesha-pro/tools hand-drawn-canvas-animation,
https://github.com/alesha-pro/tools/tree/main/skills/hand-drawn-canvas-animation; keep its LICENSE with
it) draws and animates, and engine/studio-ui.js turns
any film page into the review studio. examples/raven-story/ is a finished
journey film (128 s, made for EverMind's Raven, with Chinese files in zh/).
Reuse their code; do not start from a blank page.
The instructions and default examples use English. Keep dedicated Chinese film
assets in zh/ and Chinese UI labels as localization data; translating those
into English would remove the Chinese cut. Choose the output language for the
audience, and use --ui zh only for a Chinese storyboard interface.
Clone the repo outside the film folder (git clone --filter=blob:none <url>)
and research it before step 1: run python3 scripts/git_timeline.py <repo>,
read the README feature list and docs, and note the first commit, public
release, busiest day, reverts, hero feature, built-in agents/modules and real
integrations (references/story.md §1, §6). Ask about audience, languages and
where the film will be shown if you don't know.
Set up the film folder, also outside the product repo
(references/production.md §1):
engine/*, scripts/render-hq.mjs and scripts/frames.mjs;npm i and sh scripts/fetch_fonts.sh <dir>;git init with node_modules/ and out/ ignored.For a journey, start from the example. For a Chinese film take
raven-cast.js, raven-world.js, raven-route.js and raven-flight.js from
examples/raven-story/zh/, and the rest (raven.html, raven-score.js,
cast-sheet.html) from examples/raven-story/; for English take everything
from the top level. For another form, keep the example's film HTML, writer and
score as the skeleton and write the world code fresh. Every film HTML loads
studio-ui.js right after core.js. The bundled example links to
../../engine/; when copying it into a flat film folder with the engine,
change those script paths to the local filenames.
Captions carry the voice and the score is synthesized; there is no voiceover. If the user asks for voiceover, say so and offer to leave timed caption gaps for a recorded track.
Seven steps, in this order. Each ends with something the user can look at, and
you stop for their approval before the next. Story, character and pacing are
cheap to change on paper and expensive after a 4K render. Templates, shot
fields and checks are in references/directing.md.
OUTLINE.md with a logline, the form and why it fits, the
protagonist and caption voice, the four-part story arc in four lines, the 3–5
things the film will make the viewer remember (and which gets the most
time), the numbers it stands on, and the look in a line or two.cast-sheet.html with 6–12 expressions, key poses for
each action the story needs (walk or hop cycle, jump, fly, talk, point,
carry), every material they appear in, and a 1×/2×/3× size check
(references/craft.md §1–2, §8).OUTLINE.md to the whole film, about 2:00: acts
and looks with reasons, recurring devices, one line per beat (time, what
happens, feature, commit), the ending, and claims to double-check.shots.json, draw one keyframe per shot with the real cast and world code,
and open the storyboard page:
python3 scripts/storyboard.py shots.json --frames storyboard/frames --out storyboard/storyboard.html --ui en.
These 30 seconds fix the tone, pacing, voice and look for the rest.references/production.md §2). Don't render.studio-ui.js turns into the studio:
python3 scripts/storyboard.py shots.json --js shots.js --out storyboard/storyboard.html, then
open the film HTML. The film is on top with a scrub track (acts as bands,
shots as cells, drag anywhere, play from any point with the score in sync)
and the storyboard below, one frame per shot drawn live from the film;
click a frame to jump there. Iterate on the user's notes until they
approve. Still no MP4.node render-hq.mjs film.html --width 3840 --fps 60, one language at a
time (a 1080p24 file first, --width 1920 --fps 24 --no-cover, only if the
user wants a quick file to share). By default the closing frame is also
written as frame 0, so players and feeds show it as the cover, and it
flashes for one frame before the film starts. Keep it for social uploads;
pass --no-cover for anything played inline or looped. Verify with ffprobe
and a full decode, and report duration, size, resolution and what you
actually looked at. Then swap the storyboard's keyframes for real frames
(node frames.mjs film.html shots <seconds>).Other languages live on a branch. Translate as native copy, not literally; localize references (WeChat → Slack, only if the product has Slack); and re-check every text-heavy frame in the studio after translating, because longer lines collide.
references/forms.md).references/craft.md §3).references/text-and-fonts.md).| When | Read |
|---|---|
| Each step's document, shot fields, the studio, checks before a hand-off | references/directing.md |
| Choosing how the growth is staged (journey, growth, building, levels, companion...) | references/forms.md |
| Evidence, the setup, development, turning point and resolution arc, beats, devices, looks per act, fact checks | references/story.md |
| Drawing the protagonist, poses, motion, props, seams, companions, pixel art | references/craft.md |
| Fonts, captions, translation, spacing, text layout checks | references/text-and-fonts.md |
| Folder layout, preview commands, 4K delivery, sound, pitfalls | references/production.md |
| How the pieces fit in real code (a journey) | examples/raven-story/ (start at raven.html) |
| A text-only storyboard reference with bilingual captions; view live frames in the film studio | examples/raven-story/storyboard/storyboard.html |
| Engine API (palettes, marks, cels, exposure, camera) | comments in engine/core.js, engine/cels.js, engine/studio.js |
| Script | Does |
|---|---|
scripts/git_timeline.py <repo> | daily counts, totals, busiest days, feat/perf commits with PRs, reverts, tags → timeline.json |
scripts/fetch_fonts.sh <dir> [zh] [en] | downloads OFL fonts with licences (zh: wenkai/xiaolai/kuaile; en: comicneue/patrickhand/shortstack/architectsdaughter) |
| `scripts/frames.mjs film.html load | shots |
scripts/storyboard.py shots.json [--frames dir] [--embed] [--js shots.js] [--ui zh] [--length s] | the storyboard page: a storyline strip (acts, durations, time ticks), then the shots grouped by act, text-only or with stills (--embed makes one sendable file). --js also writes the shot data the studio reads |
engine/studio-ui.js | loaded after core.js, makes the film page the studio: scrub track with acts and shots, playback from any point with the score, keys, live storyboard frames; renders (?bare) never build it |
scripts/render-hq.mjs film.html [--width 1920/3840] [--fps 24/60] [--no-cover] [--param k=v] | streaming parallel render straight into ffmpeg, score muxed, closing frame as cover unless --no-cover; writes out/<name>-<height>p<fps>.mp4 |
engine/render.mjs | preview modes at 12/24 fps only: --grid N, --only i,j, --strip start,count (frame indices) |
Requirements: Node 22+, Google Chrome, ffmpeg (Homebrew path may need exporting), Python 3.8+.
EverMind-AI/Raven
25e1b23
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.