reel-kit
AGENTS.md1 starsChanged 54 days agoMITView on GitHub
One video = one folder cloned from this kit. CLAUDE.md is a symlink to this file, so both agents read the same map. The playbook is Nate Herk's short-form-edit skill, kept verbatim in .claude/skills/ (Codex mirror: .agents/skills/). This file does not rewrite it. For each of Nate's steps it names the local tool that does the work and the gate where the user says "ok". When in doubt, Nate's skill wins; this file only says how we run it here.
- Reads credentials
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,439 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository28 other files it gives its agents.
- hyperframes-animationSkill
- hyperframes-audioSkill
- hyperframes-cliSkill
- hyperframes-coreSkill
- hyperframes-creativeSkill
- hyperframes-keyframesSkill
- hyperframes-registrySkill
- hyperframesSkill
- hyperframes-studioSkill
- hyperframes-video-beatsSkill
- media-useSkill
- motion-graphicsSkill
- short-form-editSkill
- video-storytellingSkill
- hyperframes-animationSkill
- hyperframes-audioSkill
- hyperframes-cliSkill
- hyperframes-coreSkill
- hyperframes-creativeSkill
- hyperframes-keyframesSkill
- hyperframes-registrySkill
- hyperframesSkill
- hyperframes-studioSkill
- hyperframes-video-beatsSkill
- media-useSkill
- motion-graphicsSkill
- short-form-editSkill
- video-storytellingSkill
The file
We split this AGENTS.md into the rules it gives an agent
3 rules. About 0 are common, 0 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
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 12
If ./setup.sh has never been run on this machine, run it first and read its output.
- Very specific: line 52
If the caption has a keyword call to action ("comment KEYWORD"): create_comment_automation on the Instagram or Facebook account with …
- Very specific: line 115
Every timed value accepts a word anchor: "at": "w:word" = the start of that word in the transcript.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md 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
reel-kit — the map (Claude Code and Codex)
One video = one folder cloned from this kit. CLAUDE.md is a symlink to this file, so both agents read the same map.
The playbook is Nate Herk's short-form-edit skill, kept verbatim in .claude/skills/ (Codex mirror: .agents/skills/).
This file does not rewrite it. For each of Nate's steps it names the local tool that does the work and the gate where the
user says "ok". When in doubt, Nate's skill wins; this file only says how we run it here.
The user validates at every gate. Nothing is built before the "ok" on the current gate. That is the whole method.
First run: setup
If ./setup.sh has never been run on this machine, run it first and read its output. It names each missing tool with the
command to install it. If no transcription engine is set up, walk the user through it in plain words: option A, an
ElevenLabs key (they create it at https://elevenlabs.io/app/settings/api-keys and put it themselves in a .env file in
the project, ELEVENLABS_API_KEY=…, or in their shell profile; never ask them to paste the key into the chat, and if a
key appears in the chat, tell them to revoke it); option B, ./setup.sh --whisperx for a free local engine. Then run
./setup.sh again. For gate 7, the user connects PlugKit's MCP server from their PlugKit dashboard (MCP page); confirm
it with a whoami call before any publication step.
Read in this order
RUN.mdof the project: state, gates ticked, decisions..claude/skills/short-form-edit/SKILL.md(the playbook) and its references:quality-gates.md,plan-schema.md,curiosity-and-entertainment.md,reference-analysis.md,premium-motion-and-footage.md.DESIGN.md(the kit's default paper look) andMOTION.md(motion rules and verification). A brand brief supplied by the user (tokens from a site capture, a logo, fonts) replaces the kit's look for that project.hyperframes-corebefore writing any composition;hyperframes-video-beatsandvideo-storytellingto plan beats.
The seven gates
| # | Gate | Nate's step (short-form-edit) | Tool here | The user validates |
| 1 | Framing | Probe source and reference | Rush copied, never moved. ffprobe (format, rotation, pix_fmt). 16:9 rush → three vertical crops proposed on three moments. takes.py converts HEVC / 10-bit to H.264 yuv420p itself. | the crop |
| 2 | Rough cut | Silence + mistake tools, manual transcript review, render the clean cut once | python3 scripts/takes.py <rush> → assets/derush/: measured silence threshold, cut points on the waveform, transcription (ElevenLabs Scribe, words grouped per take, numbers as digits; WhisperX locally if no key), retakes and false starts detected, decision list printed; on a quiet or noisy track that yields one long take it splits on the word gaps of a whole-file Scribe transcript instead. Every clip is tone-mapped to SDR bt709 on the way in (scripts/sdr.py): an HDR source would switch HyperFrames to its HDR pipeline, which ghosts hidden layers. Then python3 scripts/stage.py: trim + concat → assets/speaker.mp4, assets/reel-audio.wav, assets/transcript.json, assets/edit-decisions.json. | the take list, then the cut-only video |
| 3 | Captions | Captions | Ask the user first: default look (pop, white, keywords enlarged, no color), pop with an accent color (caption_accent), kit or nate, or the captions of their reference reel (look at its frames, then match words per caption, font, color, position). One-scene storyboard.json (layout F) → build-reel.py → draft render. | caption style, spelling of names (lexicon) |
| 4 | Beats and assets | Reference analysis, asset shortlist, DESIGN.md, beat plan, OPEN-LOOPS | REFERENCE-ANALYSIS.md (timecode / idea / visual / sound / question / payoff), DESIGN.md of the project (audience, direction, shortlist, three opening concepts, sequences), OPEN-LOOPS.json, the beats table in chat, one line per beat, bare moments included. Footage: real screenshots first (npx hyperframes capture <URL> → assets/captures/<slug>/, brand tokens in extracted/), the user's own asset bank, then clips the user points to or the agent finds: python3 scripts/footage.py <url-or-file> --slug x --from 12 --to 18 --why "…" --rights "…" → assets/broll/x.mp4 + assets/broll/ledger.json (build-reel.py then writes assets/footage-ledger.json for the clips actually used). Every asset has a provenance and a usable interval. No invented mockup when the real thing exists, no generated footage unless the user asks. | the beats table line by line, each B-roll with its reason and its rights |
| 5 | Opening | Three rough openings, compare the first 3 s | Three first frames (HTML + headless Chrome, or three storyboards) side by side. Choice and reason written in DESIGN.md. | A / B / C |
| 6 | Animatic → final | Animatic before polish, build the visual world, layers and actions, music, lint / preview / draft / final | Full storyboard.json → python3 scripts/build-reel.py → compositions/, index.html, captions, assets/plan.json. npm run check at 0, node .claude/skills/short-form-edit/scripts/validate-plan.mjs ., validate-footage.mjs . when B-roll is used, draft render → the user's feedback in sentences → v2, v3. Then Studio (npm run dev, give the exact URL printed) and npm run render. Three correction rounds max. Music and SFX (media-use, hyperframes-audio, 14–20 dB under the voice, −16 LUFS) only if the user wants them. | each animatic, the Studio pass, the final render |
| 7 | Publish | Delivery, VERIFY | VERIFY.md (hash, what was actually checked), ENTERTAINMENT-REVIEW.md. Publication through PlugKit's MCP server, see below. | caption, keyword, date |
Gate 7 with PlugKit
PlugKit is connected to the agent as an MCP server (Claude Code or Codex). The calls, in order:
whoami→ the profile and the connected accounts (Instagram, Facebook Page, TikTok, YouTube, X, LinkedIn).create_media_uploadwith the file name →uploadUrl,mediaUrl,singlePutMaxBytes. The agent holds the file, so it sends it itself:curl -T renders/<slug>.mp4 "<uploadUrl>". AbovesinglePutMaxBytes, hand the useruploadPageUrlinstead.check_media_uploadwith themediaUrluntil the file is there.create_postwithprofileId,accountIds,content(the caption the user approved),mediaUrls: [mediaUrl], and eitherscheduledFor+timezone,publishNow: true, or nothing (draft). Reels on Instagram:shareToFeeddefaults to true. TikTok: readget_publish_optionsfirst and let the user choose the visibility.- If the caption has a keyword call to action ("comment KEYWORD"):
create_comment_automationon the Instagram or Facebook account withkeywords,dmText,dmButtonLabel+dmButtonUrl, before the post goes live. A comment posted before the automation exists never gets its DM.
Nothing is uploaded or published without the user's explicit "ok" on the caption, the keyword and the date.
Files of a project
<project>/
├── RUN.md · DESIGN.md · REFERENCE-ANALYSIS.md · OPEN-LOOPS.json · ENTERTAINMENT-REVIEW.md · VERIFY.md
├── storyboard.json scenes, the source of the build (format below)
├── assets/ speaker.mp4, reel-audio.wav (ignored by git) · transcript.json · edit-decisions.json · plan.json (generated)
│ derush/ (raw.mp4 ignored, raw.segments.json, raw.captions.json, takes.json)
│ broll/ (clips ignored, ledger.json) · footage-ledger.json (generated) · captures/ · brand/ · fonts/
├── index.html · compositions/ generated by build-reel.py, never edited by hand
├── scripts/ takes.py · transcribe.py · stage.py · footage.py · build-reel.py · preflight · beat-sync · frames · sync-codex-skills
└── .claude/skills/ (canon) · .agents/skills/ (Codex mirror) · .codex/config.tomlstoryboard.json
{ "id": "slug", "title": "…", "duration": 35.8, "fps": 30, "speaker": "assets/speaker.mp4", "audio": "assets/reel-audio.wav",
"caption_style": "pop", "caption_font": "\"Helvetica Neue\", Helvetica, Arial, sans-serif", "caption_size": 62,
"caption_max_words": 3, "keywords": ["salaries", "managers", "40 825"], "lexicon": {"cloud": "Claude"},
"brand": {"bg": "#F3F1EE", "ink": "#0F0D0D", "accent": "#D40F30", "font": "\"Helvetica Neue\", Helvetica, Arial, sans-serif"},
"locale": "fr-FR", "freeze_tail": 3.0, "face_pos_s": "50% 72%",
"scenes": [
{ "layout": "S", "start": 0, "end": 4.5, "holdReason": "the duel stays on screen until the source", "zone": { "out": 4.35, "items": [
{ "type": "card", "title": "Engineering<br>school", "logos": ["assets/brand/a.png", "assets/brand/b.png"], "cols": 2, "x": 40, "y": 80, "w": 480, "h": 440, "from": "left", "at": 0.15 },
{ "type": "badge", "text": "VS", "x": 480, "y": 150, "at": 2.3 },
{ "type": "stamp", "text": "WHO EARNS MORE?", "x": 130, "y": 590, "at": "w:more" } ] } },
{ "layout": "F", "start": 4.5, "end": 6.5, "cap_top": 1580, "holdReason": "transition, the source is coming" },
{ "layout": "S", "start": 6.5, "end": 8.5, "zone": { "items": [
{ "type": "image", "src": "assets/captures/report/table.png", "x": 40, "y": 120, "w": 1000, "at": 6.55, "highlights": [[419, 395, 81, 31]], "highlight_at": 7.0, "zoom_at": 7.25, "zoom": 1.9, "origin": "48% 76%" } ] } },
{ "layout": "S", "start": 8.5, "end": 14, "zone": { "items": [
{ "type": "card", "title": "Managers", "label": "BUSINESS SCHOOL · 2026 AVERAGE", "value": 40825, "suffix": " €", "count": 0.9, "x": 40, "y": 110, "w": 480, "h": 400, "at": "w:40 825" },
{ "type": "video", "src": "assets/broll/campus.mp4", "x": 560, "y": 110, "w": 480, "h": 400, "at": 10, "media_start": 2, "out_at": 13.5 } ] } },
{ "layout": "S", "start": 14, "end": 21, "zone": { "items": [ { "type": "big", "value": 1540, "suffix": " €", "label": "GAP PER YEAR", "y": 470, "size": 200, "at": "w:1 540", "count": 0.7, "circle_at": 20.6 } ] } },
{ "layout": "S", "start": 31, "end": 35.7, "zone": { "items": [ { "type": "check", "n": "#1", "text": "the jobs you aim for", "x": 60, "y": 120, "w": 960, "at": "w:jobs", "check_at": "w:aim" } ] } },
{ "layout": "S", "start": 35.7, "end": 38.8, "kind": "cta", "holdReason": "end screen", "zone": { "full": true, "gradient": true, "in": 35.8, "items": [
{ "type": "logo", "src": "assets/brand/icon.png", "x": 410, "y": 120, "w": 260, "at": 35.95 },
{ "type": "photo", "src": "assets/brand/team.jpg", "x": 180, "y": 430, "w": 720, "h": 740, "rotate": -3, "drift": true, "at": 36.15 },
{ "type": "line", "text": "Tap the button", "x": "center", "y": 1290, "size": 84, "weight": 800, "color": "#0F0D0D", "at": 36.6 },
{ "type": "chevrons", "y": 1520, "at": 37.05 } ] } }
] }Layouts: F full-frame face, optional overlay (text, image, chevrons) or CTA card keyword · S Nate's split: a screen
zone on top (0→880 px, brand colors) and the face below; zone.items of type card, badge, stamp, image, video,
big, check, logo, photo, chevrons, line; zone.full + in = a full-frame end screen that curtains down over the
face · C / B / D: the paper look of DESIGN.md (face top + paper bottom, paper top + face box, full paper) ·
Y (16:9, needs "format": "youtube" at the top of the storyboard, 1920×1080): a full-frame world with the speaker as a
card that moves inside it, in the shape of a YouTube intro where every sentence triggers what it describes.
"bg": "mesh" (a soft gradient built from the brand accent, slowly drifting) or a path to an image.
"face": [{"pos": "left", "at": "w:mot"}, {"pos": "tl", "at": 11.3}, {"pos": "full", "at": 18}] with full, wide,
left, right, tl, tr, bl, br, center, hidden; the card is cut out of the 16:9 source with clip-path, so a
portrait card never distorts the picture. face_crop_y [x, y] (0 to 1) frames the subject inside the card and
face_zoom_y (1.22 by default) tightens it. zone.items adds to the S list: glass (frosted card, icon, title,
number/count, sub, bars, shot, dark), statement (kicker + big text with <em> + sub), pill (glass
button, arrow), tag (small rounded label), cascade (src list of clips fanned out in 3D, cw, ch, step, tilt,
rise). caption_style: "nate" puts the captions on a dark pill with each keyword in an accent box.
Every timed value accepts a word anchor: "at": "w:word" = the start of that word in the transcript. Scenes must start on a
word (Nate's validator wants an anchor within −0.15 / +0.2 s); a scene with no visual event for more than 2.2 s carries a
holdReason. caption_style: pop by default (Helvetica Neue Bold, word-by-word reveal, keyword ×1.55 in the caption color;
caption_accent colors the keywords), kit (pill, uppercase) or nate. lexicon fixes one word → one word (proper nouns). keywords are matched ignoring case, punctuation
and elisions ("d'ingénieur" matches "ingénieur", "40 825" matches "40 825"). locale (default en-US) formats the numbers in
count-ups and sets the HTML lang; lang overrides the latter. Transcription detects the language on its own
(transcribe.py --lang xx forces it); only French spelled-out numbers are converted to digits.
Commands
./setup.sh # once per machine: checks node, ffmpeg, python, the transcription key, warms up HyperFrames
python3 scripts/takes.py <rush> # gate 2: take list to validate (writes assets/derush/)
python3 scripts/stage.py # gate 2: cut → assets/speaker.mp4, reel-audio.wav, transcript.json, edit-decisions.json
python3 scripts/footage.py <url|file> --slug x --from 12 --to 18 --why "…" --rights "…" # gate 4: B-roll with provenance
python3 scripts/build-reel.py # storyboard.json → compositions + index.html + captions + assets/plan.json
npm run check · npm run preflight · npm run snapshot -- --at 1.5,6 --no-end
node .claude/skills/short-form-edit/scripts/validate-plan.mjs . # Nate's plan gate
node .claude/skills/short-form-edit/scripts/validate-footage.mjs . # when B-roll is used
npm run dev # Studio, in the background; give the user the exact URL printed
npm run render (always --sdr: an HDR source would switch HyperFrames to its HDR pipeline, which ghosts hidden layers) · npm run frames
node scripts/sync-codex-skills.mjs # after any change in .claude/skills/Hard rules
Nothing is built before the user's "ok" on the current gate. Real screenshots over invented mockups. Nothing on the face, no
cutout, no matting. Media never in git. Exact spelling of proper nouns through lexicon. Never edit a generated file. Footage
has a provenance and rights before it enters a beat. No secret on screen: API keys live in the environment, never in a
file, a command line or a message. Nothing is uploaded or published without the user's explicit ok.
HyperFrames contract, reminder
Root div with id, data-composition-id, data-start="0", data-duration, data-width, data-height. Every timed element:
data-start, data-duration, data-track-index, class="clip"; the track is only time, the visual order is z-index. One paused
GSAP timeline per composition on window.__timelines["<id>"]. Sub-composition: everything inside <template>, root #root,
host id = inner id. Strict determinism. See MOTION.md.
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.

