Clips
Paths:
means the folder containing this SKILL.md, and
the plugin folder two levels above it.
Read
${CLAUDE_PLUGIN_ROOT}/PRINCIPLES.md
first: the rules every video in this plugin follows (asking, looking real, motion, story and framing, privacy, cost).
Every question to the user goes in the question box: call the AskUserQuestion tool (2-4 options, the recommended one first). Only in an agent without that tool, ask numbered questions in text.
One long video in. The best few short clips out, each a finished vertical edit in the user's style.
clips/<name>/
source.mp4 the long video (a symlink for a local file; never modify the original)
source.mp3, cover.jpg instead, for an audio-only podcast: its audio and the show's artwork
words.raw.json one transcript of the whole thing (never read it)
candidates.json every candidate with its features (never read it)
shortlist.md the top 8 that do not overlap, about 1,500 tokens: the only file you read
shortlist.json the same, for the page
picks.html the page the user picks from
edits/<name>-clip<N>/ one edit per chosen clip: source.mp4, words.raw.json (re-timed), clip.json
Run the scripts with
on Mac and Linux,
on Windows.
PY="${CLAUDE_PLUGIN_ROOT}/lib/ai_editor/run.py"
;
below runs the editor's venv Python (
on Windows).
If it is missing, run the
skill first.
K="${CLAUDE_SKILL_DIR}/scripts/clips.py"
,
C="${CLAUDE_PLUGIN_ROOT}/skills/cut/scripts"
,
S="${CLAUDE_PLUGIN_ROOT}/skills/style-edit/scripts"
.
0. Ask, once
Read the profile and taste first (
python3 "${CLAUDE_PLUGIN_ROOT}/lib/ai_editor/profile.py" show
,
python3 "${CLAUDE_PLUGIN_ROOT}/skills/taste/scripts/taste.py" show
). No profile yet: run the
skill's style intake first, so the clips come out in the user's look.
Then one question box call, the recommended option first:
| question | options |
|---|
| How many clips? | 3 (Recommended) / 5 / 1 |
| How long should each be? | 20-40 s (Recommended) / 40-60 s / 60-90 s |
| How many people talk in it? | one (Recommended) / two (a podcast or interview) |
Skip any the user already answered. These replace the cut skill's "cut first or everything at
once" question: clips run straight through, and the user approves the picks and the stills sheets.
1. The video
A local file (a hard link on the same drive, else a symlink, a copy only as the last resort):
bash
python3 "${CLAUDE_PLUGIN_ROOT}/skills/clips/scripts/clips.py" link "<absolute path>" clips/<name>
A link:
bash
python3 "${CLAUDE_PLUGIN_ROOT}/lib/ai_editor/links.py" fetch "<url>" clips/<name> --max-height 1080
It uses the venv's yt-dlp (setup installs it there, not on the PATH), caps the download at 1080p (a
1080x1920 clip needs no 4K; a 20-minute talk at 4K is several GB) and prints the file path:
. Exit 3: the site wants a login (YouTube's "confirm you're not a bot").
Ask in the question box before re-running with
--cookies-from-browser chrome
(or their browser).
A podcast (RSS feed or Apple Podcasts show link):
lists its newest episodes as
options; ask
which one in the question box (newest first), then
fetch "<option url>" clips/<option name> --direct --cover "<option image>"
:
the audio lands as
(or its own extension) and the show's artwork as
.
Only download what the user has the right to reuse: their own video, or one
they have permission for. Say so once if the link is someone else's.
2. Transcribe once
bash
python3 "$PY" "$C/transcribe.py" clips/<name>/source.mp4 clips/<name>/words.raw.json # the file fetch printed: source.mp3 for audio
Say the time first: Whisper takes 1-4 minutes per 3 minutes of video on a laptop (free), Scribe
about 20 s for a 13-minute video. Same engines as the cut skill. Scribe adds laughter and other audio events, which the score uses.
Every clip reuses this transcript: nothing is transcribed twice.
3. Candidates and the shortlist
bash
python3 "$K" candidates clips/<name> --min 20 --max 40 [--speakers 2] [--style creator-teardowns/<handle>/style.json]
Pass the length the user picked.
is the profile's first creator: the "what works" moves
measured there are listed in the shortlist. Code splits the transcript into sentences and makes every run of
whole sentences inside the length a candidate (never starting on "Mm-hmm" or ending mid-word),
measures each, ranks them by the features, and writes
.
Read
only. Each entry has the hook, the opening words of every middle sentence, the
last sentence and the measured features. Judge each entry on four questions: does the hook work
alone, can a stranger follow it, does it pay off, is there a concrete claim, number or story.
Never read
or
. Pick the user's number of clips from the
shortlist, best first. Drop, whatever the score:
- an ad read, a sponsor segment, an intro or a sign-off;
- a hook that leans on earlier context ("as I said", "that's why", "this one");
- a clip whose point is a dated claim ("at the time I'm recording this, it's number 40") when the
claim has since changed: a live capture of today's page would contradict it.
4. The picks page, then the question box
bash
python3 "$K" page clips/<name> --recommend c12,c40,c7
open clips/<name>/picks.html # Windows: start "" ..., Linux: xdg-open ...
One page: every shortlisted clip with a 360 px preview, its transcript (the hook in bold), the
score breakdown and the measured features, your picks marked. Then ask in the question box
(multi-select): your picks first, each labelled with its time and its hook, plus "a different one
from the page". Wait for the answer.
5. Each chosen clip
bash
python3 "$K" trim clips/<name> c12 c40 c7 # -> edits/<name>-clip1, -clip2, -clip3
Each edit folder gets
(frame-accurate, padded without catching the next word) and
re-timed to it. An audio-only source (
) has no picture: trim makes each
clip's
its audio over the podcast's own cover (the cover blurred and dimmed to fill 1080x1920,
the sharp cover above the captions; no artwork: black), and
says
. With a cover, the
render moves it: a slow push on the cover, the ground drifting against it, a small punch on each sentence start. For those,
don't ask a layout: overlay, reframe no, no cutout, captions on (
keeps them on). Say once
that each clip is the audio over the show's cover with the speaker's words as captions. Before the clips run, settle music once for all of them
(style-edit
"Music"; the style decides unless the user set
).
All clips at once (Claude Code, or any agent with subagents): launch one
agent
(
) per clip,
all in one message so they run at the same time. Give each
(the clip's folder, absolute),
(
), the
line, and the answers:
aspect, layout, music, the transcription engine, and reframe yes (a wide source, unless the platform is
YouTube) or no, and whether the source has captions burned in. Each takes its clip through the cut and style-edit to the stills sheet and returns a
short JSON:
,
,
,
,
,
. Merge those; never open a clip's
transcript or paper edit. Then run the
agent on every
clip's sheet, again all in
one message, and fix what they fail (plan and stills again for that clip). A
clip: run it by
hand as below.
One at a time (no subagents), for each clip in order:
- Vertical from a wide video:
python3 "$PY" "$K" reframe edits/<name>-clip<N>
crops to 9:16 with the
crop following the speaker's head shot by shot (camera cuts found with ffmpeg). Skip it when the
profile's platform is YouTube or the source is already vertical.
- Cut: the cut skill from its step 2 (): the transcript is already there.
Then build, render, verify and the cut page, as that skill says. Music under the voice is
measured per file: trims only between words there.
- Style:
python3 "${CLAUDE_PLUGIN_ROOT}/lib/ai_editor/profile.py" style edits/<name>-clip<N>
,
then the style-edit skill from its step 2. If the source already has captions burned in, set
"captions": {"present": false}
in that edit's , or the captions stack.
Either way, open every clip's
and show all the stills sheets together for one
approval, ask the render question once for all of them, and render. After approval, run
python3 "${CLAUDE_PLUGIN_ROOT}/skills/cut/scripts/judge_cut.py" score
on each clip's folder (cut
). Hand the renders over on one
review page, each clip a tab (
with clip 1,
for the rest, folder
; see
${CLAUDE_PLUGIN_ROOT}/skills/style-edit/references/review.md
), then
and
in the background.
If a script stops
| message | do |
|---|
no run of whole sentences lasts <lo>-<hi> s
| ask in the question box for a wider length, run again |
| use an id from |
| exit 3 (a login or "confirm you're not a bot") | ask before re-running with --cookies-from-browser <browser>
|
| any cut or style-edit message | that skill's "If a script stops" table |
Rules
- Every word, number and name on screen comes from that clip's own words. Nothing from the rest of
the video, and nothing the speaker did not say.
- No AI-tell looks:
${CLAUDE_PLUGIN_ROOT}/skills/style-edit/references/ai-tells.md
applies to every clip.
- A close-up podcast frame has no free space: no card or logo goes over the head. Fewer visuals is
right; captions and zooms carry it.
- Never cut a clip mid-sentence. Shorter or longer than asked beats a broken thought.
Cost per long video
Measured on a 13-minute two-person podcast and a 12-minute talking-head video (2026-10):
- Transcription: Scribe took 16-18 s; Whisper is free and slower. Once per long video.
- Candidates and features: 4-6 s of code, $0.
- Claude reads (about 1,500 tokens), never the transcript (about 20,000).
- The picks page: 30-40 s of ffmpeg for 8 previews, 7-9 MB.
- Each clip then costs what one cut and one style edit cost.
Self-check
Files
- : candidates, page, trim, reframe and the offline demo (synthetic transcript).
Stdlib only, except (OpenCV, through the venv).
${CLAUDE_PLUGIN_ROOT}/agents/clip-editor.md
: one clip through the cut and style-edit to its stills sheet.