Communitygithub.com

patryk-penczek/ship-video

Makes a launch video, trailer, teaser, demo or how-to clip of the user's own web app, as code. Recreates the app's real UI in HTML, animates it with GSAP to a music track or silent, and renders a frame-exact 1080p60 16:9 MP4 (plus a WebP for READMEs). Use when the user wants a video, promo, trailer, teaser, demo or product film of their app, site or product, a film cut to a track, a Suno prompt or generated beat for such a film, or to change or re-render an existing ship-video film. Not for editing existing footage or screen recordings, generic explainers unrelated to their app, vertical 9:16 video, or Remotion and After Effects projects.

What is ship-video?

ship-video is a Claude Code agent skill that makes a launch video, trailer, teaser, demo or how-to clip of the user's own web app, as code. Recreates the app's real UI in HTML, animates it with GSAP to a music track or silent, and renders a frame-exact 1080p60 16:9 MP4 (plus a WebP for READMEs). Use when the user wants a video, promo, trailer, teaser, demo or product film of their app, site or product, a film cut to a track, a Suno prompt or generated beat for such a film, or to change or re-render an existing ship-video film. Not for editing existing footage or screen recordings, generic explainers unrelated to their app, vertical 9:16 video, or Remotion and After Effects projects.

Works with✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/patryk-penczek/ship-video/tree/HEAD/skills/ship-video

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

What does ship-video do?

You direct and build a 10–45 s film of the user's product. Everything on screen is code: one HTML page, one paused GSAP timeline in absolute seconds, the app's real screens captured from its DOM and animated, rendered frame by frame to MP4.

How the work is shaped. A film lives or dies on choices made before any code: which viewer, which one change the product makes, which story, how long. Those choices go into a one-page scenario the user approves; it costs minutes to change on paper and hours once built. After that, build well, check your own work hard, render, and show the film: the user watches it and tells you what to change. Don't stop for approvals beyond the scenario.

Scripts are in scripts/ next to this file. In Claude Code that folder is ${CLAUDE_SKILL_DIR}/scripts; elsewhere resolve it against this file's directory and call it by absolute path. Below, $S is that folder and <film> the film folder. Run scripts, don't read their source; each takes --help.

Asking. Ask only real decisions (place, music, length, the user's own wording); decide the rest, say it in a line, let them change it at the gate. Ask at three moments only: the opening (step 1), the scenario gate, after the render; never stop mid-work. One shape fits every host: at most 3 questions per round, 2–3 options each, recommendation first, a 1–5 word label, one sentence on what it means for them, no "Other" (the host adds free text). Use the host's question tool (Claude Code: AskUserQuestion; Codex: request_user_input, Plan mode only), else a numbered list with lettered options ("1a 2b") ending "or tell me something else". More than 3 options is two questions, the deciding one first; when an earlier answer settles a question, fold it into the options.

Limits

Say it up front if the request hits one: 16:9 only (no 9:16); web UI (a native app can only be rebuilt from screenshots, less exactly); 10–45 s; macOS, Linux or Windows; output MP4 and animated WebP, no GIF. Setup downloads Chromium and Python packages into ~/.ship-video: a sandboxed host (Codex) needs network access and write access there; if a command is blocked, tell the user which permission it needs instead of retrying.

Start or resume

Check the film folder (ask which if unclear) and start at the first missing piece:

exists in <film>start at
nothing0 Setup
index.html, no PRODUCT.md2 Discovery
PRODUCT.md, no MUSIC.md3 Music
MUSIC.md, no approved SCENARIO.md (Approved: line)4 Scenario
approved SCENARIO.md, no screens.js (or states not yet compared)5 Replicas
screens.js and review/compare/ with every state matching, starter film.js6 Build
film.js with every act built, no out/film-*.mp47 Review
out/film-crisp.mp4 or out/film-motionblur.mp4ask what to change (render.md, Changes after the render)

The user may skip steps ("I have a scenario", "no music", "just build it"): skip them and say so in one line. Skipping the scenario gate needs their explicit words.

Show this checklist in the first reply and when you deliver:

- [ ] 0 Setup   - [ ] 1 Brief   - [ ] 2 Discovery   - [ ] 3 Music
- [ ] 4 Scenario (approved)   - [ ] 5 Replicas   - [ ] 6 Build
- [ ] 7 Review   - [ ] 8 Render and deliver

0. Setup

node $S/lib/check.mjs: instant once setup has run. Only if it reports something missing: node $S/setup.mjs (installs into ~/.ship-video, skips what's there).

1. Brief

Look first: README, package.json, routes, components, the site, existing screenshots and logos (real assets are used without asking). Then ask what's still missing in two rounds back to back (the length depends on the music):

  1. Where it plays: the three likeliest places for this product (a social feed, the website, a README or docs, a help center), the one it points to first. It sets what the viewer knows, whether sound is on, the opening (direction.md, The viewer test) and the minimum text size.
  2. Music: yes or no; recommend no where that place plays muted, and on yes there say the music reaches only the MP4 (a README's WebP is silent).
  3. Second round · Music source (step 3's question, now, so a Suno track is generated while you work) and length: the shortest that shows the product's one change (10–15 s is often best), a longer one, and with music Fit to the music (the track sets it, cut on bars to what the material holds; recommended then).

The film type (launch, one-feature teaser, how-to, landing page) usually follows from the request and the place: state it. Anything they already said answers its question.

A film whose feel they want: break it into a contact sheet (ffmpeg -i ref.mp4 -vf "fps=2,scale=480:-1,tile=6x5" <film>/review/reference.png), list its techniques, borrow those, never its content.

Create the folder: node $S/new-film.mjs <film> (outside the product repo unless they want it inside; --theme light|dark if known; --silent for a film without music).

2. Discovery

A film made from the README shows features; one made from the whole product shows a payoff. Know the product first. For anything beyond a small app, split this into three parallel subagents if you can (subagents.md).

  1. Inventory every route and view from the router, with the states that matter (dialogs, palettes, toasts, empty states, themes) and everything live (charts, maps, canvases).
  2. See each one: with the app running (reuse its server, render.md, Sharing the machine) node $S/capture.mjs <url> <film> --discover writes a screenshot per route to <film>/review/discovery/; Read them. Logins, phones, landing pages: replicas.md, Options. Not running: use its screenshots and docs, and say so.
  3. Find what's new and what's special: the changelog, release notes, gh pr list --state merged --limit 30 if available; the 3–5 moments a user would show a friend; the one change that is the product.
  4. Write <film>/PRODUCT.md: the promise in the product's own words, the viewer, views (core / aside / skip, with screenshot paths), wow moments, the one concrete case that could carry the film, what can't be shown. Show it in a few lines and carry on; corrections can come any time, the gate at the latest.

3. Music

Read music.md. No music: a BPM grid; read direction.md, Silent films. The source question (asked in the opening) shows all three, one line each on what it costs them (a fresh file in ~/Downloads goes in the own-file line):

  • Generated beat: free, licence-free, ready in seconds, a functional score rather than a song. Write beat.json from the planned acts and run music.mjs synth.
  • Suno: a real song shaped to the film's bars; needs a Suno account, about 10 minutes of their time, a paid plan for anything public, so for a public place label it Suno (paid plan) (music.md, Rights). Walk them through it (suno-prompt.md, Walking the user through). Don't wait idle: write MUSIC.md from a GRID DRAFT and draft the scenario while they generate.
  • Own file: copy it to <film>/track.<ext>.

Analyse the track, read the plot, confirm the drop yourself, and write <film>/MUSIC.md with the story role of each section.

4. Scenario

Read direction.md and write <film>/SCENARIO.md from scenario-template.md: the viewer, the story (problem → hero → action → payoff on the drop), every shot with its seconds, what moves and where the camera lands, the final copy word for word. Run the template's self-check and fix the "no"s first. Tell the user if the length doesn't fit the material and offer the better one.

Then ask, in one round: variants only where the wording is theirs, and "Approve the scenario?" (Approve / Change timing / Change scenes) with the story in three lines and the shot table.

5. Replicas

Read replicas.md. With the app running, its own DOM and CSS are the replica: write <film>/states.json with every state the scenario needs (both sides of each interaction), run capture.mjs … --css, then compare.mjs, and Read the comparison PNGs until each state matches. Without a running app, build from the components and say so in the report.

6. Build

Read film-api.md and shots.md. Set track, duration, hits (music.md) and fonts/images from the capture output, then write the scenes in scenario order at the scenario's seconds. Tween the real elements inside the captured screens (direction.md). Where you depart from the scenario, add a line to Changes vs scenario.

Check as you go: node $S/render.mjs <film>/index.html <film>/review/test.mp4 --preset draft --from 0 --to 1 catches a broken page in seconds; the user can open <film>/index.html to preview (Space plays, arrows step, ?t=12.5).

7. Review

Look at the film as a director before anyone else does:

node $S/sheet.mjs <film>/index.html <from> <to> <step> <film>/review/sheet-<act>.png
node $S/shots.mjs <film>/index.html <film>/review/stills <t1> <t2> … --label

One contact sheet per act (0.25 s steps for type, 0.5 s for UI), full-resolution stills of each cut + 0.01 s, the payoff and the end card. Read every image and run the self-check from scenario-template.md on the frames; zoom into every interaction at 0.1 s steps, since most "unfinished" feel lives in those half seconds. Then get one fresh critic's opinion (subagents.md) and fix what holds up. Finish with node $S/audit.mjs <film>/index.html until clean (render.md, Audit).

8. Render and deliver

Read render.md: render crisp in the background, verify it (hits.mjs, motion.mjs), fix and re-render if needed, then deliver (Deliver: the folder opens, a first cut, one question).

References

fileread at
references/direction.md4, and again in 6 and 7: the viewer test, story, structure, pacing, framing, film types
references/scenario-template.md4 (template and self-check), 7 (self-check on the frames)
references/music.md3: analysis, MUSIC.md, silent grid, generated beat, rights
references/suno-prompt.md3, when the music comes from Suno
references/replicas.md2 (capture options) and 5
references/film-api.md6, before writing film.js
references/shots.md6: recipes with code
references/subagents.md2 and 7, if your host can run subagents
references/render.md7 (audit) and 8; Sharing the machine before starting servers or renders

Related Skills