@officexapp/vidfarm-devcli 0.21.28 → 0.21.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/.agents/skills/editor-capabilities/SKILL.md +26 -0
  2. package/.agents/skills/vidfarm/SKILL.md +53 -2
  3. package/.agents/skills/vidfarm/recipes/bulk-scripting-with-a-regime.md +65 -0
  4. package/.agents/skills/vidfarm/recipes/cutout-graphics-for-explainers.md +78 -7
  5. package/.agents/skills/vidfarm/recipes/local-edit-render-approve.md +2 -2
  6. package/.agents/skills/vidfarm/recipes/retheme-template.md +1 -1
  7. package/.agents/skills/vidfarm/references/automation-and-local-dev.md +64 -5
  8. package/.agents/skills/vidfarm/references/editor-workflows.md +94 -1
  9. package/.agents/skills/vidfarm/references/hooks-and-virality.md +237 -0
  10. package/.agents/skills/vidfarm/references/onboarding.md +1 -1
  11. package/.agents/skills/vidfarm/regimes/README.md +77 -0
  12. package/.agents/skills/vidfarm/regimes/explainer.QA_REGIME.md +82 -0
  13. package/.agents/skills/vidfarm/regimes/hooks.QA_REGIME.md +117 -0
  14. package/.agents/skills/vidfarm/regimes/product-demo.QA_REGIME.md +92 -0
  15. package/.agents/skills/vidfarm/regimes/short-form.QA_REGIME.md +163 -0
  16. package/.agents/skills/vidfarm/regimes/ugc-testimonial.QA_REGIME.md +82 -0
  17. package/SKILL.director.md +597 -19
  18. package/SKILL.md +18 -2
  19. package/demo/dist/app.js +103 -103
  20. package/dist/src/cli.js +925 -18
  21. package/dist/src/devcli/handoff.js +162 -0
  22. package/dist/src/devcli/interaction-mode.js +154 -0
  23. package/dist/src/devcli/qa-check.js +173 -0
  24. package/dist/src/devcli/qa-regime.js +396 -0
  25. package/dist/src/devcli/sticker-pack.js +396 -0
  26. package/dist/src/devcli/storyboard.js +243 -0
  27. package/package.json +6 -1
@@ -77,6 +77,30 @@ Audio is natively **multi-track**. The timeline mixes UNLIMITED simultaneous `<a
77
77
  - **The headline move — split a combined original when recreating.** When the user recreates a template whose ORIGINAL had music + narration baked into ONE audio track, do NOT reproduce a single combined bed. Rebuild it as TWO independent tracks: a fresh narration track (`/api/v1/primitives/audio/speech`, or same-voice reword via `/api/v1/primitives/audio/regenerate-speech`) at ~1.0, and a separate real music track at ~0.1–0.2 — then mute or `remove_layer` the original combined source-audio layer so the old voice doesn't play under the new one. This hands the user independent voice/music volume and is the elegant workaround for AI TTS being unable to emit narration+music in one file.
78
78
  - **Honesty (ties to the create-media rules):** you cannot un-mix / stem-separate the original's baked audio — the two tracks are BUILT from a fresh narration track PLUS a real music file (owned / user-provided / `browse_files` across `/files` and `/raws`), never a faked "music" layer and never the voice track duplicated. There is no music-generation primitive.
79
79
 
80
+ ## The four charges — structure before polish (hard constraint)
81
+
82
+ Every video you touch has four charges in series, and **you write them before you start moving layers**. Editing is the fun part, so it gets done first and the words get retrofitted — that's how a beautifully-edited video ends up with nothing to stop for.
83
+
84
+ 1. 🪝 **Hook** — the opening line, as text, on screen at `start:0`. A **complete clause** (subject + verb), no jargon, naming a **situation** ("I've quit six businesses") not a label ("anonymity"). Caption chunk 1 is read before any audio — muted autoplay is the default viewing condition, so the text hook outworks the spoken one. Banned openings: throat-clearing, a logo, a title card, a fade from black, context before the claim.
85
+ 2. 🔄 **Loop** — one open question by 0:10, stated **on screen**, closing **inside this video** (name the timestamp; if you can't, there's no loop). The withheld answer must be one the viewer **can't supply themselves** — a loop whose answer they can guess passes every mechanical check and dies in the field.
86
+ 3. 😍 **Payoff** — shown, not summarized, landing before the final beat. The payoff is not the CTA.
87
+ 4. 🎣 **Bait** — one ask, final beat, and tell the user to put it in the post caption too. Never a DM funnel, "follow for part two", or ragebait.
88
+
89
+ **On a re-theme this is the thing you protect.** `editor_context` → `viral_dna.hook` / `retention` / `payoff` / `emotional_punch` tells you what the source's charges were — that structure is *why the template worked*. Rebuild each charge for the new subject; flattening the loop into a product statement is the most common way a re-theme kills a format.
90
+
91
+ Full craft (the three gates, situations-vs-labels with worked fixes, loop mechanics, compliance, diagnosis-by-charge): `load_skill('vidfarm', file='references/hooks-and-virality.md')`. Read it before writing hook copy or re-theming.
92
+
93
+ ## The FIRST FRAME is the thumbnail (hard constraint)
94
+
95
+ Frame 0 is a single frame of ~30 in the first second, and it outweighs all of them: every feed card, share link, embed, and paused player freezes on it, so **more people see that one frame than watch the video**. Whatever you change, check what `t=0` looks like before you call the job done.
96
+
97
+ - **Something real is on screen at `start:0`.** If the opening clip starts at `0.4`, the poster is black — `set_layer_timing` it back to `start:0`, or add a held hook frame at the head.
98
+ - **No entrance transition on the FIRST clip.** `set_transitions` with a `fade-black`/`fade-white`/`flash` intro makes the poster a flat black/white rectangle; a zoom/slide/blur intro freezes it mid-move. Clear the entrance on the opening clip (junction transitions *between* later clips are fine and encouraged).
99
+ - **The hook words are already up at t=0** unless you're deliberately opening on a clean face/product shot — a poster that states the promise beats a pretty frame that doesn't.
100
+ - **After a re-theme or a scenes replace, re-check it.** Decomposed forks routinely inherit a blank/slate head from the source, and a swapped opening clip is the most common way a good edit ends up with a black thumbnail.
101
+
102
+ Full rationale + the devcli twins (`vidfarm stills --at 0`, `vidfarm qa`) in `vidfarm` → `references/editor-workflows.md` ("The first frame is the thumbnail").
103
+
80
104
  ## The TEXT axis — social-native only, zero HTML slop (hard constraint)
81
105
 
82
106
  You author into HTML, which makes it dangerously easy to build a **web page instead of a video**. This is the #1 way an AI-edited composition betrays itself. Apply on every text/graphic you place — and strip it when a decomposed fork or a pasted brand asset brings one in.
@@ -101,6 +125,8 @@ You author into HTML, which makes it dangerously easy to build a **web page inst
101
125
 
102
126
  **There is no QA tool for you.** The devcli ships `vidfarm qa <dir>` — a free local blocklist pass over exactly the rules above — but it is **devcli-only with no REST twin**, so in the web editor you enforce this by reading your own output. When you hand a heavy job off to a local coding agent, tell them to run `vidfarm qa ./work` before rendering.
103
127
 
128
+ **If the user wants VOLUME, say so and hand it off.** "I need to post daily", "make 20 versions", "test these hooks" is **bulk/scripting mode**, not twenty turns of editor chat: a pinned base fork, a loop varying one thing per variant, and a **`QA_REGIME.md`** — the user's own written quality standard, which exists because nobody reviews variant #37 as carefully as #1. You can't run that loop (no shell, no filesystem), so name the pattern, offer the My Files handoff, and tell them the local agent should run `vidfarm regime init <base> --out ./work/QA_REGIME.md`, edit it with them, and gate the batch on `vidfarm qa ./work`. If they already have a regime file, its rules are still worth reading into your own edits here.
129
+
104
130
  Deeper rationale and the devcli-side twins live in `vidfarm` → `references/editor-workflows.md` ("Social-native visual standard" / "TikTok-native caption standard").
105
131
 
106
132
  ## The `editor_action` verb catalog
@@ -125,6 +125,30 @@ Then **ask whether to remember the choice**, and save it where it will actually
125
125
 
126
126
  If the user hasn't picked yet and you're about to spend, name the cheaper path and the cost, and ask. `vidfarm cost-mode` with no argument prints the current mode + an explanation of each for you to relay.
127
127
 
128
+ ## Ask the SECOND question too: interactive or autonomous?
129
+
130
+ Cost mode answers *how much money may I spend*. It does not answer *how much of the user's own hands may I use* — and that second axis moves quality more than the first. **Ask both.** They are independent: every cost mode (`minimize`, `hybrid`, `rich-ai`, `pure-videogen`) runs in either interaction mode.
131
+
132
+ - **interactive** — the user is willing to do a little manual work at fixed checkpoints, and the video gets better for it. Two checkpoints cover nearly everything: **(1) images** — you write a prompt, they run it in a *free* frontier web generator (meta.ai / ChatGPT / Gemini / a Hugging Face Space) and hand the file back; **(2) raw clips** — you hand over search keywords, they search TikTok/YouTube, download a few with a free online downloader, and point you at the folder.
133
+ - **autonomous** — you finish end-to-end with zero steps from them: source clips yourself (browser control → `raws scan` → public raws), generate within the budget, or do without.
134
+
135
+ **Why interactive usually wins on quality:** the free tiers of the frontier web image models are typically *better* than what an API-key budget buys per image, and a human eye picks better footage than any keyword scan. In `minimize` the gap is not incremental — it's the difference between **no custom art at all** and **a full sticker pack for $0**.
136
+
137
+ **Ask it like this, once, near the start:** *"Two quick settings. First, how much should I spend per video (minimize / hybrid / rich-ai / pure-videogen)? Second — do you want to be in the loop? In interactive mode I hand you an image prompt to run in a free tool (you drop the PNG back) and a keyword list for sourcing clips; it costs you a few minutes and usually looks better. Or I can run fully autonomous."* Then persist it: **`vidfarm mode interactive|autonomous`** (→ `~/.vidfarm/interaction-mode.json`), alongside `vidfarm cost-mode <choice>`. Same memory etiquette as cost mode — offer to record it in `CLAUDE.md`/`AGENTS.md`, ask first. `vidfarm mode` with no argument prints the current pair + the explainer to relay. Per-run override: `--interactive` / `--autonomous`.
138
+
139
+ **The pairings, and what each means in practice:**
140
+
141
+ | | interactive | autonomous |
142
+ |---|---|---|
143
+ | **minimize** | **the sweet spot.** $0 *with* custom art: free web image-gen → `vidfarm sticker-pack`, plus hand-sourced clips. | $0 from stock + existing raws + HTML motion only. No custom art. |
144
+ | **hybrid** | Pay for the one or two shots only AI can do; the user's hands on the hero art. | Pay where it clearly wins, skip the rest. |
145
+ | **rich-ai** | Buy the reusable greenscreen cast, but let the user approve/redo the hero sheet by hand. | Budget does the work; you never stop. |
146
+ | **pure-videogen** | Human approval at script + storyboard gates (strongly recommended — a bad storyboard is expensive). | Fully unattended; quote the number first. |
147
+
148
+ **In interactive mode, MANUAL IMAGE WORK DEFAULTS TO STICKER PACKS.** Never ask for one graphic per round trip — each hand-off costs the user a context switch and costs you tokens re-reading a file. Ask for **one sheet holding every graphic**, then split it locally for $0. `vidfarm handoff image --theme "<what>" --items "a,b,c"` mints the whole brief (prompt + steps + the free tools + the follow-up command); `--single` when you really do want one subject. When the file comes back: `vidfarm sticker-pack <sheet> --items "a,b,c"`.
149
+
150
+ **Raw-clip sourcing has a ladder — hand it to the human only at the bottom rung.** In order: (1) **your own browser control**, if you have it — drive the search and download yourself; (2) **Vidfarm cloud** — `vidfarm clipper <url>` / `vidfarm raws scan <url> --cloud` resolves and mines the video for you; (3) the **free public raws catalog** — `vidfarm public-raws --category <shelf>`; (4) **the user**, when you're fully local/keyless or when human taste matters. That last rung is `vidfarm handoff raws --keywords "villa construction,pouring concrete" --platforms tiktok,youtube --purpose "<what the clips are for>"` — it prints the keywords, tells them to google a downloader (a *search*, not a link that rots), and names the import command for when the folder is ready (`vidfarm clipper ./downloads/<file>.mp4`, or `vidfarm raws scan` to mine a long one).
151
+
128
152
  ## Default stance
129
153
 
130
154
  - Treat the Trackpad Editor as the primary surface. Reach for templates and forks before primitives.
@@ -134,6 +158,17 @@ If the user hasn't picked yet and you're about to spend, name the cheaper path a
134
158
  - For heavy edits, read the grounding artifacts before acting: `video-context.json`, `editor-harness.json`, and local `.harness/*` bundles when present.
135
159
  - For agentic rewrites, think in the three axes: scenes, audio, text. Decide whether each axis is a SWAP or a REPLACE.
136
160
 
161
+ ## Storyboard first — the plan pass is a core part of the format now
162
+
163
+ **A composition project carries its plan with it.** `STORYBOARD.md` at the project root holds the ordered frames — one key moment each, with `duration`, `status`, an optional `src` pointing at that frame's sub-composition, a one-line `scene` description, and its `voiceover` line — and the optional `SCRIPT.md` beside it holds the full narration. This is a first-class part of the composition format, not a scratch file: **the Vidfarm editor renders it.** The Storyboard/Preview toggle at the top of the editor shows the plan as a contact sheet with a comment box per frame, tracks each frame through `outline → built → animated`, and hands the director's per-frame comments back to you.
164
+
165
+ That makes the storyboard the **cheapest place to be wrong**, and the natural interactive checkpoint: a plan is free to redo, a rendered scene is not.
166
+
167
+ - **Draft it before you build:** `vidfarm storyboard ./work --init --frames "Hook,Problem,Reveal,Proof,CTA"` (frames accept `Title|one-line scene`). Then fill in each frame's `scene` and `voiceover`.
168
+ - **Read it back any time:** `vidfarm storyboard ./work` prints the frames with their status marks and the current stage; `--json` gives an agent the parsed manifest.
169
+ - **Advance `status` as you build** — `outline` (planned) → `built` (a real sub-composition exists at `src:`) → `animated` (motion done). The editor's review stages are derived from exactly those counts, so keeping them honest is what makes the director's view meaningful.
170
+ - **In interactive mode, gate on it.** Show the storyboard, let the director comment or approve in the editor, *then* build. In `pure-videogen` this is not optional — an unapproved storyboard is the single most expensive mistake available (see the pure-videogen ladder above, and `vidfarm sequence` for the AI shot-sheet pipeline, which is a different thing: `sequence` generates storyboard *images*, `storyboard` maintains the plan *file* the editor reads).
171
+
137
172
  ## Say "create a vidfarm template that…" — reusable by default (the house habit)
138
173
 
139
174
  **Every video a director makes is really a *reusable template*, and Vidfarm's whole leverage comes from treating it that way.** So actively steer the user's language toward it: when someone asks to "make a video" / "create a TikTok" / "cut me an ad," gently reframe and echo it back as **"create a *vidfarm template* that …"** — then build it as a template, not a one-off export. This is a real, common, first-class workflow, not a marketing tic; name it as such.
@@ -169,8 +204,18 @@ Present both harnesses to the director, recommend (A) unless they've asked for p
169
204
 
170
205
  **Explainer/cutout videos — the transparent-sticker workflow.** For explainers (a subject "on stage" while labels, arrows, and props pop in around it), the cheap workhorse is a **transparent cutout sticker**: `vidfarm cutout --generate "<subject>"` AI-generates the graphic on a chroma plate, keys it out, **and trims the canvas down to the subject's true min width/height** — one free local ffmpeg step, no mostly-empty PNG to fight with — then `vidfarm place` + `vidfarm keyframes` scale/position and animate it (zoom, grow, shake, drift). It's the same "generate a reusable element once, then reuse it" thrift as the cheap harness, tuned for stickers. Full guided harness: recipe `recipes/cutout-graphics-for-explainers.md`; placement + zoom/grow/shake/move motion recipes: `references/editor-workflows.md` (“Cutout graphics for explainers”).
171
206
 
207
+ **"Make me a sticker pack" = ONE greenscreen sheet of many items, then masked apart — and `vidfarm sticker-pack` is that whole loop.** A sticker pack is never one graphic; it's a *set* (props, icons, reactions, characters, backdrops) that must share one art style. Generating them one at a time is both expensive (N image jobs) and inconsistent (N independent styles), so the move is the opposite: **generate a single image holding every item, laid out on a flat greenscreen plate, then cut each item out locally for $0.** `vidfarm sticker-pack --generate "<theme>" --items "a,b,c"` does all of it — one billed image job for the whole set, then a free local key, an **automatic** alpha-segmentation that finds each item (no hand-measured `--crop` rects), a per-item trim to its true bounding box, and a `stickers.json` manifest. Already have a greenscreen sheet? `vidfarm sticker-pack ./sheet.png` cuts it up for **$0**. Use `--dry-run` to eyeball the detected boxes first; `--gap` merges/splits items that came out joined or broken; `vidfarm mask <sheet> --crop …` is the manual fallback for one stubborn item.
208
+
209
+ - **Stickers are not necessarily small.** A sticker is *any* transparent element you place and animate — an icon, a mascot, a prop, a character, and equally **a full-width landscape, skyline, or backdrop** that fills the frame. `sticker-pack` filters speckle only; it has no maximum item size. Ask for the big pieces in the same sheet as the small ones.
210
+ - **Stickers are usually animated, not pasted.** Once placed, animate each one with `vidfarm keyframes` presets (`pop-in`, `float`, `shake`, `grow`, `slide-in-left`, `drift`) — that's HTML/CSS canvas motion, deterministic, free, and identical in preview and render. Layer moves up (pop-in, then idle float) for real life. See `references/editor-workflows.md` → "Cutout graphics for explainers".
211
+ - **A sticker can carry its OWN motion too.** A *moving* subject has no single bounding box, so it isn't a PNG: key the clip with `vidfarm remove-greenscreen <video>` → transparent WebM (browser/editor-playable, the right choice on a composition).
212
+ - **The plate must be a color the ART DOESN'T USE — green is a default, not a law.** A chroma key removes exactly ONE color, so a green plate under green artwork (leaves, frogs, plants, money, an "eco" icon set) keys holes straight through the stickers. `sticker-pack`/`cutout` handle this for you in two ways, and you should still say it out loud when it matters: **(a)** when generating, they read the subject and move the plate off any hue it mentions — green → magenta (`#FF00FF`) → blue (`#0047BB`) → black → white — and print which plate they picked and why; **(b)** when splitting a sheet you already have, they **detect the plate from the sheet's four corners**, so a red/purple/blue sheet handed back from a web generator just works. Pin it yourself with `--key-color "#FF00FF"` / `--preset magenta` (that disables the auto-pick), or `--no-auto-key` to force plain green. If a pack's palette collides with *every* standard plate, split it into two sheets on two different plates rather than fighting the key.
213
+ - **Transparent GIF is supported, for GIF-only surfaces.** `vidfarm sticker-pack … --output-format gif` (stills) and `vidfarm remove-greenscreen <video> --gif` (animated) emit transparent GIFs. GIF alpha is **1-bit**, so edges go hard — fine for chat/forum/Notion sticker surfaces, worse than PNG/WebP/WebM for compositing on a timeline. Prefer PNG/WebP/WebM unless the destination only eats GIF.
214
+
172
215
  **Explainer house style — the defaults to build with unless told otherwise.** **White background / light mode** (plain white stage, no gradients, no dark mode, no photo backdrop), **kinetic word-by-word captions** in dark ink on the light stage (`vidfarm captions generate --style word-pop --color "#111111" --active-color "#7C3AED" --background-style plain` — skip outlines/shadows, they're only needed over busy footage), and **female TTS narration** (`vidfarm tts --voice coral` on OpenAI — `nova` for energy, `sage` for calm; `Kore`/`Leda` on Gemini; any ElevenLabs voice via `vidfarm voices`). **Keep it clean and simple** — one idea on screen at a time, two or three cutouts per beat, one accent color, one font, lots of white space; remove before you add. **Illustrations default to simplicity**: flat vector, simple shapes, minimal detail, 2–3 flat colors, no baked-in text — simple art keys cleanly, trims tight, and stays on-style across the whole cast. State the defaults once so the director can override any of them. Full detail: recipe `recipes/cutout-graphics-for-explainers.md` (“House style — the explainer defaults”).
173
216
 
217
+ **Landscape footage in a fullscreen vertical explainer — use the blurred plate, never bars.** When an explainer is built on **real filmed footage** and the source is 16:9 (or 4:3) on a 9:16 canvas, do not `contain` it (hard black letterbox bars read as an unfinished export) and do not blindly `cover` it (a wide shot loses its left and right thirds). Duplicate the clip: a full-canvas `cover` copy behind, heavily **gaussian-blurred and faded dark**, plus the sharp copy centered as a hero band — optionally zoomed ~1.3× — with its **top and bottom edges feathered** into the blur. Same clip, same timecode, so it reads as one continuous image with a shallow-depth-of-field plane, fullscreen edge to edge, nothing cropped, and clean dark space for the header and captions. Bake it once with ffmpeg into a single 1080×1920 file (free, local) and place it as one ordinary full-canvas layer — layer blur is not an editor property, so the pre-bake is the path that works in the editor, `serve`, and cloud render alike. Copy-paste ffmpeg + HTML recipes, tuning table, and the failure modes: `references/editor-workflows.md` (“The blurred plate — landscape footage, fullscreen, on a vertical canvas”).
218
+
174
219
  **Cost-saving move — mask illustrations OUT of a source image the director already has.** (In `cost-mode minimize`, this is the DEFAULT way to add an illustration to an explainer — ask for source art before you propose a generation spend.) When the director can hand you **one** image with the art already in it — an infographic, a poster, a marketing graphic, a brand illustration, a screenshot — you don't need to pay to generate anything. `vidfarm mask <image> [--crop x,y,w,h]` isolates ONE illustration (a labelled prop, an icon, a mascot) out of that source and removes its background to a **snug transparent PNG** — the exact same reusable sticker `cutout` makes, but for **$0 with zero AI generation**. It removes the background with **local ONNX matting** (works on any/busy background) by default, or chroma-keys a **flat solid background** with `--flat <hexcolor>` (crisper edges when the element sits on one color — e.g. the cream paper behind an infographic's icons). Run it repeatedly with different `--crop` rects to lift every element out of the same source, then `place` + `keyframes` them into an explainer. **Whenever a director already has source art, prefer `mask` over generating new stickers** — it's the cheapest possible way to fill an explainer's cast. Same recipe: `recipes/cutout-graphics-for-explainers.md` (“Mask from an image you already have”).
175
220
 
176
221
  **Free manual image-gen — custom art in `minimize` mode for $0, on someone else's tokens.** `mask` only works when the art already exists. When the video needs a **bespoke** graphic and cost mode is `minimize` (or the user said "no spend"), the answer is **not** "we can't" and **not** a silent billed `generate` — it's a **manual handoff**: you write the prompt, the user runs it in a **free** image generator, they hand the PNG back.
@@ -178,7 +223,7 @@ Present both harnesses to the director, recommend (A) unless they've asked for p
178
223
  - **Offer it once, up front, and let them set the default.** The first time custom art is needed in a cost-saving session, ask plainly: *"Want me to default to free manual image generation — I write the prompt, you paste it into a free tool and drop the image back — or would you rather I spend credits on `vidfarm generate` for these?"* Honor the answer for the rest of the session (and offer to remember it alongside the cost mode). Don't re-ask per image once they've chosen; just say "here's the next prompt."
179
224
  - **Free generators to name:** <https://meta.ai> (no cost, generous), free-tier **ChatGPT** (image gen included), or a free image **Hugging Face Space** (<https://huggingface.co/spaces> — search "flux" or "sdxl"). Any of them; the user picks whichever they're already signed into.
180
225
  - **Ask for ONE sheet, not N images — this is the token-efficiency trick.** Each round trip costs the user a manual step and costs you tokens re-reading a new file. So request **one image containing every graphic the scene needs**, laid out as a grid of separate objects on a **flat pure-green background** (`#00FF00`), well spaced, none overlapping or touching an edge. One generation, one hand-back, then you lift each element out locally for free.
181
- - **Then cut it up locally, for $0:** `vidfarm put-file ./sheet.png` to bring it in, then `vidfarm mask ./sheet.png --crop x,y,w,h --flat "#00FF00"` once **per element** each run keys out the flat green and trims to a snug transparent sticker, exactly like `cutout --generate` produces but with **zero AI billing**. `place` + `keyframes` them as usual. (`--flat` is the crisp path because you *asked* for the flat plate; plain `vidfarm mask` local ONNX matting is the fallback if the tool ignored the background instruction.)
226
+ - **Then cut it up locally, for $0 — in ONE command:** `vidfarm sticker-pack ./sheet.png --items "<object one>,<object two>,…" --out-dir ./stickers` keys the flat green out, finds every item in the sheet automatically, and writes one snug transparent sticker per item (named from `--items`) plus a manifest exactly like `cutout --generate` produces, with **zero AI billing**. `place` + `keyframes` them as usual. Add `--dry-run` first to check the detected boxes. Fallbacks: if two items came out joined, lower `--gap`; if the generator ignored the green-plate instruction, `vidfarm mask ./sheet.png --crop x,y,w,h` (local ONNX matting) grabs elements one at a time off any background.
182
227
  - **Prompt template — give the user this, filled in:**
183
228
 
184
229
  > A flat vector illustration sheet on a solid pure green background (#00FF00), no gradient, no shadow, no text, no labels. Arranged in a 3×2 grid with generous even spacing, each object fully separated and not touching any other object or the image edge: (1) `<object one>`, (2) `<object two>`, (3) `<object three>`, … Simple flat shapes, 2–3 flat colors, minimal detail, consistent style and line weight across all objects, front-facing, centered in its own cell. Square image, high resolution.
@@ -224,7 +269,11 @@ You may be running as the **in-web AI chat** (the /editor copilot, the chat dock
224
269
  - **Determine the surface before claiming capabilities.** The web chat has only its declared tools and REST routes. It cannot execute arbitrary JavaScript/Python, open a shell, create a local repository script, or use the user's filesystem. Never tell a web-chat user that you ran code or wrote a script unless a dedicated declared tool actually did so. A desktop coding agent has a real shell and filesystem and MAY write/run scripts, perform arbitrary local computations over paginated API results, create reports/CSVs/JSON, edit composition files, and orchestrate long devcli workflows within the user's authorization.
225
270
  - **The web AI chat can do all three paintbrushes** — clip raws, author HTML/hyperframe motion, and generate AI media — and it drives edits directly on the live timeline. Keep small-to-medium jobs here: text/caption swaps, a scene or two replaced, single generations, captions, approve/schedule. Just do them.
226
271
  - **No HTML slop — a video is not a web page.** Compositions are authored in HTML, so the #1 tell of an AI-edited video is landing-page furniture: gradient CTA "buttons" ("Sign Up for a Free Trial →"), rows of benefit chips/badges ("✓ No Credit Card Needed"), frosted/bordered cards holding a gradient headline + a URL, feature grids, bullet lists, web-default type (Inter/Roboto/Arial at weight 400-600). None of that exists in a real TikTok/Reel — **nothing in a video is clickable**. If you are typing `btn` / `badge` / `chip` / `card` / `rounded-full` / `shadow-lg` / `backdrop-blur` / `bg-gradient-to-r`, stop and rewrite it as timed text on the footage. Arrows, scribble/underline marks, italics, ALL-CAPS, single-word color pops, emoji, transparent cut-out stickers, and mock social UI (iMessage bubbles, comment cards) are all *fine* — they're native to the platform.
227
- - **On devcli, QA every video you produce: `vidfarm qa ./work`.** Free, instant, local-onlyit blocklists exactly the slop above plus font-regime/safe-zone drift, and prints a concrete fix per finding. **Feedback, not a gate**: it exits 0 even on findings, never runs automatically, and is a blocklist (unusual/stylized compositions pass untouched), so there's no reason not to run it before every publish. `--json` for scripted batches, `--strict` only if you want a CI failure. **Web-chat copilot: this command does not exist for you** (devcli-only, no REST twin) — apply the standard by hand, and when handing a heavy job to a local coding agent, tell them to run `vidfarm qa`.
272
+ - **Every video gets the four charges hook, loop, payoff, bait and you write them BEFORE you touch the timeline.** This is the largest quality delta in the product and it costs nothing: most agent-made videos fail on structure, not polish, because the timeline is the fun part so it gets built first and the words get retrofitted. Invert it: (1) write the **hook line as text** — a complete clause, subject + verb, no jargon, naming a **situation** ("I've quit six businesses"), never a label ("anonymity") and put it on screen at `start:0`; (2) name the **curiosity loop** and the timestamp it closes at, *inside this video* (if you can't state the timestamp, there is no loop, and the withheld answer must be one the viewer **can't guess**); (3) name the **payoff** — shown, not summarized, landing before the final beat; (4) write the **bait** one ask in the final beat and in the post caption. Then build. Chunk 1 is read before any audio (muted autoplay is the default), so the text hook does more work than the spoken one. Full harness — the three gates, banned openers, loop mechanics, compliance, and diagnosis-by-charge — in `references/hooks-and-virality.md`; the checkable form is `vidfarm regime show hooks`.
273
+ - **The first frame IS the thumbnail — compose it on purpose.** Frame 0 is a single frame of ~30 in the first second, but it's the poster every feed, share link, and paused player freezes on, so **more people see that one frame than watch the video**. It must never be black, empty, mid-fade, or caught mid-animation: put a real visual at `start:0`, have the hook words already on screen at t=0, and never hang a `fade-black`/`fade-white`/`flash` *entrance* on the **first** clip (junction transitions between later clips are fine — this rule is only about the opening). Verify it, don't assume: devcli `vidfarm stills ./work --at 0` renders that exact frame, and `vidfarm qa` flags a blank or fading open.
274
+ - **Ask early: one-time video, or bulk?** "Make me a video about X" and "I need to post daily / give me 20 hook variants" are different jobs, and directors often don't know the second one has a name. Ask once, up front: *"One video, or should we set this up as a repeatable batch?"* Bulk = **scripting mode** (a pinned base fork + a loop that varies ONE thing per variant; a public-raws shelf is the cheapest source of the N), and every batch gets a **`QA_REGIME.md`** — because a loop of fifty videos has no human looking at every frame, and the regime is what replaces those eyes. Don't silently ship a one-off when they asked for volume, or drag someone into a harness when they wanted one clip.
275
+ - **`QA_REGIME.md` is the director's own quality contract, and it's a first-class artifact.** `vidfarm qa`'s built-ins are universal (slop, fonts, the thumbnail frame); a regime is what makes *this* format good — audience, hook shape, banned vocabulary, pacing, compliance line. It lives next to the work, they own it, it stacks: `vidfarm regime init short-form --out ./work/QA_REGIME.md` (bundled bases: `short-form`, `hooks`, `ugc-testimonial`, `explainer`, `product-demo` — each a starting point to **edit**, never a house style), then `vidfarm qa ./work --regime hooks --regime ./brand/HOUSE.md`, and any user file anywhere is valid. Its `checks:` front matter is machine-settled; its `- [ ]` checklist comes back as **review items you answer honestly in your report** — never claim a video passed the half the CLI can't judge. When a batch teaches you something, **write it back into the regime**: that's the artifact that compounds. Details in `references/automation-and-local-dev.md` ("Scripting mode"), format in `regimes/README.md`.
276
+ - **On devcli, QA every video you produce: `vidfarm qa ./work`.** Free, instant, local-only — it blocklists exactly the slop above plus first-frame/thumbnail and font-regime/safe-zone drift, and prints a concrete fix per finding. **Feedback, not a gate**: it exits 0 even on findings, never runs automatically, and is a blocklist (unusual/stylized compositions pass untouched), so there's no reason not to run it before every publish. `--json` for scripted batches, `--strict` only if you want a CI failure. **Web-chat copilot: this command does not exist for you** (devcli-only, no REST twin) — apply the standard by hand, and when handing a heavy job to a local coding agent, tell them to run `vidfarm qa`.
228
277
  - **Every production adheres to the TikTok-native caption standard.** On-screen text lives inside the readable safe zone (**~8%–85%** of a 9:16 frame — never pinned to the top/bottom edges the phone UI clips), uses the composition's bold font regime (**Montserrat** default / TikTok Sans, weight **700–900**, ~36–64px on a 1080-wide frame), and uses **exactly one of four valid backgrounds**: outline/stroke (`background_style:"outline"`, the default), plain + shadow (`"plain"`), an active-word highlight pill (`set_captions` `spotlight`/`karaoke` — the only legitimate pill), or a tight-hugging solid band (`"highlight-solid"`, radius ≤8px, no border/shadow/gradient/blur). Decomposed forks often inherit the source's edge-pinned caption in an off-regime font — fix it, don't inherit it. Local devcli renders auto-normalize position + font family only (never the slop), so author it correctly. Full rules in `references/editor-workflows.md` ("Social-native visual standard" + "TikTok-native caption standard").
229
278
  - **Where the web chat struggles: complex, long, multi-step transformations.** A full multi-scene re-theme, an iterative render-critique-iterate loop, heavy scripted or batch work, or anything needing a real filesystem and many sequential tool calls will hit context limits, turn/timeout ceilings, and the web editor's constraints (CSS/declarative motion only — JS animation adapters are stripped on save). Don't grind a big transformation one layer at a time in a chat turn and stall.
230
279
  - **Practical workaround — hand the heavy job to local devcli.** When a task is genuinely large or long-running, **proactively recommend the director run it locally with an AI coding agent** (Claude Code / OpenAI Codex / any capable agent): `vidfarm pull <forkId>` writes the composition + the `.harness/` grounding bundle to disk, the agent edits with the full devcli verb set and JS animation adapters, renders free with `vidfarm serve`, and `vidfarm publish` pushes it back. This is the **best-quality (B) harness's** natural home (adversarial grading with a coding agent). Frame it as "this is a big rebuild — you'll get a better, faster result running it locally with a coding agent; here's how," not as a dead end.
@@ -241,6 +290,8 @@ Read only the relevant reference file for the current task.
241
290
  - REST automation, `vidfarm` command surface, local serve loop, skill packs: `references/automation-and-local-dev.md`
242
291
  - Getting-started interviews, **consultations**, strategy docs, onboarding flow: `references/onboarding.md`
243
292
  - Primitive routes such as TTS, STT, music, overlays, background removal, product placement: `references/primitives.md`
293
+ - **Hooks, retention, and why a video travels — the four charges: `references/hooks-and-virality.md`.** Read it before writing ANY hook, caption script, or re-theme, and before a hook-variant batch. It is the craft harness; the rest of the skill is mechanics.
294
+ - Bulk / N-variant production: recipe `recipes/bulk-scripting-with-a-regime.md`; the `QA_REGIME.md` format and the bundled bases: `regimes/README.md` (+ the regime files beside it, readable as-is)
244
295
  - Complete REST API map and raw-HTTP conventions: `references/rest-api.md`. Load it only when the user asks for REST, an endpoint/schema, direct HTTP integration, or exhaustive API coverage. For the entire specification, follow its domain links and load every listed reference; do not preload them into ordinary director conversations.
245
296
 
246
297
  ## HyperFrames Skills — Load on Demand
@@ -0,0 +1,65 @@
1
+ ## Recipe: Bulk Video Generation (Scripting Mode) with a QA_REGIME.md
2
+
3
+ Use this when the director wants **volume** — daily posting, hook tests, one video per clip in a pool, N variants of a template. Ask first if you're not sure: *"One video, or should we set this up as a repeatable batch?"* If they want volume, this is the shape.
4
+
5
+ The thing that makes bulk work is not the loop — loops are easy. It's that **nobody is going to watch variant #37 as carefully as variant #1**, so the standard has to be written down before the loop runs. That's the `QA_REGIME.md`.
6
+
7
+ ### 0. Read the craft harness first
8
+
9
+ `references/hooks-and-virality.md` — the four charges (hook / loop / payoff / bait), the three gates, and the anti-patterns that only bite at volume. Two of them decide whether this batch is worth running at all: **a different noun is not a different hook** (twenty variants of one sentence with the nouns swapped is one video), and **never point a generator at your grader** (a model writing hooks scored by the same model converges on the rubric, not on what works — scores climb, nothing improves). The regime catches defects; it does not rank winners.
10
+
11
+ ### 1. Agree the variant axis — before any code
12
+
13
+ One thing changes per variant; everything else is held constant. Hook line, opening clip, opening pain, avatar — pick one and say so out loud. A batch where several things changed at once teaches the director nothing, which defeats the point of running a batch instead of making one good video. **The cluster is the unit, not the video**: one attribution `tracer` per cluster, so a bad audience can't be mistaken for a bad hook.
14
+
15
+ ### 2. Pin the base
16
+
17
+ ```bash
18
+ vidfarm pull <forkId> --dir ./work # one canonical base fork per batch
19
+ ```
20
+
21
+ Read `./work/.harness/agent-guide.md` first, as always.
22
+
23
+ ### 3. Install and EDIT the regime
24
+
25
+ ```bash
26
+ vidfarm regime list # short-form | hooks | ugc-testimonial | explainer | product-demo
27
+ vidfarm regime init hooks --out ./work/QA_REGIME.md
28
+ ```
29
+
30
+ Then **edit it with the director**. The bundled file is a starting point; the parts that matter are the ones they add — who the viewer is, their banned vocabulary, the compliance line, the pacing this account actually uses. A regime nobody edited isn't about their videos. Existing regime somewhere else on disk? Just point at it: `--regime ./brand/HOUSE_RULES.md`. They stack.
31
+
32
+ ### 4. Source the N cheaply
33
+
34
+ ```bash
35
+ vidfarm public-raws --categories --json # live shelf vocabulary
36
+ vidfarm public-raws --category scroll-stoppers --limit 20 --json > pool.json
37
+ ```
38
+
39
+ A curated shelf is a pre-tagged, free, already-hosted clip pool — the cheapest way to get N distinct variants without N downloads or N generation calls.
40
+
41
+ ### 5. Loop: edit → QA against the regime → render
42
+
43
+ ```bash
44
+ for VARIANT in "${VARIANTS[@]}"; do
45
+ SLUG="$(echo "$VARIANT" | tr ' ' '-' | cut -c1-40)"
46
+ vidfarm set-text ./work --layer hook --text "$VARIANT"
47
+ vidfarm qa ./work --json > "qa/$SLUG.json" # ./work/QA_REGIME.md auto-discovered
48
+ jq -e '.ok' "qa/$SLUG.json" >/dev/null || { echo "skipped $SLUG"; continue; }
49
+ vidfarm render "$FORK_ID" --dir ./work --out "renders/$SLUG.mp4" --tracer "batch-$SLUG"
50
+ done
51
+ ```
52
+
53
+ `vidfarm qa` still exits 0 on findings — the `jq -e` line is **your** gate, in your script, made explicit. Keep it that way; a hard gate inside the tool would quietly train the loop to stop trying anything unusual.
54
+
55
+ ### 6. Answer the review items — don't skip this
56
+
57
+ The regime's `- [ ]` checklist comes back on every run because the CLI *can't* settle it. Machine checks catch a 13-word hook or a black first frame; only you can answer "is this variant genuinely different from its siblings?" or "can the viewer guess the withheld answer?" **Report both halves honestly**: what the machine checked, and what you judged. A batch report claiming a clean pass on the judgment half is worse than no report.
58
+
59
+ ### 7. Feed what you learn back into the regime
60
+
61
+ When the director says "the label-framed hooks all died" or "anything over 30s tanked", write it into `QA_REGIME.md` as a rule or a checklist line — with the reason attached, so the next agent doesn't argue it away. The compositions are disposable; **the regime is the artifact that compounds across batches.**
62
+
63
+ ### Cost note
64
+
65
+ Per-video AI spend multiplies by N. Bulk belongs in `minimize`/`hybrid` cost mode with reused assets: clip pools and HTML/CSS motion over a fixed asset set, not per-variant generation. Generate a reusable element once, then vary text and media around it.
@@ -22,11 +22,77 @@ The mechanical trio — **generate on a chroma plate → key it out → trim to
22
22
 
23
23
  **In cost-saving mode, don't generate illustrations at all — mask them out of images the director already has.** If `vidfarm cost-mode` is `minimize` (or the director says "without burning credits"), the default for adding an illustration is `vidfarm mask <their-image> --crop …` — lifting art out of an infographic, poster, deck slide, brand sheet, or screenshot for **$0 and zero AI calls**. Ask for source art before you ask for a generation budget; the guided loop is **"Mask from an image you already have"** below. **If no source art exists and the graphic must be custom, you still don't have to spend** — hand the director a prompt for a **free** image generator (meta.ai / free ChatGPT / a Hugging Face Space) and cut the returned sheet into stickers locally: **"Free manual image-gen"** below.
24
24
 
25
+ ### "A sticker pack" — what it means, and the one command for it
26
+
27
+ **When a director asks for a sticker pack (or "a set of stickers", "a prop pack", "an icon set", "assets for this video"), that is a specific pipeline, not N separate cutouts:**
28
+
29
+ > **Generate ONE image containing every item, laid out on a flat greenscreen plate → key that plate out once → mask each item apart into its own transparent file.**
30
+
31
+ Do it that way every time, for two reasons: **cost** (one billed image job for the whole set instead of one per sticker) and, more importantly, **style consistency** — items drawn in the same image share line weight, palette, perspective and lighting, which N independent generations never do.
32
+
33
+ `vidfarm sticker-pack` is that entire loop in one command. It also does the part that used to be manual: **finding the items**. Instead of measuring a `--crop x,y,w,h` rect per item by eye, it segments the keyed sheet's **alpha channel** into connected islands of opaque pixels — one island per item — and cuts each one out, trimmed to its true bounding box.
34
+
35
+ ```
36
+ # Generate the sheet AND split it (one image job for the whole pack)
37
+ vidfarm sticker-pack --generate "cozy farm props, flat vector, 2-3 flat colors" \
38
+ --items "red barn,tractor,hay bale,sun,fence,rolling hills landscape" \
39
+ --out-dir ./stickers
40
+
41
+ # Or split a greenscreen sheet you already have — $0, no account
42
+ vidfarm sticker-pack ./sheet.png --items "barn,tractor,hay bale" --out-dir ./stickers
43
+
44
+ # Look before you cut: prints the detected boxes, writes nothing
45
+ vidfarm sticker-pack ./sheet.png --dry-run
46
+ ```
47
+
48
+ Out comes `./stickers/sticker-01-red-barn.png`, `sticker-02-tractor.png`, … each trimmed tight, plus **`stickers.json`** (name, file, pixel size, sheet crop, area share) so a later step — or another agent — can pick props by name without re-deriving anything.
49
+
50
+ **Knobs that matter:**
51
+
52
+ - `--items "a,b,c"` — the exact cast. It both steers the generation and **names the outputs** in reading order (top-to-bottom rows, left-to-right). `--count <n>` instead if you don't care what the items are.
53
+ - `--dry-run` — list the detected crop boxes and stop. Cheap sanity check before writing a dozen files.
54
+ - `--gap <pct>` (default 1.2) — how far apart two islands must be to count as separate items. **Two items came out as one sticker → lower it** (or ask for wider spacing on the sheet). **One item came out split in two → raise it** (its parts, e.g. a floating antenna or a dotted arrow, weren't bridged).
55
+ - `--min-area <pct>` (default 0.15) — drops key speckle. There is **no maximum** — see the size note below.
56
+ - `--preset`/`--key-color` — match the plate (default `#00FF00`). `--pad`, `--alpha-threshold`, `--output-format png|webp|gif`, `--prefix`, `--max-items`, `--keep-plate`/`--keep-sheet` behave like `cutout`'s.
57
+ - Stubborn item? Fall back to one hand-measured `vidfarm mask ./sheet.png --crop x,y,w,h --flat "#00FF00"` for that one; the rest of the pack still comes from `sticker-pack`.
58
+
59
+ **Pick a plate the ART doesn't use — this is the #1 way a pack comes out broken.** A chroma key removes exactly ONE color. A sticker pack of leaves, frogs, plants, money, or "eco" iconography on a GREEN plate keys holes straight through the artwork, and it looks like the cut failed when really the plate was wrong. The commands handle it two ways:
60
+
61
+ - **Generating?** `sticker-pack --generate` / `cutout --generate` read the subject text and move the plate off any hue it mentions — green (`#00FF00`) → magenta (`#FF00FF`) → blue (`#0047BB`) → black → white — then print which plate they chose and why. Say it back to the director when it moves: *"Your items are mostly green, so I generated them on a magenta plate."*
62
+ - **Splitting a sheet you already have?** The plate is **detected from the sheet's four corners** (a sticker sheet always has plate in the corners), so a red/purple/blue sheet handed back from a free web generator just works with no flags.
63
+
64
+ Override whenever you know better: `--key-color "#FF00FF"` or `--preset magenta` pins the plate (and turns the auto-pick off); `--no-auto-key` forces plain green. If a pack's palette collides with *every* standard plate — a rainbow icon set — split it across two sheets on two different plates rather than fighting `--tolerance`. And when a sticker is a *green* subject, never let the user generate it on green: the hand-off brief (`vidfarm handoff image`) already picks the plate for them and carries the matching `--key-color` into the follow-up command.
65
+
66
+ **Generation is the failure point, not the cutting.** The sheet prompt is auto-appended with the important instruction — *every item fully separated by clear plate-colored background, nothing touching or overlapping, wide margins, no text, no shadows, one consistent style* — because **touching items segment as one sticker**. If a pack comes back merged, re-run the generation asking for more spacing before you fight the `--gap` knob.
67
+
68
+ ### Stickers are not necessarily small — and they usually move
69
+
70
+ Two things directors assume that aren't true:
71
+
72
+ - **A sticker can be huge.** "Sticker" here means *a transparent element you can place, scale and animate independently* — nothing about size. A full-width **landscape, skyline, cityscape, room interior, or backdrop** is a perfectly good sticker, and belongs in the same sheet as the icons so it shares their style. `sticker-pack` has no maximum item size (only a speckle floor), so a background plate that covers 60% of the sheet cuts out just like a 3% icon does. Ask for the big pieces explicitly in `--items` (e.g. `"rolling hills landscape (wide)"`).
73
+ - **A sticker is normally animated, not pasted.** The default animation surface is the **canvas/HTML itself**: place the PNG as an image layer, then animate it with `vidfarm keyframes` presets — `pop-in`, `float`, `shake`, `grow`, `slide-in-left`, `drift` — or raw keyframe stops. That's CSS/declarative motion, deterministic, free, and identical in preview and final render, and it's what gives an explainer its life. Layer moves for realism: a callout that `pop-in`s and then `float`s idle; an arrow that `slide-in-left`s and then `shake`s at its target. Full vocabulary: `references/editor-workflows.md` → "Cutout graphics for explainers".
74
+ - **When the sticker's OWN artwork moves** (a waving mascot, a spinning coin, a looping animation), it isn't a still at all — there's no single bounding box to trim to. Key it as a clip: `vidfarm remove-greenscreen <video>` → **transparent WebM** (browser- and editor-playable; a ProRes `.mov` alpha master is the local fallback when ffmpeg can't encode WebM alpha, and `--cloud` always returns WebM).
75
+
76
+ **Transparent GIF stickers.** Some destinations only take GIF — chat apps, forums, Notion, older web overlays, sticker packs meant to be shared rather than rendered. Both paths can emit one:
77
+
78
+ ```
79
+ vidfarm sticker-pack ./sheet.png --output-format gif --out-dir ./stickers # still stickers as GIF
80
+ vidfarm remove-greenscreen ./mascot.mp4 --gif --gif-fps 12 --gif-width 480 # ANIMATED transparent GIF
81
+ ```
82
+
83
+ GIF alpha is **1-bit** — a pixel is fully opaque or fully gone, so antialiased edges go hard and semi-transparent shadows/glows disappear (`--gif-alpha <0..255>` moves where that line falls). That's the format, not the key. **For anything going onto a composition, prefer PNG/WebP (still) or transparent WebM (clip);** reach for GIF only when the destination demands it.
84
+
25
85
  ### The guided sequence (prompt harness)
26
86
 
27
- **Step 0 — Decide the cast of stickers.** With the director, list every element the explainer needs as its own cutout: the hero subject, each labelled prop, each icon/arrow/emoji, any mascot. Each becomes one transparent PNG. Stickers are reusable — generate once, reuse across scenes.
87
+ **Step 0 — Decide the cast of stickers.** With the director, list every element the explainer needs as its own cutout: the hero subject, each labelled prop, each icon/arrow/emoji, any mascot, any full-frame backdrop. Each becomes one transparent PNG. Stickers are reusable — generate once, reuse across scenes. **If the cast is more than two or three items, make it a PACK** (one sheet, split locally — see "A sticker pack" above) rather than N separate `cutout` calls.
88
+
89
+ **Step 1 — Make each cutout.** Four paths, cheapest first:
28
90
 
29
- **Step 1Make each cutout.** Three paths, cheapest first:
91
+ - **Cut a whole pack out of ONE sheet** (`vidfarm sticker-pack`) the default for a *set*, and the only path that keeps a cast on-style. See "A sticker pack" above.
92
+ ```
93
+ vidfarm sticker-pack --generate "<theme>, flat vector" --items "a,b,c,d" --out-dir ./stickers
94
+ vidfarm sticker-pack ./sheet.png --out-dir ./stickers # free, sheet you already have
95
+ ```
30
96
 
31
97
  - **Mask it out of a source image the director already has** (FREE, no account, no generation) — *the cheapest path, and the one to prefer whenever source art exists.* If the director hands you one image with the art already in it — an infographic, a poster, a marketing graphic, a brand illustration, a screenshot — lift each illustration straight out of it with `vidfarm mask`:
32
98
  ```
@@ -97,10 +163,12 @@ This is the biggest cost saver in the whole explainer workflow: **if the directo
97
163
 
98
164
  Everything here is **local and free** — crop, matte/key, and trim are all `ffmpeg` + the bundled ONNX engine. No wallet, no account, no generation call.
99
165
 
100
- ### Free manual image-gen (the $0 path when NO source art exists)
166
+ ### Free manual image-gen (the $0 path when NO source art exists — and the DEFAULT in interactive mode)
101
167
 
102
168
  `mask` needs art that already exists. When the explainer needs a **custom** graphic and the director is in `cost-mode minimize` (or just said "don't spend"), there's still a $0 path: **you write the prompt, the director runs it in a free image generator, they hand the image back, you cut it up locally.** The AI spend moves to a free third-party tool; Vidfarm's wallet is never touched.
103
169
 
170
+ **This is what `vidfarm mode interactive` means in practice** — and `vidfarm handoff image --theme "<what>" --items "a,b,c"` mints the whole brief for you (the prompt, the numbered steps, the free tools, the plate color, and the follow-up `sticker-pack` command with the matching `--key-color`). Don't hand-write these packets; print the brief.
171
+
104
172
  **Offer it once, then make it the default.** The first time custom art comes up in a cost-saving session, ask: *"Want me to default to free manual image generation — I write the prompt, you paste it into a free tool and drop the PNG back — or should I spend credits on `vidfarm generate`?"* Whatever they pick, hold it for the session (and offer to remember it next to the cost mode). After that, don't re-ask per graphic — just hand over the next prompt.
105
173
 
106
174
  **Free generators to name:** <https://meta.ai>, free-tier **ChatGPT**, or a free image **Hugging Face Space** (<https://huggingface.co/spaces>, search "flux" / "sdxl"). Let the director use whichever they're already logged into.
@@ -115,12 +183,15 @@ Everything here is **local and free** — crop, matte/key, and trim are all `ffm
115
183
 
116
184
  **No text in the image, ever** — rendered text never keys or scales cleanly; add copy as a caption or HTML layer instead.
117
185
  3. **Bring the sheet in:** `vidfarm put-file ./sheet.png` (or drag into **My Files** in the web app).
118
- 4. **Split it into stickers — one `mask` per element, all free:**
186
+ 4. **Split it into stickers — one command, all free:**
187
+ ```
188
+ vidfarm sticker-pack ./sheet.png --items "<object one>,<object two>,…" --out-dir ./stickers
189
+ ```
190
+ It keys the flat green, finds each object in the alpha channel, and writes one trimmed transparent sticker per object (named from `--items`) plus `stickers.json`. Run it with `--dry-run` first to check the boxes. Two objects merged into one? The generator drew them too close — lower `--gap`, or grab that pair by hand:
119
191
  ```
120
- vidfarm mask ./sheet.png --crop 4%,4%,29%,45% --flat "#00FF00" --out prop-a.png
121
- vidfarm mask ./sheet.png --crop 36%,4%,29%,45% --flat "#00FF00" --out prop-b.png
192
+ vidfarm mask ./sheet.png --crop 4%,4%,29%,45% --flat "#00FF00" --out prop-a.png
122
193
  ```
123
- `--flat "#00FF00"` is the crisp path precisely because you *asked* for the flat green plate. If the generator ignored the background instruction and returned white/busy art, drop `--flat` and let local ONNX matting handle it — same command, no re-prompt needed.
194
+ If the generator ignored the background instruction and returned white/busy art, `vidfarm mask` **without** `--flat` falls back to local ONNX matting — same command, no re-prompt needed.
124
195
  5. **Stage, animate, render** exactly as in Steps 3–5 above. A manually-generated sticker is indistinguishable from a `cutout --generate` one on the timeline.
125
196
 
126
197
  **Grid sizing note:** a 3×2 grid on a square image puts each cell at roughly `33%` wide × `50%` tall; start crops a couple of percent inside the cell and use `--keep-region` on the first run to verify before masking the rest.
@@ -6,8 +6,8 @@ Use this when a coding agent is doing the work locally or the user wants a repro
6
6
  2. Run `vidfarm pull <forkId> --dir ./work`.
7
7
  3. Read `./work/.harness/agent-guide.md` and `./work/.harness/context.json` before editing.
8
8
  4. Make deterministic edits to `composition.html` and optionally `composition.json`.
9
- 5. Validate with `vidfarm lint` or `vidfarm stills` when useful.
10
- 6. **QA before you render: `vidfarm qa ./work`.** Free, instant, devcli-only. It blocklists HTML slop (CTA buttons, benefit chip rows, frosted cards, gradient text, web-page classes/fonts) and checks the caption font regime + safe zone. Feedback only — exit 0 even on findings, never automatic — but it catches the #1 tell of an agent-made video, so run it on every production. Fix what's real, ignore what's a deliberate style call, then render.
9
+ 5. Validate with `vidfarm lint` or `vidfarm stills` when useful. **Always look at `vidfarm stills ./work --at 0`** — that frame becomes the thumbnail, so it must not be black, empty, or mid-fade.
10
+ 6. **QA before you render: `vidfarm qa ./work`.** Free, instant, devcli-only. It blocklists HTML slop (CTA buttons, benefit chip rows, frosted cards, gradient text, web-page classes/fonts), checks the caption font regime + safe zone, and flags a blank/fading first frame (the thumbnail). Feedback only — exit 0 even on findings, never automatic — but it catches the #1 tell of an agent-made video, so run it on every production. Fix what's real, ignore what's a deliberate style call, then render.
11
11
  7. Render with `vidfarm render <forkId> --dir ./work --wait`.
12
12
  8. Approve the finished MP4 with `vidfarm approve --video <url|./final.mp4> --caption "..."`. This prints the shareable `share_url`.
13
13
 
@@ -5,7 +5,7 @@ Use this when the user wants to keep the format’s feel but replace the subject
5
5
  1. Read `references/editor-workflows.md`.
6
6
  2. Fetch `video-context.json` and `editor-harness.json` first.
7
7
  3. State the plan in the three axes vocabulary: scenes, audio, text; SWAP vs REPLACE for each.
8
- 4. Preserve the hook structure, cut rhythm, emotional punch, and important scenes flagged by the harness.
8
+ 4. Preserve the hook structure, cut rhythm, emotional punch, and important scenes flagged by the harness. **Read `references/hooks-and-virality.md` before rewriting the opening line or the retention beat** — `viral_dna.hook`/`retention`/`payoff` name the source's four charges, and rebuilding each one for the new subject (rather than flattening the loop into a product statement) is the whole job.
9
9
  5. Source footage in this order:
10
10
  - My Files or existing raws
11
11
  - a raws hunt from a long-form source
@@ -36,6 +36,50 @@ Send a stable `tracer` on export so retries are traceable and filterable in job
36
36
 
37
37
  **Scripting mode** is the recommended posture for repeatable template automation. Use it when a director wants to take a template they like, agree on a base fork, and then drive bulk or one-off edits entirely through REST or `vidfarm api` from a script, Lambda, or local machine.
38
38
 
39
+ **Ask which mode you're in, once, before you build.** These are different jobs and the answer changes everything downstream:
40
+
41
+ | | **One-time video** | **Bulk / scripting mode** |
42
+ |---|---|---|
43
+ | The deliverable | One MP4 you both look at | A loop that produces N videos nobody watches frame-by-frame |
44
+ | Quality control | Your eyes on the render | **A `QA_REGIME.md`** — the batch's written standard |
45
+ | What you optimize | This video | The *variant axis* (one thing changes; everything else is held) |
46
+ | Cost posture | Per-video decisions are fine | Per-video AI spend × N — reuse assets, prefer clip pools |
47
+
48
+ A director who says "make me a video about X" usually wants the first. A director who says "I need to post daily" / "make 20 variants" / "test hooks" wants the second and often doesn't know it has a name. **Offer the upgrade explicitly:** *"Want this as one video, or should we set it up as a repeatable batch? Batches get a QA_REGIME.md so variant #37 is as good as #1."* Don't silently build a one-off when they asked for volume, and don't drag someone into a scripting harness when they wanted one clip.
49
+
50
+ ### `QA_REGIME.md` — the quality contract for a batch
51
+
52
+ `vidfarm qa`'s built-in rules are **universal** (no HTML slop, the font regime, the thumbnail frame) — the same for everyone, so they live in code. A regime is the opposite: it's what makes **this** director's **this** format good — their audience, hook shape, banned vocabulary, pacing, compliance line. It can't be hard-coded, so it lives next to the work as Markdown they own and version.
53
+
54
+ **It exists because bulk output loses its human reviewer.** One video gets eyes on every frame; fifty generated in a loop do not. The regime is what the loop grades against.
55
+
56
+ ```bash
57
+ vidfarm regime list # the bundled starting points
58
+ vidfarm regime init short-form --out ./work/QA_REGIME.md # copy, then EDIT it
59
+ vidfarm qa ./work # auto-picks up ./work/QA_REGIME.md
60
+ vidfarm qa ./work --regime hooks --regime ./brand/HOUSE.md # built-in + your own file — they STACK
61
+ ```
62
+
63
+ Bundled bases (`vidfarm regime list`, files under `.agents/skills/vidfarm/regimes/`): **`short-form`** (the default — the four charges hook/loop/payoff/bait + the standalone rule), **`hooks`** (hook-variant batches: chunk-1 legibility, the unguessable test, the anti-patterns that only show up at volume), **`ugc-testimonial`**, **`explainer`**, **`product-demo`**. Each is a *starting point to edit*, never a house style to conform to — the parts that matter most are the parts the director adds. A regime can also be any file anywhere: `--regime ./campaigns/q3/RULES.md` is fully supported, and `VIDFARM_QA_REGIME=./work/QA_REGIME.md` sets a default for a whole run.
64
+
65
+ **The format is two halves, and the split is deliberate:** a front-matter `checks:` block the CLI settles deterministically (duration, aspect, `hook_words_max`, `forbid_text`, `first_frame_text`, … — full key list in `regimes/README.md`), and every `- [ ]` checkbox in the body, which comes back as a **review item for you to answer**. "Is the withheld answer one the viewer can't supply themselves?" is a judgment call; a linter claiming to settle it would be lying. **Answer the review items honestly in your report** — the CLI prints them precisely because it can't.
66
+
67
+ **Build on it.** When you learn something from a batch ("the label-framed hooks all died"), write it into the regime as a new rule or checklist line. That is the artifact that compounds across runs; the composition files don't.
68
+
69
+ ### The bulk loop, with the regime in it
70
+
71
+ ```bash
72
+ vidfarm regime init hooks --out ./work/QA_REGIME.md # once, then edit for this account
73
+ for VARIANT in "${VARIANTS[@]}"; do
74
+ vidfarm set-text ./work --layer hook --text "$VARIANT"
75
+ vidfarm qa ./work --json > "qa/$SLUG.json" # regime auto-discovered from ./work
76
+ jq -e '.ok' "qa/$SLUG.json" >/dev/null || continue # YOUR gate, in YOUR script
77
+ vidfarm render "$FORK_ID" --dir ./work --out "renders/$SLUG.mp4"
78
+ done
79
+ ```
80
+
81
+ `vidfarm qa` still exits 0 on findings — the gate above is the *script's* choice, made explicit with `jq`, not a behavior change in the tool. Keep it that way: an agent that can't ship a deliberately weird variant will quietly stop trying weird variants.
82
+
39
83
  This section is for a **desktop/local coding agent**, not the web copilot. A local Codex/Claude agent may use its shell and filesystem to write JavaScript/TypeScript/Python/shell scripts, fetch every API page, join and score catalog/library data, calculate statistics, emit CSV/JSON/Markdown reports, manipulate composition DOM files, and run iterative render/inspection loops. The web copilot cannot inherit those abilities from this document: it may only call its declared tools and bounded REST routes. If web chat prepares work for this flow, consume its My Files handoff document as input; do not claim the web chat itself executed the script.
40
84
 
41
85
  Contract:
@@ -169,9 +213,10 @@ The licensed harness also carries the **generative build workflow** guidance (ch
169
213
  | `vidfarm generate <image\|video> --prompt "…"` | `POST /api/v1/primitives/{images,videos}/generate` (polls job) | generate AI media → finished URL |
170
214
  | `vidfarm inpaint <image> --mask <png> --prompt "…" [--region "label=…"] [--ref …] [--out <f>]` | `POST /api/v1/primitives/images/inpaint` (polls job) | masked image EDIT — replace ONLY the transparent-mask region, keep everything else (devcli twin of the /inpaint page) |
171
215
  | `vidfarm create-overlay "<subject>" [--key-color #00FF00] [--aspect-ratio 1:1] [--place <dir>] [--out <f>]` | `POST /api/v1/primitives/images/create-overlay` (polls job) | **Vox-style** transparent OVERLAY — AI image on a forced key-color background, chroma-keyed out in one job → ready-to-composite transparent PNG |
172
- | `vidfarm remove-greenscreen <image\|video> [--preset green\|blue\|white\|black\|digital-green\|magenta] [--key-color #00FF00] [--tolerance 0.3] [--local] [--out <f>]` | `POST /api/v1/primitives/remove-greenscreen` (polls job) | chroma-key a FLAT solid background → transparent PNG/WebP (image) or WebM/VP9-alpha (video); auto-detects media kind. `--local` runs it FREE in-process (sharp/ffmpeg, no wallet); default cloud is billed at real compute × 1.2. Aliases: `greenscreen`, `remove-background-greenscreen`. |
216
+ | `vidfarm remove-greenscreen <image\|video> [--preset green\|blue\|white\|black\|digital-green\|magenta] [--key-color #00FF00] [--tolerance 0.3] [--local] [--gif] [--out <f>]` | `POST /api/v1/primitives/remove-greenscreen` (polls job) | chroma-key a FLAT solid background → transparent PNG/WebP (image) or WebM/VP9-alpha (video); auto-detects media kind. `--local` runs it FREE in-process (sharp/ffmpeg, no wallet); default cloud is billed at real compute × 1.2. **`--gif` writes a transparent GIF instead** (ANIMATED for a clip; `--gif-fps`/`--gif-width`/`--gif-alpha`) — local-only, 1-bit alpha, for GIF-only sticker surfaces; prefer PNG/WebP/WebM for compositing. Aliases: `greenscreen`, `remove-background-greenscreen`. |
173
217
  | `vidfarm cutout <image\|url> [--generate "<prompt>"] [--preset green] [--pad <px>] [--alpha-threshold <n>] [--no-trim] [--output-format png\|webp] [--out <f>]` | **local, free, ffmpeg-only** (no job) — key + `alphaextract`/`cropdetect` trim | **The transparent explainer-STICKER maker.** Keys out the flat plate **and then shrinks the canvas to the cutout's true min width/height** (a 1024² mostly-empty plate → a snug sticker whose pixel size IS the subject) so you can scale/position it precisely. `--generate` AI-generates the graphic first on a matching chroma plate (that step is the billed image primitive), then keys+trims in one shot; without it, keys+trims a file/url you already have. **IMAGE-only** (a moving subject has no single bounding box — key a clip with `remove-greenscreen`). Prefer this over `create-overlay` locally: same idea, but free and auto-trimmed. `--pad` keeps transparent breathing room; `--json` reports final `width`/`height`/`area_reduced_pct`. Alias: `sticker`. See recipe `cutout-graphics-for-explainers.md`. |
174
218
  | `vidfarm mask <image\|url> [--crop x,y,w,h] [--flat <hex>] [--pad <px>] [--alpha-threshold <n>] [--no-trim] [--output-format png\|webp] [--keep-region <f>] [--out <f>]` | **local, free** (no job) — ffmpeg crop + ONNX matting (or ffmpeg chroma-key) + `cropdetect` trim | **Lift an illustration OUT of an image you already have** (infographic / poster / marketing graphic / brand sheet / screenshot) → snug transparent PNG, the same reusable explainer sticker `cutout` makes but with **$0 and zero AI generation** — the cost-saving move whenever source art exists. `--crop x,y,w,h` (pixels **or** %) isolates ONE element from a multi-illustration source before masking (re-run with different rects to grab each). Background removed by **local ONNX matting** (any/busy background) by default, or **`--flat <hexcolor>`** chroma-keys a solid fill for crisper edges (an infographic's cream/white paper); then trims to the subject's true min width/height. **IMAGE-only** (matte a clip with `remove-background`). Aliases: `isolate`, `extract`. See recipe `cutout-graphics-for-explainers.md` → "Mask from an image you already have". |
219
+ | `vidfarm sticker-pack [sheet\|url] [--generate "<theme>"] [--items "a,b,c"] [--count <n>] [--dry-run] [--gap <pct>] [--min-area <pct>] [--output-format png\|webp\|gif] [--out-dir <d>]` | **local, free, ffmpeg-only** (no job; only `--generate` bills, ONCE for the whole set) — key + alpha-channel segmentation + per-item trim | **The STICKER-PACK maker — the answer whenever a director asks for "a sticker pack" / prop set / icon set.** A pack is ONE greenscreen sheet holding every item, keyed once and then masked apart: 1/N the cost of N `cutout` calls, and the only way a cast stays on-style. Finds each item **automatically** by segmenting the keyed sheet's alpha into connected islands — no hand-measured `--crop` rects — and writes one snug transparent file per item (named from `--items`, reading order) plus a `stickers.json` manifest. `--dry-run` prints the detected boxes first; `--gap` merges (lower) or splits (raise) items that came out joined/broken; items have **no maximum size** — a full-frame landscape/backdrop is as valid a sticker as a 3% icon. **Plate color is chosen for you:** when generating it reads the subject and moves the plate off any hue the art uses (green → magenta → blue → black → white — a pack of leaves/frogs/money on GREEN would key holes through the art), and when splitting an existing sheet it DETECTS the plate from the sheet's four corners, so a red/purple sheet handed back from a web tool just works. Pin it with `--key-color`/`--preset`, or `--no-auto-key` for plain green. `--output-format gif` emits 1-bit-alpha GIFs for GIF-only surfaces. IMAGE-only. Aliases: `stickers`, `sticker-sheet`. See recipe `cutout-graphics-for-explainers.md` → "A sticker pack". |
175
220
  | `vidfarm tts "…" [--style "…"] [--voice <v>] [--out <file>]` | (LOCAL-FIRST: your own OPENAI/GEMINI/OPENROUTER_API_KEY → audio file on disk; `--cloud` = `POST /api/v1/primitives/audio/speech` + poll, ElevenLabs on the platform key by default, `--own-key` for yours) | text → narration audio; `--cloud --voice <voice_id>` picks an ElevenLabs voice |
176
221
  | `vidfarm music "<prompt>" [--length <sec>] [--out <f>] [--own-key]` | `POST /api/v1/primitives/music/generate` (polls job) | prompt → music track (ElevenLabs; platform key + wallet by default, `--own-key` for yours) |
177
222
  | `vidfarm voices [--own-key] [--limit N]` | `GET /api/v1/primitives/audio/voices` | list ElevenLabs voices (voice_id/name/labels) for `tts --voice`; default a voice + tell the user they can choose |
@@ -199,6 +244,10 @@ The licensed harness also carries the **generative build workflow** guidance (ch
199
244
  | `vidfarm login <email>` / `vidfarm verify <email> <code>` | `POST /api/v1/user/request-otp` · `verify-otp` | get an API key |
200
245
  | `vidfarm whoami` | `GET /api/v1/user/me` | who am I (also prints the active cost mode) |
201
246
  | `vidfarm cost-mode [minimize\|hybrid\|rich-ai\|pure-videogen]` | (local `~/.vidfarm/cost-mode.json`) | show/set the money-saving preference every billed command respects; no arg = show + explain each; `--clear` forgets it |
247
+ | `vidfarm mode [interactive\|autonomous]` | local (`~/.vidfarm/interaction-mode.json`) | **The SECOND preference axis — ask it alongside cost mode.** Is the human in the loop? `interactive` = at checkpoints you hand them a copy-paste brief (an image prompt for a FREE web generator; a keyword list for sourcing clips) and they hand files back — usually BETTER output, and in `minimize` the only way to get custom art at all. `autonomous` = you finish solo within the budget. Independent of cost mode: every cost mode runs either way. No arg prints the pair + the explainer to relay; `--clear` forgets; per-run `--interactive`/`--autonomous`. Aliases: `interaction-mode`, `interaction`. |
248
+ | `vidfarm handoff image --theme "<what>" [--items "a,b,c"] [--style …] [--single]` | local (pure text) | **The interactive-mode IMAGE brief.** Prints the exact prompt, the numbered steps, the free tools (meta.ai / ChatGPT / Gemini / HF Spaces) and the follow-up command. Defaults to a **sticker pack**: ONE sheet holding every item on a chroma plate → `vidfarm sticker-pack` splits it for $0. Picks a plate the art won't collide with (green art → magenta plate) and carries that `--key-color` into the follow-up. `--single` for one subject. |
249
+ | `vidfarm handoff raws --keywords "a,b" [--platforms tiktok,youtube] [--count N] [--purpose "…"]` | local (pure text) | **The interactive-mode CLIP-SOURCING brief** — the bottom rung of the sourcing ladder (browser control → `clipper`/`raws scan --cloud` → public raws → the human). Prints what to search, how to download (a Google *search* for a downloader, never a link that rots), and the import command for when the folder is ready. |
250
+ | `vidfarm storyboard [dir] [--init] [--frames "Title\|scene,…"] [--json]` | local (`STORYBOARD.md` / `SCRIPT.md`) | **The plan pass, and a core part of the composition format.** Scaffolds/reads the project's `STORYBOARD.md`: ordered frames with `duration`/`status`/`src`/`scene`/`voiceover`. The Vidfarm editor renders this file in its **Storyboard** view (contact sheet + per-frame comments + `outline → built → animated` progress), so it's the cheapest place to get a director's approval before building. Not to be confused with `vidfarm sequence` (which GENERATES storyboard images for the pure-videogen pipeline). Alias: `plan`. |
202
251
  | `vidfarm wallet [--job <id>\|--tracer <t>] [--limit <n>]` | `GET /api/v1/user/me/wallet` | cost log: balance + lifetime spend + recent charges. `--job <renderJobId>` prints **what that one video cost** (sums its charges); `--tracer <t>` sums a tracer. Cloud-only; readable on the free plan too (shows $0.00). Aliases: `spend`, `costs` |
203
252
  | `vidfarm provider-keys` / `vidfarm add-provider-key <p> <secret>` | `GET`·`POST /api/v1/user/me/provider-keys` | manage AI keys |
204
253
  | `vidfarm upload <file> [--folder <path>]` | presign → S3 PUT → finalize (`.../temporary-files/presign` + `.../temporary-files`) | upload → durable URL (ephemeral, 30-day TTL; prefer `--folder temp` for scratch). Goes direct to S3, so large files (up to **200 MB**) bypass the ~6 MB Lambda body limit |
@@ -219,7 +268,8 @@ The licensed harness also carries the **generative build workflow** guidance (ch
219
268
  | `vidfarm raws preset list\|run\|save` / `raws export <ids…> --to <dir>` | (local library) | saved queries; copy raw MP4s out |
220
269
  | `vidfarm lint <dir\|composition.html>` | (local static validation) | pre-publish composition check: timing, overlaps, preset names, media src |
221
270
  | `vidfarm stills <dir> [--at 0,2.5,…]` | (local in-process render of PNG frames) | visually verify an edit without a full render |
222
- | `vidfarm qa <dir\|composition.html> [--json] [--strict]` | (local static QA — **devcli-only**, no cloud/REST twin) | **social-native QA: HTML slop + font regime. Run it on EVERY video you produce.** Free, instant, feedback-only |
271
+ | `vidfarm qa <dir\|composition.html> [--regime <name\|path>…] [--json] [--strict]` | (local static QA — **devcli-only**, no cloud/REST twin) | **social-native QA: HTML slop + first frame + font regime. Run it on EVERY video you produce.** `--regime` grades against a QA_REGIME.md too (stackable). Free, instant, feedback-only |
272
+ | `vidfarm regime list\|show <name\|path>\|init <name> [--out <path>]` | (local — **devcli-only**) | QA_REGIME.md: the director's own per-style quality contract. `init` copies a bundled base to edit — the pattern for bulk/scripting mode |
223
273
  | `vidfarm doctor` | (local environment triage) | check ffmpeg/node/keys/agent CLI/poisoned env + list local serve/preview processes before debugging anything else; `--kill-orphans` reaps dead servers squatting ports (fixes the "Waiting for preview server…" hang) |
224
274
  | `vidfarm skills list\|add <name>\|update` | `GET /skill-pack/index.json` · `/skill-pack/:name/*` | install/refresh skill packs (see "Skill packs — import on demand") |
225
275
  | `vidfarm tts "…" --engine local` / `vidfarm stt <file> --engine whisper` | (keyless LOCAL engines: Kokoro-82M TTS, whisper.cpp STT) | narration + word-timestamp transcripts with zero keys and zero accounts |
@@ -236,13 +286,17 @@ The licensed harness also carries the **generative build workflow** guidance (ch
236
286
  ## `vidfarm qa` — the social-native QA pass (devcli-only, heavily recommended)
237
287
 
238
288
  ```bash
239
- vidfarm qa ./work # human-readable findings + verdict
240
- vidfarm qa ./work --json # machine-readable: rule / severity / where / fix
241
- vidfarm qa ./work --strict # ALSO exit 1 on slop (only if you want a CI gate)
289
+ vidfarm qa ./work # human-readable findings + verdict
290
+ vidfarm qa ./work --json # machine-readable: rule / severity / where / fix
291
+ vidfarm qa ./work --strict # ALSO exit 1 on slop (only if you want a CI gate)
292
+ vidfarm qa ./work --regime hooks # + grade against a QA_REGIME.md (repeatable; also
293
+ # auto-discovers ./work/QA_REGIME.md)
242
294
  ```
243
295
 
244
296
  **Run this on every video you produce.** It is free, instant (pure DOM, no ffmpeg/Chrome/network), and it is the only automated check for the thing that most often ruins an agent-made video: **HTML slop**. Compositions are authored in HTML, so an agent's web-page instincts leak straight onto the frame as landing-page furniture that appears on every website and in **zero** real TikToks.
245
297
 
298
+ It also judges **one frame on its own terms: t=0**, because that frame becomes the thumbnail every feed and share sheet freezes on (see `references/editor-workflows.md`, "The first frame is the thumbnail"). Pair it with `vidfarm stills ./work --at 0` — QA finds the structural cause, the still shows you the actual poster.
299
+
246
300
  **It is feedback, not a gate.** Default exit code is **0** even when it finds slop; nothing in the render or publish path calls it; it never runs automatically. `--strict` exists only if you deliberately want a CI failure. A finding you disagree with is fine to ignore and say so — it is a lint, not a verdict on the work.
247
301
 
248
302
  **It is a BLOCKLIST, not an allowlist.** It names specific known-bad web patterns. Everything it doesn't name is legal, so a weird, ugly, hand-made, or wildly stylized composition passes untouched. It will never push your videos toward one house style — if it fires on a genuine creative choice, that's a bug in the rule, not in your video.
@@ -261,9 +315,14 @@ What it flags:
261
315
  | `font-regime` | error/warn | A text layer in a website body font (Inter/Roboto/Arial/system-ui → **error**) or any family outside the imported regime (Montserrat, TikTok Sans, Abel, Source Code Pro, Yesteryear → warn, it silently falls back at render) |
262
316
  | `font-size` / `font-weight` | error/warn | `font-size:0` (invisible) is an error; sub-2.6%-of-canvas-width text and weight <600 warn |
263
317
  | `caption-safe-zone` | warn | Text outside the 8%–85% band on a **portrait** canvas (landscape/square are exempt) |
318
+ | `thumbnail-blank-open` | error | Nothing on screen at **t=0** — the opening clip starts late, so the poster frame is black |
319
+ | `thumbnail-fade-in` | error/warn | An **entrance** transition on the FIRST clip: `fade-black`/`fade-white`/`flash`/`smoke` → **error** (frame 0 is a flat solid); any other preset → warn (frame 0 caught mid-move). Junction transitions on later clips are never flagged |
320
+ | `thumbnail-no-hook-text` | warn | The composition has text, but none of it is up at t=0 — the poster carries no hook words. Ignorable when you're deliberately opening on a clean face/product shot |
264
321
 
265
322
  Every finding carries a concrete `fix` line — the answer is always "say it as timed text on the footage", never just "delete it". Fold `--json` into scripted batch runs to QA N variants at once.
266
323
 
324
+ **The two halves, and why the tool only claims one.** Everything above is universal and mechanical. The half that decides whether a *particular* video is any good — is the hook legible cold, does the loop close, is this variant genuinely different from its siblings — is the director's, and it lives in a **`QA_REGIME.md`** (see "Scripting mode" above). Pass one with `--regime <name|path>` (repeatable, and a `QA_REGIME.md` sitting next to the composition is picked up automatically): its `checks:` front matter is settled deterministically alongside the built-ins, and its `- [ ]` checklist comes back as **review items you must answer yourself**. `vidfarm qa` deliberately never fakes a verdict on those — a "PASS" it couldn't have earned is worse than no check at all.
325
+
267
326
  ## Cost mode — the devcli's money-saving guardrail
268
327
 
269
328
  The four modes, quoted as **cost per finished video**. The first two are spend postures; the last two are also *production methods* — `rich-ai` buys reusable greenscreen raws and animates them in HTML, `pure-videogen` generates every frame: