pr-to-video
Turn a GitHub pull request (a PR URL, owner/repo#N, or 'this PR' in a checked-out repo) into a code-change explainer video — changelog, feature reveal, fix, or refactor walkthrough built from the diff, commits, and files: the input is a code change, not a website. Not a product promo (/product-launc
By heygen-com · 207,398 installs
npx skills add heygen-com/hyperframes --skill pr-to-video
Source repository · Upstream listing
First, keep this skill fresh — confirm with the user before running: npx hyperframes skills update pr to video . A fast no op when everything is current; otherwise it refreshes this skill plus the core domain skills it depends on before you rely on them.
media use : Before sourcing audio/images/logos, call /media use to resolve BGM/SFX/images from the HeyGen catalog and brand logos from their official sources. Run adopt first to register existing assets. See /media use skill.
PR to HyperFrames
Use this skill to ingest a GitHub pull request, understand the change, plan a code change explainer, and build it frame by frame in HyperFrames. The input is a code change (read via gh ), not a website — there is no capture step and no real assets beyond the contributors' avatars.
The front door is /hyperframes . You are the orchestrator. Run each step, verify its gate, and only then continue. This skill is for a GitHub pull request (a code change). Any other intent, a bare "make a video", or any uncertainty → read /hyperframes first — the intent layer owns every route decision, and a fresh creation arriving here without BRIEF.md goes through it anyway (Setup's opening rule).
You are the orchestrator. Work in the resolved external PROJECT DIR , never in the caller repository by default. Run steps in order and pass each gate before continuing. User gated steps are Step 0, Step 3, and Step 6. Read ../hyperframes core/references/brief contract.md before Step 0 — it defines the gate types and how BRIEF.md 's flow / storyboard derive the mode that governs the Step 3/4/6 gates. Do every step yourself except Step 5, where you dispatch a bounded pool of frame workers. Do not put design or motion rules here; those live in the frame worker sub agent, this skill's local ../hyperframes animation/rules/ + ../hyperframes animation/blueprints/ , and hyperframes creative .
Workflow: Step 0 setup → hyperframes.json ; Step 1 ingest → capture/extracted/ + assets/<login .png ; Step 2 design system → frame.md ; Step 3 storyboard/script → STORYBOARD.md and SCRIPT.md ; Step 3.1 audio → audio meta.json ; Step 4 visual design → enriched STORYBOARD.md ; Step 5 frames → compositions/frames/NN .html and index.html ; Step 6 final render → renders/video.mp4 .
Step 0: Setup
Goal: Enter with a confirmed brief — including the PR reference (a full URL, an <owner /<repo <N ref, or "this PR" in a checked out repo) — create the HyperFrames project, and make the brief durable. The style is always code editorial (fixed at Step 2, never asked).
The brief is confirmed by the intent layer, not by questions asked here. Opening rule, in order: (1) BRIEF.md exists → read it and ask nothing — the brief is settled, and its flow / storyboard derive the mode (brief contract § 1). (2) No BRIEF.md but the project exists ( hyperframes.json / STORYBOARD.md on disk) → resume from the storyboard's frontmatter and the recorded preferences; never re interrogate a half built project. (3) Neither — a fresh creation request that arrived here directly → read /hyperframes and run its intent layer ( references/intent interview.md ): it checks recipes and remembered defaults, and conducts this route's questions — including the PR size → length doctrine, which lives whole in ../hyperframes/references/routes/pr to video.md — then hands back the locked brief. Edit requests skip all of this — go do the edit.
Resolve the project directory before doing any other work. Preserve a user supplied project directory; otherwise use the durable external cache location printed by the resolver. Never create videos/ in the caller repository:
The capability preflight runs before fetch, story work, audio, or frame dispatch. If the installed CLI cannot run the validation command required by this skill, stop with its upgrade instruction rather than spending the run's context first.
Initialize only if $PROJECT DIR/hyperframes.json is missing. Its basename comes from the PR, such as acme sdk pr 1842 ; never use the workspace name or a timestamp.
npx hyperframes init "$PROJECT DIR" non interactive example=blank skill=pr to video — init checks the installed skills against the latest on GitHub and updates the global set if any are out of date.
Every relative path command below runs with $PROJECT DIR as its working directory. Examples without an explicit subshell mean (cd "$PROJECT DIR" && …) ; never change the caller repository's working tree.
Write BRIEF.md immediately after init (never before — init refuses a non empty directory): the intent layer's locked brief, shape per ../hyperframes core/references/brief format.md . Resolve <MEDIA DIR as the installed /media use skill directory. Then record each preference backed answer with node <MEDIA DIR /scripts/prefs.mjs record hyperframes . ( brief format.md names the subset). If the intent layer adopted a recipe, run node <MEDIA DIR /scripts/recipe.mjs use hyperframes . name <name ; it copies its frame.md into the project (Step 2 is then skipped) and returns the skeletons Step 3 drafts from. A recipe fills answers, not approvals; the review gates still run.
Show sign in status before proceeding past Setup — run npx hyperframes auth status and relay its output verbatim. It reports whether voice/BGM will use HeyGen or local engines and, when signed out, how to sign in. Apply one branch:
Collaborative: wait for the user to sign in or explicitly choose offline / go .
Autonomous: state the status and continue through the available local engines.
Do not silently omit a required capability when no offline provider exists; surface the blocker. Do not fold this decision into another question or write keys into a per repo .env . Auth ownership and offline fallbacks: /media use references/setup providers.md § Providers.
Gate: hyperframes.json and BRIEF.md exist; the PR ref is captured in the brief; the preference backed answers were recorded (brief contract § 2); sign in status was shown (signed in, or continuing offline).
Step 1: Ingest the PR (no capture)
Goal: Fetch the PR's facts and fold them into the project as the source of information. There is no website capture . fetch pr.mjs runs gh deterministically — completing the files list via paginated gh api so a large PR doesn't truncate at ~100 files, and writing only capture/pr.json + capture/diff.patch (no scratch dir). For MERGED PRs it also resolves a best effort shipped version (+ version source ) into pr.json , so the end card can cite a real version instead of inventing one. Then ingest.mjs folds that into the synthetic capture package offline.
If fetch pr.mjs exits 1 (gh auth / not found / private), report its stderr and stop — do not fabricate PR contents . If ingest.mjs exits 1, read its stderr (usually a malformed pr.json ), fix, and rerun (deterministic). fetch people avatars.mjs always exits 0; missing avatars just mean no credits close to author.
people.json carries a name for whichever contributors gh already named (the PR author, commit authors, mergedBy ) — null for the rest (reviewers/commenters/assignees, which gh pr view only ever gives a bare login ). Before writing the credits close in Step 3, resolve any null name yourself for the 1 6 people who'll actually appear on that frame: gh api users/<login jq .name (you already have gh — no need to script this). If GitHub has no public name for that user either, fall back to the login on screen and drop that person from the spoken line (see story design.md's credits section — the voiceover must still say names, never raw handles).
Gate: capture/pr.json , capture/diff.patch , capture/extracted/tokens.json , capture/extracted/visible text.txt , and capture/extracted/people.json exist; you can state the PR's change in one clear sentence. assets/<login .png is best effort — its absence is not a failure.
Step 2: Design System
Goal: Adopt the code editorial frame preset; a script turns it into this video's frame.md + caption skin.
The style is fixed — code editorial (warm editorial; a navy code surface built for diffs). Run:
The script copies the code editorial preset's FRAME.md → frame.md , remixes it onto any brand tokens in capture/extracted/tokens.json (a PR has none → colors:[] / fonts:[] keeps code editorial's own palette, a complete design), copies the preset's caption skin to .hyperframes/caption skin.html , and self validates (exits 1 on a broken mapping). Proceed as soon as it exits 0 — no hand editing.
Gate: build frame.mjs exited 0 — frame.md exists from the code editorial preset, and .hyperframes/caption skin.html exists as the caption skin source.
Step 3: Storyboard and Script
Goal: Turn the PR into an approved frame by frame explanation plan.
Read ../hyperframes creative/references/story spine.md (hook language, value before evidence, storyboard as proposal, source traceable visuals), references/story design.md , ../hyperframes animation/blueprints index.md , ../hyperframes core/references/storyboard format.md , and ../hyperframes core/references/script format.md . Use them to write STORYBOARD.md and, when narration is needed, SCRIPT.md . Set the frontmatter duration: from the brief's length — a rough expectation; assembly reports where the cut lands against it.
Use story design.md for the PR archetype (changelog / feature reveal / fix explainer / refactor walkthrough), the PR native frame types, hook, persuasion, beats, the per frame word budget, and the credits close. The sequence comes from narrative design, not the diff's file order — explain the change, don't read the diff aloud. As a soft guide , consult the role→blueprint menu in ../hyperframes animation/blueprints index.md : for each beat, write the voiceover in the shape its candidate blueprint implies and tag that candidate blueprint: id when one fits (story truth still decides which beats exist — never force a beat to fit a shape). Feature 2–4 real diff hunks (from capture/diff.patch ), each a small legible snippet; name the code block each wants in the frame's scene . Frames carry no asset candidates except the credits close (1–6 assets/<login .png avatars). Use the exact required fields from the storyboard and script references.
After drafting, run the review loop's plan pass — ../hyperframes core/references/review loop.md § 1: open the board (don't ask whether to — run the preview from PROJECT DIR in the background), present the plan as a proposal, and ask the two questions — approve or change, and sketches first (recommended) or skip. Feedback loops through chat or the board's comments file until approved. This is a checkpoint gate (brief contract § 1): in autonomous mode there is no board and nothing to ask — post the same summary as a heads up and proceed; sketches collapse into the build, and the one preview question comes at Step 6.
Gate: STORYBOARD.md exists, every frame has the required narrative fields, SCRIPT.md exists when narration is needed, and the user approved the plan (autonomous: the summary was posted as a heads up).
Step 3.1: Audio
Goal: Generate narration, word timings, music, and audio metadata from the approved script.
Start audio after Step 3 approval. Run it in the background, then continue to Step 4.
Choose the narration voice from the user's ask before invoking. If the request named a voice, gender, or tone, pick a matching voice id and pass it with voice <id . The pipeline default is otherwise Marcia (female) on HeyGen / am michael on Kokoro — so a request like "a male voice" is silently ignored unless you pass the flag. Voice ids are provider specific; resolve against whichever provider Step 0's sign in status selected: HeyGen (signed in) via node <MEDIA DIR /audio/scripts/