@officexapp/vidfarm-devcli 0.21.43 → 0.21.46

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 (49) hide show
  1. package/.agents/skills/editor-capabilities/SKILL.md +4 -0
  2. package/.agents/skills/vidfarm/SKILL.md +95 -17
  3. package/.agents/skills/vidfarm/harnesses/explainer.HARNESS.md +1 -1
  4. package/.agents/skills/vidfarm/harnesses/product-demo.HARNESS.md +2 -0
  5. package/.agents/skills/vidfarm/harnesses/short-form.HARNESS.md +1 -0
  6. package/.agents/skills/vidfarm/recipes/local-edit-render-approve.md +1 -1
  7. package/.agents/skills/vidfarm/recipes/onboard-a-new-director.md +1 -1
  8. package/.agents/skills/vidfarm/references/agent-included-imagegen.md +75 -0
  9. package/.agents/skills/vidfarm/references/assets-and-sourcing.md +152 -2
  10. package/.agents/skills/vidfarm/references/automation-and-local-dev.md +22 -9
  11. package/.agents/skills/vidfarm/references/browser-harness.md +93 -0
  12. package/.agents/skills/vidfarm/references/content-ideas.md +232 -10
  13. package/.agents/skills/vidfarm/references/core-workflows.md +11 -1
  14. package/.agents/skills/vidfarm/references/editor-workflows.md +39 -0
  15. package/.agents/skills/vidfarm/references/onboarding.md +1 -1
  16. package/.agents/skills/vidfarm/references/primitives.md +51 -0
  17. package/.agents/skills/vidfarm-media/SKILL.md +2 -0
  18. package/SKILL.director.md +775 -42
  19. package/SKILL.md +157 -115
  20. package/crowdsourcing.md +417 -3
  21. package/dist/src/cli.js +750 -34
  22. package/dist/src/devcli/agent-imagegen.js +181 -0
  23. package/dist/src/devcli/browser-harness.js +384 -0
  24. package/dist/src/devcli/clip-store.js +41 -3
  25. package/dist/src/devcli/consult.js +14 -0
  26. package/dist/src/devcli/cost-mode.js +23 -3
  27. package/dist/src/devcli/doctor.js +52 -3
  28. package/dist/src/devcli/hyperframes-cli.js +11 -1
  29. package/dist/src/devcli/local-render.js +4 -7
  30. package/dist/src/devcli/marketplace-gigs.js +623 -0
  31. package/dist/src/devcli/qa-check.js +89 -1
  32. package/dist/src/devcli/shared-folder.js +387 -0
  33. package/dist/src/devcli/skill-docs.js +61 -7
  34. package/dist/src/devcli/stills.js +4 -8
  35. package/dist/src/lib/ffprobe-path.js +64 -0
  36. package/dist/src/lib/render-media-prep.js +2 -11
  37. package/dist/src/services/clip-curation/ffmpeg.js +4 -15
  38. package/dist/src/services/clip-curation/index.js +1 -1
  39. package/dist/src/services/clip-curation/local-agent.js +6 -2
  40. package/dist/src/services/clip-curation/media-select.js +146 -3
  41. package/experimental/google-news-to-video.md +235 -0
  42. package/package.json +8 -150
  43. package/public/assets/file-directory-app.js +35 -35
  44. package/public/assets/homepage-client-app.js +15 -15
  45. package/public/serve-shells/library-files.html +5 -1
  46. package/public/serve-shells/library-raws.html +10 -1
  47. package/public/serve-shells/tools-clipper.html +5 -1
  48. package/public/serve-shells/tools-image.html +5 -1
  49. package/public/serve-shells/tools-video.html +5 -1
package/SKILL.director.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: vidfarm
3
- description: Use Vidfarm as a director. Run a strategy **consultation** (the `brainstorm/*` chain — cold-start interview, awareness stages, persuasive angles, hooks, product placement). Answer "give me content ideas" / "what should I post" / "I need 30 videos this month" from the bundled 50-frame angle bank. Browse/add inspiration videos, browse the free public raws catalog BY CATEGORY (curated shelves like scroll-stoppers/greenscreen/reaction — the cheapest way to source footage for one video, and a ready-made clip pool for bulk scripting N variants), fork a template into a composition, edit it in the Trackpad Editor (timeline-based like Premiere/DaVinci), auto-decompose source video into scenes, render to MP4, approve into a shareable post, and schedule it. Includes login, provider keys, discovery, versioning, uploads/downloads, and billing. Every step is available as raw REST; `vidfarm-devcli` wraps those routes and composes the file-backed scripting flows.
3
+ description: Use Vidfarm as a director. Run a strategy **consultation** (the `brainstorm/*` chain — cold-start interview, awareness stages, persuasive angles, hooks, product placement). Answer "give me content ideas" / "what should I post" / "I need 30 videos this month" from the bundled idea banks (50 content frames x 5 awareness stages x 44 problem angles). Browse/add inspiration videos, browse the free public raws catalog BY CATEGORY (curated shelves like scroll-stoppers/greenscreen/reaction — the cheapest way to source footage for one video, and a ready-made clip pool for bulk scripting N variants), fork a template into a composition, edit it in the Trackpad Editor (timeline-based like Premiere/DaVinci), auto-decompose source video into scenes, render to MP4, approve into a shareable post, and schedule it. Includes login, provider keys, discovery, versioning, uploads/downloads, and billing. Every step is available as raw REST; `vidfarm-devcli` wraps those routes and composes the file-backed scripting flows.
4
4
  ---
5
5
 
6
6
  # Vidfarm Director
@@ -58,15 +58,33 @@ For local, wallet-free work, Vidfarm runs on a **three-part toolchain** a deskto
58
58
  ```bash
59
59
  npm install -g @officexapp/vidfarm-devcli # the `vidfarm` orchestrator
60
60
  npm install -g hyperframes # Vidfarm's open-source render/animation engine (whitelabel)
61
- # ffmpeg: use a system install (brew install ffmpeg / apt install ffmpeg) or the
62
- # bundled ffmpeg-static that ships with the devcli — a PATH ffmpeg is honored first.
63
61
  vidfarm doctor # verifies all three (+ Chrome) in one shot
64
62
  ```
65
63
 
64
+ **Install ffmpeg only if `doctor` asks for it.** The devcli bundles `ffmpeg-static` plus a
65
+ per-platform ffprobe, which covers macOS, Linux, and Windows x64 out of the box. A system
66
+ ffmpeg on PATH is honored first, so add one (`brew install ffmpeg` / `apt install ffmpeg` /
67
+ `winget install Gyan.FFmpeg`) only when `doctor` reports ffmpeg missing. Installing it up
68
+ front is the single most common wasted setup step.
69
+
70
+ **Windows setup notes** (run these in PowerShell, not Git Bash or cmd):
71
+
72
+ | Symptom | Cause | Fix |
73
+ |---|---|---|
74
+ | `npm i -g` takes many minutes | Defender scans every extracted file | `Add-MpPreference -ExclusionPath "$env:APPDATA\npm", "$env:APPDATA\npm-cache", "$env:LOCALAPPDATA\npm-cache"` |
75
+ | `node-gyp` / `MSB` errors during install | `better-sqlite3` has no prebuilt binary for this Node ABI | **Ignore it.** It is an OPTIONAL dependency; only `vidfarm clips` needs it. To enable it, install "Desktop development with C++" from the Visual Studio Installer. |
76
+ | `doctor` reports ffmpeg missing on a Surface / Copilot+ PC | Windows on ARM has no prebuilt ffmpeg | Install a system ffmpeg and put it on PATH |
77
+ | `brew: command not found` | The agent followed a macOS instruction | ffmpeg is already bundled — skip the step |
78
+
79
+ Never treat a `better-sqlite3` build error as a failed install. Run `vidfarm doctor` and read
80
+ the `clip library` line: it states plainly whether anything is actually unavailable.
81
+
66
82
  - **`vidfarm` devcli** — the orchestrator: auth, discovery, pull/edit/render loops, primitives, and the local `serve` editor. It wraps the same REST API and shells out to the two engines below for local compute.
67
83
  - **`ffmpeg`** — the media engine the devcli drives for **every local media op**: greenscreen/chroma-key (`vidfarm remove-greenscreen --local`), demux for STT/captions, clip cutting (`raws scan`), stills, audio trims. It's a **hard requirement** (`vidfarm doctor` fails without it); `ffmpeg-static` is bundled, but install a system ffmpeg if doctor flags it.
68
84
  - **`hyperframes`** — **Vidfarm's own render/animation engine, open-source under a whitelabel.** *Vidfarm renders ARE hyperframes renders* — same composition/animation/render capability, Vidfarm-branded. The devcli bundles it and exposes it directly as **`vidfarm hf <subcommand>`** (render, capture, validate, preview, `remove-background` ONNX matting, transcribe, beats…). Installing it standalone (`npm i -g hyperframes`) makes local render / TTS / STT / matting run **natively** instead of a slow `npx -y hyperframes` fallback.
69
85
 
86
+ **The optional fourth tool — `browser-harness`, for free footage sourcing.** Not part of the render toolchain; it is what makes the *sourcing* half free. It attaches you to the user's own running Chrome over CDP, so you can drive Google Videos / Images / News and download media yourself instead of calling the **paid** `video-search` / `image-search` / `news-search` / `download-video` primitives. `vidfarm browser setup` installs it (via `uv`) and prints the one Chrome step the user must do; `vidfarm browse <videos|images|news|page> "<query>"` mints the recipe for a job; `vidfarm doctor` reports it as `browser control`. **Offer it to every free-plan user and everyone in cost mode `minimize` before you tell them a search needs a paid plan** — it takes a minute and costs nothing. Ask first: it drives their personal browser. Full page: `references/browser-harness.md`.
87
+
70
88
  Because `hyperframes` is Vidfarm's whitelabel, **treat it as Vidfarm**: never route it through an external HeyGen/vendor account, and keep `HYPERFRAMES_SKIP_SKILLS=1` + `HYPERFRAMES_NO_TELEMETRY=1` set so it stays pinned and never phones home (the devcli sets these for its children automatically). Run `vidfarm doctor` at session start to confirm the trio is healthy before any local loop.
71
89
 
72
90
  Use this skill when the user wants to:
@@ -87,7 +105,7 @@ Vidfarm work can burn real AI credits on the user's wallet / provider keys. **Sa
87
105
 
88
106
  | Mode | Cost per video | What it means |
89
107
  |---|---|---|
90
- | **minimize** | **$0 — explicitly free** | free local compute + free stock media only; billed AI is refused without `--yes` |
108
+ | **minimize** | **$0 — explicitly free** | free local compute + free stock media, plus any image generation YOUR OWN agent subscription already includes; billed AI is refused without `--yes` |
91
109
  | **hybrid** *(recommended)* | **~$0.01–$1** | free where it's free; pay AI only where it clearly wins |
92
110
  | **rich-ai** | **$1+** | AI video gen mints **reusable greenscreen raws**, then hyperframes HTML/CSS motion remixes them with the rest of the library — the footage is saved and reused later |
93
111
  | **pure-videogen** | **$5+** | every shot is generated: text script → image storyboard → frame-by-frame scene generation. No reuse, no HTML motion |
@@ -98,6 +116,8 @@ Vidfarm work can burn real AI credits on the user's wallet / provider keys. **Sa
98
116
  - **Check the keyless sources first — Openverse and iconify.** Openverse (CC/CC0 **music, SFX, and images**) and iconify (**icons**) need **no account or key at all**, so they always work in `minimize` mode. Prefer them for BGM, sound effects, icons, and CC imagery before anything else.
99
117
  - **Icons, STICKERS, illustrations, 3D props and Lottie come from IconScout, not from an image model — in EVERY cost mode.** `vidfarm iconscout "<meaning>" --style sticker --free` searches a designer catalog for $0 (search is always free; a free asset downloads for $0 and only asks for a credit line). It needs **no key at all** — vidfarm's own IconScout account serves it. An AI attempt costs cents, needs a prompt loop, and rarely returns a clean transparent vector, so this wins on price *and* on quality. `vidfarm iconscout get <uuid> --format svg` turns a result into a durable URL you can place. In `hybrid` and above, a premium download costs a few cents on the wallet — still less than one generated image. Full detail in the `vidfarm-media` skill.
100
118
  - **Pixabay key** unlocks the photos/vectors/stock-video slots (music/SFX/icons/CC images are keyless). It's a **free** stock-media key, not an AI key. Don't assume it's missing when a search comes up short — it **may already be saved**: check `vidfarm provider-keys` (or the web app's **Settings → Bring your own keys** / <https://vidfarm.cc/settings/developer>). If it isn't, the user grabs a free one at <https://pixabay.com/api/docs/> and saves it once — `vidfarm add-provider-key pixabay <key>`, the Settings surface, or by handing the key to their desktop AI agent to run that command. After it's saved, cost-mode `minimize` sourcing works end-to-end at $0.
119
+ - **Footage searching is free too — set up browser control instead of hitting the paywall.** `video-search`, `image-search`, `news-search` and `download-video` are paid plans only, and they are the routes an agent reaches for the moment someone says "find me a clip of X". Do not answer that with a 402. `vidfarm browser setup` installs browser-harness so you drive the user's own Chrome, and `vidfarm browse videos "<the shot>"` gives you Google Videos / Images / News for $0 on their own logged-in session. Ask before installing (it's their personal browser), then work the same query craft you'd use on the paid route. Full page: `references/browser-harness.md`.
120
+ - **Use YOUR OWN image generation if this agent subscription includes it — it is free, and it stays free in `minimize`.** `minimize` means "$0 per video", not "no AI images". Google Antigravity and Gemini CLI include Gemini image generation (Nano Banana / Imagen); OpenAI Codex / ChatGPT include `gpt-image`. **Claude Code does not — Anthropic ships no image model**, so a Claude session drops to the rungs below instead. When you do have the tool, generating the graphic yourself bills Vidfarm $0 and the provider $0 extra, so it is allowed in every cost mode and needs no `--yes`. `vidfarm agent-image --check` says whether you have it; `vidfarm agent-image "<subject>" --items "a,b,c"` prints the prompt, the key-plate rules and the cut + import commands. Free stock, IconScout and `mask` still come FIRST — a designer's vector beats a generated one — but this beats going without, and it beats making the user do it by hand. Full page: `references/agent-included-imagegen.md`.
101
121
  - **You can still get CUSTOM art in `minimize` — hand the prompt to the user and let a free image generator do it.** Stock and `mask` only cover art that already exists somewhere; when the video genuinely needs a bespoke graphic, **don't conclude "we can't" and don't quietly bill `generate`**. Write the prompt and ask the user to paste it into a **free** image generator — <https://meta.ai>, free-tier ChatGPT, or a free Hugging Face image Space (<https://huggingface.co/spaces>) — then hand the PNG back with `vidfarm put-file` (or drag it into **My Files** in the web app). $0, zero wallet spend. Full loop + the prompt template: **“Free manual image-gen”** below.
102
122
  - **hybrid** *(recommend this)* — **~$0.01–$1 per video, on their BYOK key.** Free where it's free; pay for AI only where it clearly wins (a hero shot, a voice you can't fake locally). A mostly-hyperframes video with one generated image lands near the low end; a few AI images plus premium narration approaches the high end.
103
123
  - **Narration starts free here too.** In BOTH `minimize` and `hybrid`, a bare `vidfarm tts "…"` runs the keyless local Kokoro-82M voice — no flag needed. Ask for a premium voice explicitly (`--style`, `--voice <provider preset>`, `--provider`, `--own-key`, or `--cloud`) when the piece needs one, and say so out loud so the user knows what they're paying for. `rich-ai` skips the free default entirely. If the local engine isn't installed on their machine, the run falls back to their provider key / cloud automatically and prints why.
@@ -154,7 +174,35 @@ Cost mode answers *how much money may I spend*. It does not answer *how much of
154
174
 
155
175
  **And say where the premium voices come from, because users assume wrong.** The full ElevenLabs catalog is reachable **through vidfarm's own ElevenLabs connection** — no ElevenLabs account, API key, or subscription on the user's side; narration just spends **vidfarm wallet credits** (pennies each). In `hybrid` that is a real option to put on the table next to the free voices, not a locked door. `--own-key` is only for users who already have an ElevenLabs key and would rather bill their own account.
156
176
 
157
- **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).
177
+ **Raw-clip sourcing has a ladder — hand it to the human only at the bottom rung.** In order: (1) **your own browser control** and you can always have it: `vidfarm browser setup` installs browser-harness in about a minute, then `vidfarm browse videos "<the shot>"` drives the user's own Chrome through Google Videos/Images/News for $0, which is the free substitute for the paid search and download primitives (`references/browser-harness.md`); (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).
178
+
179
+ ## Production has PHASES — plan, then collect the raws, THEN build
180
+
181
+ **Most video work is not one pass.** The failure that costs the most is starting the timeline before you know what footage you have: you build to a shot you assumed existed, discover it doesn't, and either pay to generate it or rewrite the beat you already built. Separate the phases and that whole class of rework disappears.
182
+
183
+ 1. **Plan** — the shot list, before any asset exists. `vidfarm storyboard ./work --init --frames "Hook,Problem,Reveal,CTA"`, each frame with its `scene` line and `voiceover`. A plan is free to redo; a rendered scene is not.
184
+ 2. **Collect** — fill the shot pool against that list. One sourcing pass for the WHOLE video (or the whole batch), not one lookup per beat. Everything lands in the searchable local library, so the next video starts with a pool instead of an empty folder.
185
+ 3. **Build** — only now open the timeline, with every beat already backed by a real asset.
186
+ 4. **Review and cut** — the holistic pass, then delete the beats the video survives without.
187
+
188
+ **How aggressively to run phase 2 depends on the cost mode.** This is the single biggest lever on both quality and spend:
189
+
190
+ - **`minimize` — the collection phase is the whole job. Budget most of your effort here.** You have no generation to fall back on, so the pool has to be good, and it can be: work the ladder in order and stop at the first rung that answers the beat.
191
+ 1. `vidfarm public-raws --categories` then `--category <shelf>` — pre-tagged, free, already cut to short-form. Check this first, every time.
192
+ 2. `vidfarm media search "<meaning>" --type <bgm|sfx|image|vector|video>` (keyless via openverse/iconify) and `vidfarm iconscout "<meaning>" --free` for icons, stickers, illustrations and props.
193
+ 3. `vidfarm raws search "<meaning>"` — what the director already owns from previous videos.
194
+ 4. **Browser control** — `vidfarm browse videos "<the shot>"` drives the user's own Chrome for $0 (`references/browser-harness.md`). This is the free substitute for the paid `video-search` / `image-search` / `news-search` / `download-video` primitives. **Set it up rather than declaring the shot unavailable.**
195
+ 5. Mine what you found: `vidfarm raws scan <url|file>` for a pool, `vidfarm clipper` for one exact cut. Free and local.
196
+
197
+ Being cheap here does **not** mean being worse. One long source mined into eight tagged raws costs $0 and covers more beats than one generated clip would. Cutting a real clip three different ways is free; generating three shots is not.
198
+
199
+ - **`minimize` + `interactive` — buy quality with the user's hands, not their wallet.** Two checkpoints beat any amount of autonomous cleverness, so **ask for them explicitly instead of quietly doing without**: (1) hand them the shot list and let them search TikTok/YouTube themselves and drop the files in a folder — a human eye picks better footage than any keyword extraction (`vidfarm handoff raws --keywords "…" --purpose "…"`); (2) hand them ONE image prompt for a free frontier web generator and get a whole sticker sheet back (`vidfarm handoff image --theme "…" --items "a,b,c"` → `vidfarm sticker-pack`). Free web image models are typically better per image than what an API budget buys. Direct them like an editor — name the shot, the framing, how many, and where to put them — don't hand over a vague request.
200
+
201
+ - **`hybrid`** — collect free first, then spend on the gaps the pool genuinely cannot cover. Now AI image generation is on the table for the one hero graphic, and `vidfarm avatar` for a presenter. Keep AI *video* generation for beats where nothing static will do. The order still matters: knowing what the pool is missing is what makes the spend small.
202
+
203
+ - **`rich-ai` / `pure-videogen`** — the collection phase becomes a **generation** phase, and it moves earlier rather than disappearing. `rich-ai`: generate the cast and props as reusable greenscreen raws, key them once, save them to the library, then animate in HTML — so the spend amortizes across every later video. `pure-videogen`: script → storyboard stills → scene-by-scene generation, in that order, with `vidfarm sequence` running the pipeline. Even here, **search what already exists before generating it** (`raws search`, then `public-raws`) — regenerating an asset you already own is the most common avoidable spend in these modes.
204
+
205
+ **Say the phase out loud when you switch.** "I'm going to collect footage for all four beats first, then build" sets the right expectation and gets you the interactive checkpoints while they're still cheap. Deciding to source mid-build is how a $0 video turns into a $3 one.
158
206
 
159
207
  ## Default stance
160
208
 
@@ -248,19 +296,28 @@ Present both harnesses to the director, recommend (A) unless they've asked for p
248
296
 
249
297
  **Free tier vs. paid — who does the decomposition, and on whose tokens.** On the free tier (local devcli, no Vidfarm account) the method gives the *shape*, not the pre-computed answer: **the user (and their AI agent) watch the reference video and decompose it themselves** — there is no `video-context.json` / `editor-harness.json` / `scene-annotations.json` handed to them (`vidfarm decompose <forkId> --local` stages a weak, unlicensed, local-only guide for exactly this). **Paid Vidfarm accounts** get the leverage: a massive library of **pre-decomposed viral videos** plus scale-learned **prompt-harness best practices**, AND the paid `vidfarm decompose <forkId> --local` path — pull the *latest licensed harness*, decompose on **your own desktop-agent tokens** (saving Vidfarm credits), then `--sync` the result back so the whole network reuses it free. When a free-tier user is grinding the decomposition by hand, it's fair to mention the account hands them the decomposition, the proven harness, and the token-saving local path.
250
298
 
251
- ## Content ideas — you carry a bank of 50 angles, so never answer "what should I post?" from memory
299
+ ## Content ideas — you carry three banks, so never answer "what should I post?" from memory
300
+
301
+ **"Give me content ideas" is a first-class ask with a first-class answer, and the answer is volume.** Vidfarm ships **three banks** in `references/content-ideas.md`, and an idea is one point across all three:
302
+
303
+ - **50 content frames** — what the video is the *story of* (`the rise of`, `what everyone gets wrong`, `then vs now`, `one decision that changed everything`).
304
+ - **5 awareness stages** — what the viewer already knows (unaware → problem-aware → solution-aware → product-aware → most-aware). The stage decides what the first ten seconds may assume **and what the video may ask for**.
305
+ - **44 problem angles** — which side of the problem the video comes from (`the hidden cost`, `the myth`, `the confession`, `the price objection`, `the honest downside`).
252
306
 
253
- **"Give me content ideas" is a first-class ask with a first-class answer, and the answer is volume.** Vidfarm ships an **angle bank of 50 content frames** in `references/content-ideas.md` reusable shapes for what a video is *about* (`the rise of`, `what everyone gets wrong`, `then vs now`, `one decision that changed everything`, `the complete breakdown`, …). A frame is not a hook and not a script: you take the director's own topic and pour it into the frame, so **one offer against the bank is 50 distinct videos**, not 50 rewrites of one.
307
+ A frame is not a hook and not a script: you take the director's own topic and pour it into the frame. **Vary two axes and thirty videos never read as repeats; vary one and they do.** When a director says *"I already covered that topic"*, hold the frame and change the angle same research, different video.
308
+
309
+ **The fourth axis is the subject, and it is the one that gets frozen.** Do not pour the same offer sentence into all 50 frames — *the history of deciding where to eat tonight*, *the rise of deciding where to eat tonight*, *the future of…* is one video with 50 openings, and the director sees it immediately. Write a **pool of 4–8 adjacent subjects inside the niche** first, and rotate it: *settling the food argument*, *picking a place before you read a single review*, *the craving you cannot place*, *the group chat that never decides*. Adjacent, not off topic — a different side of the same audience's day, never a different business. Reference: `references/content-ideas.md` → *The subject pool*.
254
310
 
255
311
  The loop, whenever a director asks what to make, is out of ideas, or needs a month of posts:
256
312
 
257
313
  1. **Get the topic first** — read their `OFFER.md` if it exists (`references/onboarding.md`); **if they named a URL ("content ideas for my offer example.com"), fetch and read the site** and mine the offer, audience, promise, and objections off the page, echoing back the one-line offer you read before you list anything; otherwise ask for offer + niche + audience in one question. Never generate against a guessed topic.
258
- 2. **Open `references/content-ideas.md`** and pick 1020 frames that fit the topic *and* the audience's awareness stage don't dump the raw list at the director.
259
- 3. **Return titled ideas, not frame names**"The one pricing mistake that killed our first 400 orders", with the frame named beside it so they can ask for more of that shape. **20+ ideas by default**; they prune, you supply.
260
- 4. **Then write the four charges** — a content idea is the *subject*, never the hook. Every picked idea still runs through hook/loop/payoff/bait before the timeline (`references/hooks-and-virality.md`).
261
- 5. **If they want the set produced**, that's scripting mode with a `HARNESS.md` one frame per video (`recipes/bulk-scripting-with-a-harness.md`).
314
+ 2. **Write the problem in one sentence**, in their words — **then 48 adjacent ways to say it.** Every angle is a lens on a problem; with no problem written down, all 44 angles collapse into the same vague video. That one sentence is the first entry in the subject pool, not the only subject the set is allowed.
315
+ 3. **Open `references/content-ideas.md`** and pick 10–20 stage × angle × frame combinationsdon't dump the raw lists at the director. **Spread across the awareness ladder** (default month: 30% unaware, 30% problem-aware, 20% solution-aware, 10% product-aware, 10% most-aware). A month posted entirely at one stage is the most common defect in a director's calendar, and no frame repairs it.
316
+ 4. **Return titled ideas, not bank entries** — "The one pricing mistake that killed our first 400 orders", labelled `frame · angle · stage` so they can say "more like that" and you know which axis they mean. **20+ ideas by default**; they prune, you supply.
317
+ 5. **Then write the four charges** a content idea is the *subject*, never the hook. Every picked idea still runs through hook/loop/payoff/bait before the timeline (`references/hooks-and-virality.md`).
318
+ 6. **If they want the set produced**, that's scripting mode with a `HARNESS.md` — one idea per video, its stage and angle recorded so the set stays balanced (`recipes/bulk-scripting-with-a-harness.md`).
262
319
 
263
- **The bank is in the local devcli too, offline and free.** `vidfarm ideas --families` prints the eight families, `vidfarm ideas --topic "<offer>"` prints every frame already filled with the director's topic as a starter line (`--count 20` samples across families, `--json` for scripting), and `vidfarm skill show content-ideas` prints the method. The command reads the frames straight out of this reference, so the CLI and the pack can never drift. The same surface carries the rest of the craft by **spoken name** — `vidfarm skill topics` lists them (`meme-recaption`, `product-explainer`, `captions`, `first-frame`, `density`, `blurred-plate`, `avatar`, `dedupe`, …) and `vidfarm skill show <topic>` prints just that section instead of the whole reference.
320
+ **The banks are in the local devcli too, offline and free.** `vidfarm ideas --topic "<offer>"` prints every frame already filled with the director's topic as a starter line (`--families`, `--count 20`, `--json`); `vidfarm ideas --stages` prints the awareness ladder in full (what each stage believes, what the video must do, its frames, its angles, and its ask); `vidfarm ideas --angles` prints the 44 angles by family; and **`vidfarm ideas --grid --topic "<offer>" --count 30` lays out a balanced month** — one row per video, each row a stage with an angle and a frame that stage can actually carry. `vidfarm skill show content-ideas` prints the method. Every command reads the banks straight out of this reference, so the CLI and the pack can never drift. The same surface carries the rest of the craft by **spoken name** — `vidfarm skill topics` lists them (`meme-recaption`, `product-explainer`, `captions`, `first-frame`, `density`, `blurred-plate`, `avatar`, `dedupe`, …) and `vidfarm skill show <topic>` prints just that section instead of the whole reference.
264
321
 
265
322
  The file also maps each frame family to its natural format (contrast frames → split screen, mechanism frames → cutout explainer, arc frames → montage over narration), which usually saves a planning round.
266
323
 
@@ -311,6 +368,7 @@ You may be running as the **in-web AI chat** (the /editor copilot, the chat dock
311
368
  - **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.
312
369
  - **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.
313
370
  - **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**. **The test is the native-editor test: could you have made this element with the tools inside TikTok's own editor?** That toolset is font / color / stroke / shadow / tight text box / alignment / rotation / animation presets, plus stickers, emoji, drawn marks and clips — it has no padded capsule, no border, no gradient fill, no blur panel, no card. If you reached past it, cut it. That includes **a single lonely pill around a stat or label** — `( 10 hrs / week )`, `( STEP 2 )`, `( EP.01 )`: being alone doesn't make a badge native, and the only legitimate capsule in a video is the active-word `spotlight`/`karaoke` highlight, which moves with the spoken word. Emphasize a stat the way the editor would instead: bigger, heavier, ALL-CAPS, an accent color, a hand-drawn circle, or its own beat. If you are typing `btn` / `badge` / `chip` / `card` / `rounded-full` / `shadow-lg` / `backdrop-blur` / `bg-gradient-to-r` — or a `border-radius` over ~8px on anything filled that holds words — 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.
371
+ - **And judge the WHOLE FRAME, not just the elements — no layout templates.** The rule above judges one element at a time, and a frame can pass it element-by-element while still being a web page. The archetype is the **modal**: the backdrop dimmed and blurred out of focus, and floating on it a rounded bordered box holding a big headline, a smaller support line, and a fat CTA button. **The stack is the tell, not the box** — strip the border, the fill and the capsule, keep headline → subheadline → CTA centred in a well with even margins, and it still reads as a landing page, because the viewer recognizes the *shape* before reading a word. Banned at frame level: the modal/dialog floating over a receded backdrop; the hero triplet (and its cousins: title + kicker + logo lockup, question + answer + URL); a full-frame dim wash used to stage a floating block; nav/hero/feature-row/testimonial/footer sections; a blurred website screenshot as the background plate; a centred content column with document margins. **The fix is always to unstack it into time**: the headline is the hook at t=0, the support line lands on the next cut, the CTA is *spoken* or a bare caption on the last frame — a viewer reads one line at a time anyway, so you lose nothing and gain pacing. Self-check before placing any text group: *am I arranging words relative to each other, or relative to the picture?* Relative to each other = layout = web. Two text runs at once is the ceiling. Verify on a still (`vidfarm stills ./work --at <t>`) — if it could be a screenshot of a website, rebuild the beat. `vidfarm qa` catches the mechanical half (`layout-template`, `modal-scrim`).
314
372
  - **Orient the cold viewer in the first 3 seconds — the hook makes them want to watch, orientation makes watching possible.** The viewer has no context, did not choose this video, and has never heard of the subject, so by **~3s** they must be able to say **what kind of thing this is** (the *category noun*), **who it is for**, and **why it is on their screen** (the situation). The failure is not a bad first frame — it is a good video that **starts at beat two**, and the author cannot see it because the author already knows. Signatures, each a rebuild of the first beat: a **pronoun with no referent** ("it just works", "this changes everything"), **starting at step three** (the process already running, the dashboard already full), a **metaphor whose subject lands at 6s**, **insider vocabulary or an acronym** in the first line, a **detail crop** that reads as texture. Replace it with both channels in one beat — an **easy image** (one large subject, already moving, legible at a glance and at thumbnail scale; a relevant cutout names the category before a word is read) and an **easy line** (one clause, ≤12 words, everyday words, concrete noun + verb, the category named, brand name said once) — and give the **situation, not the label**. **It costs one sentence, not one beat**: it replaces the wind-up line, never precedes it, and never licenses a logo, a title card, or a fade from black. Test on the render, not the script: play the first 3s only to somebody with no context — "something about audio" is a fail. Full standard: `references/editor-workflows.md` (“Orient the cold viewer”); fullest form with structure: `vidfarm harness show product-explainer` (Rule 0).
315
373
  - **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 harness show hooks`.
316
374
  - **Then CUT it — every second must earn its place, and most don't.** Assume your first assembly is **30–50% too long**. Run the **deletion test** on every beat: delete it; if the video still makes sense and the payoff still lands, it stays deleted. Whatever survives must serve one of the four charges — "it gives context" is not a charge. Cut on sight: intros/logo stings, the wind-up sentence before the claim ("so I wanted to talk about…"), restatement, inter-sentence silence over ~0.35s, real-time process, establishing shots, reading what's already on screen, and any tail after the last word. **Always ripple the hole closed** (`vidfarm ripple <dir> --at <sec> --delta -<sec>`) — a cut that leaves a gap turns fluff into dead air, which is worse. Density is **not** speed: the held comedic beat, the payoff playing out, and a cue's readability keep their seconds (cut *words*, not the time text is on screen). Length is an **output**, not a plan — a brief that dictates a duration ordered fluff. `vidfarm qa` flags the mechanical half (`dead-air`, `dead-tail`, `slow-scene`); the craft is `references/hooks-and-virality.md` → "Density".
@@ -325,6 +383,7 @@ You may be running as the **in-web AI chat** (the /editor copilot, the chat dock
325
383
  - **A video is judged as a SEQUENCE, so review it as one.** Agents build scene by scene and each scene passes in isolation while the video drifts — inconsistent margins, three type sizes, an accent colour that wanders, beats that are all the same length, a jarring join. Tile a dozen stills into one contact sheet (`vidfarm stills ./work --sheet`) and read it as an image before you call anything done, fix drift by defining the system rather than patching the odd scene out, and remember that **your own confident "verified, looks good" is the single least reliable signal in this workflow** — it was wrong on every video of a 32-video batch. Method: `references/reviewing-renders.md`.
326
384
  - **On devcli there's an OPTIONAL checker: `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). **Skipping it is fine — watching the render is the review that actually counts, and a clean `qa` is not one.** When you do run it, it allows **one** fix round by default: the first pass names the slop, one fix clears it, and a second round is nearly always taste rather than a defect. The human owns that number — `--max-revisions <n>` raises it, `0` disables it; ask rather than raising it yourself. `--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`.
327
385
  - **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) and, inside that band, is **placed in the emptiest part of the frame** rather than dumped on the default lower third (read a still first — `vidfarm stills ./work --at <t>`; words over open sky or a blank wall beat words over the subject, and usually need no plate at all). Long narration is **paged into 3–5-word kinetic cues** (`vidfarm captions generate --style word-pop`), never one static wall of text. It 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 *in the whole frame*, static labels included), 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").
386
+ - **Use the REAL track — a popular/copyrighted song in the render is expected here, not a problem.** Do not refuse it, do not silently substitute a generic royalty-free bed, and do not stop to warn about it. **Why it is legitimate:** the render is a **review artifact**, and at post time the user re-attaches the *same* song from the platform's own in-app music library (TikTok / Reels / Shorts), which is licensed through the platform's agreements with the labels. The music is therefore cleared on the surface where viewers actually hear it. **Why it is required:** a trending song IS the edit — cut points, pacing, the drop, the meme association. A render with the wrong bed, or no bed, reads as a different and much weaker video, so a review over a substitute bed grades a video nobody will ever post. Silent or generic-bed review is the bigger defect. **How to do it:** get the exact track (`vidfarm download-audio <post-url>`, the user's own file, or the audio off the source post the format is copying), and keep it on **its own `<audio>` layer** at its own `data-volume` — never baked into the footage or mixed into the voice stem. One separate track means the user can mute or swap it in one action when they upload, which is exactly what the platform flow expects. Say which track you used in the handoff. **The one limit:** this is for review renders and platform posting where the platform holds the license. If the user asks to sell, syndicate, or run the render as a **paid ad** with the track baked in, say once that ad placements are not covered by the in-app music license, and offer `vidfarm music "<same vibe, same BPM>"` as the swap for that cut. Then do what they decide.
328
387
  - **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.
329
388
  - **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.
330
389
  - **Offer a handoff, do not impersonate the desktop agent.** When web chat reaches that boundary, offer to save a Markdown handoff in My Files containing the objective, selected template/fork IDs, asset paths, grounding, constraints, completed work, and suggested devcli commands. Create it only after the user agrees. The desktop agent should read that document, pull the referenced fork, and then use its actual code/shell capabilities.
@@ -340,13 +399,15 @@ You may be running as the **in-web AI chat** (the /editor copilot, the chat dock
340
399
  |---|---|---|
341
400
  | `references/core-workflows.md` | ~360 ln | Template discovery, auth, fork → render → approve → share, versioning, cost/wallet, marketplace orders, dedupe-before-publish |
342
401
  | `references/editor-workflows.md` | ~650 ln | **The biggest read.** Timeline editing, decompose, captions, transitions, motion, AI placement, the caption standard, the editor action verbs |
343
- | `references/assets-and-sourcing.md` | ~185 ln | Raws hunts, clip scanning, My Files, recurring characters, downloading media off a URL, social recycle |
402
+ | `references/assets-and-sourcing.md` | ~275 ln | **Google search for footage** (the query playbook), raws hunts, clip scanning, My Files, recurring characters, downloading media off a URL, social recycle |
403
+ | `references/agent-included-imagegen.md` | ~70 ln | **Free custom art without spending.** Image generation the AGENT's own subscription already includes (Antigravity / Gemini CLI, Codex / ChatGPT — Claude Code has none): why it is allowed in cost mode `minimize`, `vidfarm agent-image --check` / the brief command, where it sits on the asset ladder, and the honest limits |
404
+ | `references/browser-harness.md` | ~85 ln | **Free-plan sourcing, and cost mode `minimize`.** Driving the user's own Chrome with browser-harness as the $0 substitute for the paid video-search / image-search / news-search / download-video primitives: setup, the browse recipes, the raws collection loop, the interactive hand-off, and the licensing/etiquette limits |
344
405
  | `references/automation-and-local-dev.md` | ~520 ln | **Big.** The whole `vidfarm` command table, REST automation, scripting/bulk mode, `HARNESS.md`, local serve loop, skill packs |
345
- | `references/primitives.md` | ~475 ln | **Big.** One-shot primitive routes: TTS, STT, music, avatars, overlays, greenscreen, inpaint, background removal, product placement |
406
+ | `references/primitives.md` | ~530 ln | **Big.** One-shot primitive routes: video/image/news search, TTS, STT, music, avatars, overlays, greenscreen, inpaint, background removal, product placement |
346
407
  | `references/hooks-and-virality.md` | ~295 ln | **Before writing ANY hook, caption script, or re-theme**, and before a hook-variant batch. The four charges, three gates, banned openers, loop mechanics. This is the craft; the rest of the pack is mechanics |
347
408
  | `references/reviewing-renders.md` | ~140 ln | **Before you report a video as done**, or grade someone else's. The holistic pass, the common defects, frozen-render and audio verification |
348
409
  | `references/onboarding.md` | ~80 ln | Cold-start interviews, **consultations** (the `brainstorm/*` chain), strategy docs, durable director context |
349
- | `references/content-ideas.md` | ~90 ln | **"Give me content ideas" / "what should I post" / a month of posts.** The 50-frame angle bank, how to apply it to the director's topic, and frame → format notes |
410
+ | `references/content-ideas.md` | ~335 ln | **"Give me content ideas" / "what should I post" / a month of posts.** The three banks — 50 content frames, the 5-stage awareness ladder (with each stage's frames, angles and permitted ask), and 44 problem angles — plus **the subject pool** (adjacent topics inside the niche, so 50 frames are not 50 versions of one sentence), the monthly stage mix, the frame × angle × stage grid, and frame → format notes |
350
411
  | `references/rest-api.md` | ~85 ln | Only when the user asks for REST, an endpoint/schema, or direct HTTP integration. It is an index — follow its domain links; do not preload it into ordinary director conversations |
351
412
 
352
413
  **Recipes — step-by-step procedures. When a recipe matches the task, prefer it over the broad reference.**
@@ -372,6 +433,19 @@ You may be running as the **in-web AI chat** (the /editor copilot, the chat dock
372
433
  | `harnesses/product-demo.HARNESS.md` | ~110 ln | Real product doing a real thing; the highest slop-risk format in the catalog |
373
434
  | `harnesses/product-explainer.HARNESS.md` | ~245 ln | **"What is this thing?" for a brand nobody has heard of** — no usable screen footage. Orienting the cold viewer by 3s (Rule 0), the plain-English line by t=5s, harvesting the client site's own graphics before buying or generating (Rule 5b), the ≤3-text-run sticker-led open, VO + bed, and per-client differentiation for N-URLs-to-N-videos batches |
374
435
 
436
+ ## Experimental prompts — generalized methods, opt-in
437
+
438
+ Vidfarm keeps a small shelf of **experimental prompts**: complete, standalone methods still under live testing. They are **not** part of the router above and nothing in this pack depends on them — read one when a director asks for experimental prompts, or names one.
439
+
440
+ Why they exist: the prompts you find on the `/discover` pages are tuned to **one template's format**. These are deliberately **generalized** — the method, not the template — so they transfer to whatever you are building. The live index is `https://vidfarm.cc/experimental` (always current); today it holds:
441
+
442
+ | Prompt | What it does |
443
+ |---|---|
444
+ | `https://vidfarm.cc/experimental/unique-product-explainers.md` | N customer URLs → N product-introduction videos that do not look like each other. Differentiation as an input, frame-level review, measured verification |
445
+ | `https://vidfarm.cc/experimental/google-news-to-video.md` | A recent real event → a timely video. Two stages: `news-search` finds the STORY, `video-search` finds the VISUALS. Query formulas, Google operators, licence discipline |
446
+
447
+ Fetch one as plain markdown and follow it end to end; do not skim it into a summary.
448
+
375
449
  ## HyperFrames Skills — Load on Demand
376
450
 
377
451
  Vidfarm ships a curated HyperFrames skill suite alongside this director pack. Use it for composition authoring and motion craft without loading the entire suite into context.
@@ -391,14 +465,18 @@ HyperFrames authoring and rendering in this package are Vidfarm-native: local wo
391
465
  The File Index above says what each file *is*; this says which one a given ask means. Choose the narrowest path that satisfies the request.
392
466
 
393
467
  1. If the user needs help figuring out what to make, **or asks for a "consultation"** (the `brainstorm/*` chain: cold-start interview → awareness stages → angles → hooks), read `references/onboarding.md` first. **Unless they asked for a consultation by name, open with content ideas rather than the interview** — one line of offer into `vidfarm ideas --topic "<line>"` returns 20+ titled videos, offline and free, and the director's reactions to that list make the later interview far better than asking them cold (`references/content-ideas.md`). Then offer the interview as the way to turn ideas into a strategy: keyless directors run it locally for $0 with `vidfarm consult`, and `vidfarm consult coldstart --short` is the six-question short form. **Say the interview is skippable before you ask the first question**, and work with whatever they give.
394
- 1b. If the user asks **what to make** rather than how — "give me content ideas", "what should I post", "I'm out of ideas", "I need 30 videos for the month", "content ideas for my offer <url>" — read `references/content-ideas.md` and work the 50-frame angle bank against their offer. Return 20+ titled ideas, not three.
468
+ 1b. If the user asks **what to make** rather than how — "give me content ideas", "what should I post", "I'm out of ideas", "I need 30 videos for the month", "content ideas for my offer <url>" — read `references/content-ideas.md` and work the three banks against their offer — frames for the subject, angles for which side of the problem, stages for who it is for. Return 20+ titled ideas, spread across the awareness ladder, not three.
395
469
  2. If the user already knows the goal and needs a suitable template, read `references/core-workflows.md` and use the template discovery flow.
396
470
  3. If the task is “change this video,” read `references/editor-workflows.md`.
397
471
  4. If the task is “find footage” or “use our existing assets,” read `references/assets-and-sourcing.md`.
398
- 4b. If the task is **“download this video/audio off a website”** (a pasted YouTube / TikTok / Instagram / X post URL the user wants the actual file from), Vidfarm does that for you on a **paid plan** — `POST /api/v1/primitives/videos/download` (or `/audio/download`), devcli `vidfarm download-video <url>` / `vidfarm download-audio <url>`. **Free plan → do not call it; walk the user through opening the URL in Chrome and downloading it from the page, then `vidfarm put-file` the local file in for $0.** Details in `references/assets-and-sourcing.md` → `references/primitives.md`.
472
+ 4b. If the task is **“download this video/audio off a website”** (a pasted YouTube / TikTok / Instagram / X post URL the user wants the actual file from), Vidfarm does that for you on a **paid plan** — `POST /api/v1/primitives/videos/download` (or `/audio/download`), devcli `vidfarm download-video <url>` / `vidfarm download-audio <url>`. **Free plan → do not call it; get the file out of Chrome instead. Best: `vidfarm browser setup` + `vidfarm browse page "<url>"` so YOU drive their Chrome and save it (`references/browser-harness.md`); otherwise walk the user through opening the URL and downloading it from the page. Either way `vidfarm put-file` brings the local file in for $0.** Details in `references/assets-and-sourcing.md` → `references/primitives.md`.
399
473
  4c. If the task is **“turn this Reddit/X thread, subreddit, or account into a video”** — “tweet to TikTok”, “Reddit to TikTok”, “make a video from this thread”, “what are the top comments saying” — run `vidfarm recycle <source>` (or `POST /api/v1/primitives/social/recycle`) with the URL. It **decomposes** the source into raw JSON (text, comment tree, media URLs, author pics, stats) and hands it back unranked so YOU pick what to remix. **Paid plan; `max_records` is the spend ceiling.** Brokers the reddit-lead-gen / x-lead-gen OfficeX apps, so it waits out their async job for you. Details in `references/assets-and-sourcing.md` → `references/primitives.md`.
400
474
  4d. If the task is **“post this again / to several accounts / on another platform”**, or you are about to publish or bulk-produce at all — that is **deduplication**. Run `vidfarm dedupe <mp4> [--variants N]` on the **exported file** (free, local ffmpeg, no re-render), then approve/schedule each variant. **Ask the operator whether they want deduplicated copies, and how many, BEFORE the render/bulk run** — deciding after means paying for a second render. Details in `references/core-workflows.md` → *Deduplicate before you publish* and `references/primitives.md` → *Primitive: media_dedupe*.
401
475
  4e. If the ask contains the word **“harness”** — *“create me a harness”*, *“update the harness for this format”*, *“give me the harness for this template_id”* — that is a known, named process, not a vague request. Read `harnesses/README.md` (the three phrasings and the format), then `recipes/bulk-scripting-with-a-harness.md` if the job is a batch. The third phrasing means the **decomposition**: `vidfarm harness derive <forkId>`.
476
+ 4f. If the task is **“find me footage / a clip of X”** and the free catalog and public raws shelves do not have it, **search Google before you generate anything**: `vidfarm video-search "<shot>"` returns real source URLs (TikTok, YouTube, Pexels, archive.org) which go straight into `vidfarm raws scan <url>` (mine clips) or `vidfarm download-video <url>` (collect the file). `vidfarm image-search` does the same for stills. **Paid plans only, flat $0.0003 per call** — cheaper than one AI image attempt by two orders of magnitude, so it is almost always worth one wide search first. **On a free plan or in `minimize`, browse the same searches yourself for $0** — `vidfarm browse videos|images "<shot>"` (see 4h). Query craft matters more than anything else here: `references/assets-and-sourcing.md` → *Google search for footage*. **A public video is not a licensed video** — check rights before reuse.
477
+ 4g. If the ask is **timely** — “make a video about what just happened”, newsjacking, “what's trending in <niche> this week” — run `vidfarm news-search "<topic>" --fresh w` for the STORY, then `vidfarm video-search` for the VISUALS. Two stages, never one query. Free plan / `minimize`: the same two stages as `vidfarm browse news "<topic>"` then `vidfarm browse videos "<the thing>"`, for $0 (see 4h). Full method: `https://vidfarm.cc/experimental/google-news-to-video.md`.
478
+ 4h. If any of 4b / 4f / 4g would cost money the user doesn't want to spend — a **free plan**, a `402`, or cost mode **`minimize`** — the answer is **browser control, not an apology**. `vidfarm browser setup` installs browser-harness (drives the user's own Chrome, ~1 minute, $0, no account), then `vidfarm browse videos|images|news|page "<query|url>"` substitutes for `video-search` / `image-search` / `news-search` / `download-video`. Ask before installing — it is their personal browser. Read `references/browser-harness.md`.
479
+ 4i. If the ask is a **whole video or a batch** rather than one lookup, run it in phases — **plan the shot list, collect the raws for every beat, then build** (SKILL.md → *Production has PHASES*). How hard you work the collection phase is set by the cost mode: in `minimize` it is most of the job and it is where quality comes from; in `hybrid` you collect free first and pay only for the gaps; in `rich-ai` / `pure-videogen` it becomes a generation phase that still starts with searching what already exists.
402
480
  5. If the task is scripted, local, CI-driven, or `vidfarm serve`-based, read `references/automation-and-local-dev.md`.
403
481
  5b. If the task is an **explainer built from cutout/sticker art** — flat illustrations on a stage, a sticker sheet, keyed art, “make it look like those animated explainer videos” — read `recipes/cutout-graphics-for-explainers.md`. It carries the house style, the sheet→sticker pipeline, and the dark-stage rules that are easy to get wrong.
404
482
  5c. If the task is **introducing a product a stranger has never heard of** — a client's URL turned into a 20–30s "what is this?" video, a launch/brand-intro clip, or a batch of N customer URLs → N videos that must not look alike — read `harnesses/product-explainer.HARNESS.md`. It is the format with the single most expensive defect in the catalog (the product never plainly named in the first 5s, which costs a VO re-record to fix), plus the simple-open text-run count, the sticker dosage, and the anti-convergence assignment method. Use `product-demo` instead when you actually have the UI on screen.
@@ -591,6 +669,7 @@ POST /api/v1/approved/posts
591
669
  Content-Type: application/json
592
670
 
593
671
  { "caption": "required", "title": "optional", "pinned_comment": "optional", "tracer": "optional",
672
+ "thumbnail_url": "optional https://.../poster.jpg",
594
673
  "media": [ { "url": "https://.../output.mp4", "kind": "video", "role": "primary" } ] }
595
674
  ```
596
675
 
@@ -598,8 +677,17 @@ Content-Type: application/json
598
677
 
599
678
  - `GET /api/v1/approved/posts` — list your approved posts
600
679
  - `GET /api/v1/approved/posts/:postId` — read one (returns `share_url`, `download_zip_url`)
680
+ - `PATCH /api/v1/approved/posts/:postId` — `{ folder_path?, thumbnail_url? }`; move the post between `/approved` folders and/or replace its social thumbnail
681
+
682
+ ### The social card of a share link
601
683
 
602
- devcli: `vidfarm approve --video <mp4-url> --caption "..."` prints the `share_url` as a first-class openable link; `vidfarm posts` lists, `vidfarm post <id>` reads one.
684
+ `share_url` gets pasted into X, Discord, Slack and iMessage, so its preview card matters. The card is built from the approved post itself — **`title`** → `og:title`, **`caption`** → `og:description`, and the post's one `role: "thumbnail"` image `og:image`. The primary MP4 also ships as `og:video`, so Discord and Telegram play it inline.
685
+
686
+ You never have to build that thumbnail: if a post has no image asset, vidfarm extracts a frame (~1s in) from the primary video, files it in the **file directory** under `/files/approved/…` (durable + public), and attaches it as the thumbnail. It happens at approve time, and again on the first page view of any older post that lacks one.
687
+
688
+ **Choose the frame yourself when the auto-frame is weak** (a black fade-in, a mid-blink face). Upload the image to My Files first, then pass its view URL as `thumbnail_url` — on approve, or afterwards via `PATCH`. An explicit thumbnail is never overwritten. Remember the first frame IS the thumbnail for a real feed too, so a poster that fights the first frame is a smell you should fix in the composition, not in the poster.
689
+
690
+ devcli: `vidfarm approve --video <mp4-url> --caption "..."` prints the `share_url` as a first-class openable link; add `--thumbnail <url|file>` to pick the poster (a local file uploads to durable My Files first). `vidfarm posts` lists, `vidfarm post <id>` reads one.
603
691
 
604
692
  ## Schedule a post
605
693
 
@@ -1321,6 +1409,7 @@ Compositions are authored in HTML, so the single most common way an AI-edited vi
1321
1409
  - **CTA / "button" shapes.** Any filled capsule or rounded rect containing action copy — "Sign Up for a Free Trial →", "Learn More", "Get Started", "Book a Call" — especially gradient-filled with a glow or drop shadow. A social CTA is *spoken*, or a plain caption line, or an arrow pointing at the real UI. Not a button.
1322
1410
  - **Badges, chips, pills — including a SINGLE one.** The "✓ ID-Verified Tutors · ✓ No Credit Card Needed · ✓ 30-Min Trial" strip is the obvious case, but the far more common one is **one lonely capsule holding a stat or a label**: `( 10 hrs / week )`, `( STEP 2 )`, `( EP.01 )`, `( BEGINNER )`, `( +40% )`. Being alone does not make it native — a rounded, padded, filled tag around static text is a `<span class="badge">` wearing a different hat, and it is one of the loudest web tells in the whole frame. **The only legitimate pill in a video is the active-word highlight** (`spotlight`/`karaoke`), because it tracks the spoken word and moves. Static text gets `outline`, `plain`, or a tight band that hugs the glyphs (radius ≤ ~8px). If a stat deserves emphasis, give it emphasis the *editor* can give: bigger, heavier, ALL-CAPS, an accent color, a hand-drawn circle or underline around it, its own beat on screen.
1323
1411
  - **Cards, panels, containers.** A rounded-rect box (dark, bordered, shadowed, or `backdrop-filter` frosted) holding a heading plus a subheading/URL. Text belongs **on the footage**, not inside a floating panel with padding around it.
1412
+ - **Layout templates — a whole frame arranged like a page.** A modal/dialog floating over a dimmed or blurred backdrop; a headline + subheadline + CTA stacked in a centred well; a blurred website screenshot used as the background plate. This is the frame-level version of the rule and it survives the deletion of every individual style above — see "The layout-template rule" below.
1324
1413
  - **Gradient text fills, neon border glows, elevation shadows, glassmorphism, hover-implying strokes.**
1325
1414
  - **Web page furniture of any kind:** navbars, hero sections, feature grids, two-column layouts, `<ul>` bullet lists with disc markers, tables, alerts, progress bars as decoration, logo-in-a-circle avatars, "as seen in" strips.
1326
1415
  - **Corporate web type:** Inter, Roboto, system-ui, Arial, Helvetica, Georgia, Times — at web weights (400–600) and web sizes (16–24px). Instantly reads as "a screenshot of a website."
@@ -1329,6 +1418,27 @@ Compositions are authored in HTML, so the single most common way an AI-edited vi
1329
1418
 
1330
1419
  **The capsule rule of thumb.** On any element that holds words: `border-radius` over ~8px **combined with** a background fill and padding = a badge. Either take the fill away (bare text + outline/shadow) or take the radius and padding down until the band hugs the glyphs. There is no third option for static text.
1331
1420
 
1421
+ #### The layout-template rule — the FRAME is not a page
1422
+
1423
+ Every rule above judges one element. This one judges the **whole frame**, and it catches the case where each individual element looks defensible but the composition is still a web page. The archetype: a **modal** — the background dimmed and blurred out of focus, and floating on top of it a rounded bordered box holding a big headline, a smaller support line, and a fat red button. Nobody authored "slop" there; they authored a *layout template*, and a layout template is the strongest web tell there is, because a viewer recognizes the SHAPE before they read a single word.
1424
+
1425
+ **The stack is the tell, not the box.** Delete the border, delete the fill, delete the button capsule, and *keep the arrangement* — headline, then a smaller line under it, then a call to action, centred in a well with symmetric margins — and it still reads as a landing page. A phone-shot video never arranges words into a document: it puts **one thought on screen at a time**, wherever the picture leaves room, and the next thought arrives on the next beat.
1426
+
1427
+ **Banned frame-level shapes:**
1428
+
1429
+ - **The modal / dialog.** A content block staged *on top of* a backdrop that has been dimmed, blurred, greyed, or scaled back to make it recede. Nothing in a video pops "above" the video.
1430
+ - **The hero triplet.** Headline → subheadline → CTA, stacked and centred. Also its cousins: title + kicker + logo lockup, question + answer + URL.
1431
+ - **The full-frame scrim used as staging.** A dark wash over the whole frame so a floating block reads on top. (A local legibility band on *one caption* is legal; a page-wide wash to stage a panel is not. Nor is a blurred-and-dimmed backdrop — a blurred fill behind a 16:9 clip in a 9:16 frame is fine on its own, but blur *plus* dimming is modal staging.)
1432
+ - **Page sections.** Nav strip, hero, three-up feature row, testimonial block, footer with fine print — in any order, in any frame.
1433
+ - **The blurred website screenshot as a background plate.** If the backdrop is a web page at all, the frame is a screen recording of a web page. Either show the real product UI full-bleed and in focus (that is legitimate footage), or don't show it.
1434
+ - **Document margins.** A centred content column with even gutters left and right and air above and below. Social frames are full-bleed; the text lands where the picture is empty, not inside a measured well.
1435
+
1436
+ **The fix is always the same: unstack it into time.** Take the three lines the layout was going to show at once and give each one its own beat over live footage — the headline is the hook at t=0, the support line lands on the next cut, the CTA is *spoken* (or a bare caption on the final frame). You lose nothing, because a viewer reads one line at a time anyway; you gain the pacing that makes it look shot rather than designed.
1437
+
1438
+ **The self-check before you place a text group:** *am I arranging words relative to each other, or relative to the picture?* Relative to each other = layout = web. Relative to the picture = a caption = native. Two on-screen text runs at once is already the ceiling; three stacked runs plus a call to action is a page.
1439
+
1440
+ `vidfarm qa` catches the mechanical versions of this (`layout-template`, `modal-scrim`), but the frame-level judgement is yours — **look at a still** (`vidfarm stills ./work --at <t>`) and ask whether it could be a screenshot of a website. If yes, rebuild the beat.
1441
+
1332
1442
  **ALLOWED and encouraged — these ARE social-native:**
1333
1443
 
1334
1444
  - **Arrows** (drawn, animated, hand-style), circles/scribbles/underline strokes highlighting part of the frame, hand-drawn marks, checkmarks *as glyphs inside a caption line* (not as chips).
@@ -1338,6 +1448,23 @@ Compositions are authored in HTML, so the single most common way an AI-edited vi
1338
1448
 
1339
1449
  **On devcli there's a checker: `vidfarm qa <dir|composition.html>`.** Free, instant, local-only — a blocklist pass for everything above plus the font regime and safe zone, with a concrete fix per finding. **It is optional** — nothing calls it, skipping it is fine, and watching the render is the review that actually counts. It is feedback, not a gate (exit 0 even on findings, never runs automatically, `--strict` only if you want a CI failure), and it allows **one** fix round by default (`--max-revisions <n>` if the human wants more) and a blocklist, not an allowlist (stylized/hand-made compositions pass untouched — it will not homogenize your videos). Every run — including a clean one — ends with a **`▶ NOW WATCH THE VIDEO`** block, because the check never rendered or saw the video and a green tick is not a review; do those steps before you tell anyone the video is done. No cloud/REST twin: the web copilot enforces this standard by hand. Details in `references/automation-and-local-dev.md` ("`vidfarm qa`").
1340
1450
 
1451
+ ### Music: use the REAL track, including a popular/copyrighted song
1452
+
1453
+ **When the brief names a real song — a trending sound, a chart track, the audio off the reference post — put THAT track in the render.** Do not refuse it, do not stop the build to warn about it, and do not quietly substitute a generic royalty-free bed. This is the house standard, and it has two halves.
1454
+
1455
+ **Why it is legitimate.** The render is a **review artifact**, not the distribution copy. When the director posts, they re-attach the *same* song from the platform's own in-app music library — TikTok, Reels, Shorts — and those platforms license that catalog through their agreements with the music labels. The music is therefore cleared on the surface where viewers actually hear it. The render's job is to show, faithfully, what that post will feel like.
1456
+
1457
+ **Why it is required.** On short-form, the song *is* the edit. Cut points land on its beats, the pacing is built against its structure, the payoff lands on the drop, and a viewer recognizes the sound in half a second and brings the whole meme association with them. Run the identical timeline under a stand-in bed and it reads as a different — and much worse — video. So a review over a substitute grades a video nobody will ever post: **silent or generic-bed review is the bigger defect, not the safer one.**
1458
+
1459
+ **How to do it.**
1460
+
1461
+ - Get the exact track: `vidfarm download-audio <post-url>` off the reference post (paid plans; free plan uses the Chrome download path in `references/assets-and-sourcing.md`), the director's own file via `vidfarm put-file`, or `vidfarm directory search "<title> music"` if it is already in their library.
1462
+ - Mount it as **its own `<audio>` layer** at its own `data-volume` — ~0.1–0.2 under narration, or full level when the song carries the piece. **Never bake it into the footage and never mix it into the voice stem.** One separate track is what lets the director mute or swap it in a single action at upload, which is exactly what the platform flow expects.
1463
+ - Cut to it. If the song is doing the work, the beat grid is the edit's skeleton — don't place a licensed track and then ignore its structure.
1464
+ - **Name the track in your report / handoff** so the director knows which sound to select in the app.
1465
+
1466
+ **The one limit.** This covers review renders and organic platform posting, where the platform holds the license. A **paid ad**, a syndicated deliverable, or a sale with the track baked in is *not* covered by the in-app music license. Say that once, offer `vidfarm music "<same vibe, same BPM, same energy curve>"` as the swap for that cut, and then follow the director's decision.
1467
+
1341
1468
  ### TikTok-native caption standard (position + font + background) — always adhere
1342
1469
 
1343
1470
  > Captions are also the *delivery system* for three of the four charges: the hook is read before any audio, the loop has to stay on screen, and the payoff number needs its own card. What the words should SAY is in `references/hooks-and-virality.md`; this section is how they must LOOK.
@@ -1907,6 +2034,90 @@ When you hand back a render, say what you **measured** and what you **judged**,
1907
2034
 
1908
2035
  **Never report a clean pass on the half you didn't actually look at.** A confident "verified, looks good" over an unreviewed video is worse than no review, because it spends the director's trust on nothing — and per the base rate at the top of this file, it is usually wrong.
1909
2036
 
2037
+ ## Google search for footage — find THE shot, then clip it (paid plans)
2038
+
2039
+ Before you download anything, you have to **find** it. `vidfarm video-search` runs a Google video search and hands back real URLs — TikTok, YouTube, Pexels/Pixabay/Mixkit, news sites, archive.org — which then feed the two collectors you already have:
2040
+
2041
+ ```bash
2042
+ vidfarm video-search "warehouse worker packing orders POV 4K" --limit 40
2043
+ vidfarm raws scan "<a result url>" --clips 8 # mine short raws out of it
2044
+ vidfarm download-video "<a result url>" # or collect the single file
2045
+ vidfarm image-search "manila street market wide shot" --limit 40
2046
+ vidfarm news-search "AI startup funding announced" --fresh w
2047
+ ```
2048
+
2049
+ REST twins: `GET /api/v1/primitives/video-search`, `/image-search`, `/news-search` (`?q=…&max_results=…`). Field-level reference in `references/primitives.md`.
2050
+
2051
+ **Paid plans only · flat $0.0003 per call**, whatever the result count — so ask for one **wide** page rather than paging twice.
2052
+
2053
+ **On a free plan, or in cost mode `minimize`, run the same searches yourself for $0.** `vidfarm browser setup` installs browser-harness (about a minute, no account, no key), and then `vidfarm browse videos|images|news "<query>"` drives the user's own Chrome through the same Google surfaces. You read the SERP instead of receiving ranked JSON, but the query craft below is identical and the results are the same web. Set it up rather than telling a free user the search needs a paid plan — full page, including the download substitute for `download-video`, in `references/browser-harness.md`. The free catalog (`vidfarm media search`, `vidfarm iconscout --free`) and the public raws shelves are still the cheaper first stop.
2054
+
2055
+ **Collect for the whole video, not one beat at a time.** Whichever route you use, sourcing is a *phase*: plan the shot list, run one pass that fills every beat, then build. See SKILL.md → *Production has PHASES*.
2056
+
2057
+ **A public video is not a licensed video.** These searches return links with no licence attached. For client work prefer, in order: public domain → CC0 → CC BY (with credit) → stock with an explicit commercial licence → written permission from the creator. Save the source URL **and** the licence page every time.
2058
+
2059
+ ### 1. Search the SHOT, not the topic
2060
+
2061
+ ```
2062
+ [subject] + [action] + [shot/style] + [quality/orientation]
2063
+ ```
2064
+
2065
+ ```
2066
+ office worker typing laptop close up 4K
2067
+ entrepreneur frustrated at desk vertical video
2068
+ Manila street traffic night handheld
2069
+ package delivery POV raw footage
2070
+ woman scrolling phone over shoulder 9:16
2071
+ factory production line wide shot 4K
2072
+ ```
2073
+
2074
+ Shot vocabulary that actually changes the results: `close up`, `wide shot`, `overhead`, `drone`, `POV`, `handheld`, `security camera`, `slow motion`, `timelapse`, `vertical`, `9:16`, `portrait`, `raw footage`, `unedited`, `no music`, `walking tour`, `dashcam`, `ambient footage`, `product demo`, `screen recording`.
2075
+
2076
+ For footage that reads as **real UGC**, add: `phone footage`, `amateur footage`, `day in the life`, `vlog`, `behind the scenes`, `POV`.
2077
+
2078
+ ### 2. Aim at the stock libraries through Google
2079
+
2080
+ Google often searches a stock library better than the library's own search bar:
2081
+
2082
+ ```
2083
+ site:pexels.com/videos warehouse worker
2084
+ site:pixabay.com/videos Manila traffic
2085
+ site:mixkit.co/free-stock-video entrepreneur
2086
+ site:commons.wikimedia.org factory machinery video
2087
+ site:archive.org public domain newsreel
2088
+ ```
2089
+
2090
+ Pexels footage can generally be modified and used commercially with no attribution, subject to restrictions such as misleading endorsements. Pixabay also permits broad reuse but restricts recognizable brands and standalone redistribution. Read the licence page, and keep it.
2091
+
2092
+ ### 3. Reusable YouTube footage
2093
+
2094
+ ```
2095
+ site:youtube.com "Creative Commons" warehouse footage
2096
+ site:youtube.com "CC BY" coffee production 4K
2097
+ site:youtube.com "public domain" historical footage
2098
+ site:youtube.com "royalty free footage" city traffic
2099
+ ```
2100
+
2101
+ Or search YouTube directly and apply its Creative Commons filter. **Verify the description and the original source** — uploaders mislabel footage they don't own, and the label does not transfer rights.
2102
+
2103
+ ### 4. TikTok through Google
2104
+
2105
+ ```
2106
+ site:tiktok.com/@*/video/ "warehouse"
2107
+ site:tiktok.com "day in the life" accountant
2108
+ site:tiktok.com "packing orders" small business
2109
+ site:tiktok.com "Manila commute" POV
2110
+ site:tiktok.com "remote work setup" freelancer
2111
+ ```
2112
+
2113
+ Useful additions: `before after`, `storytime`, `POV`, `tutorial`, `reaction`, `behind the scenes`, `day in the life`. Exclude the noise: `site:tiktok.com "packing orders" -dance -meme -compilation`.
2114
+
2115
+ Google does not index every TikTok — TikTok's in-app search is better for **discovery**, Google is better when you want one exact phrase or creator. TikTok supports embedding an original post with attribution; downloading and republishing needs permission.
2116
+
2117
+ ### 5. News first, visuals second
2118
+
2119
+ `news-search` finds the **story**; `video-search` finds the **visuals**. Run them as two stages — searching for both at once finds neither. The full timely-content method (query formulas, operators, the two-stage agent prompt, accuracy rules) is the standalone prompt at `https://vidfarm.cc/experimental/google-news-to-video.md`.
2120
+
1910
2121
  ## Download a video from a website (Vidfarm fetches it for you — paid plans)
1911
2122
 
1912
2123
  **Yes, Vidfarm can download videos off the web for the user.** When someone pastes a YouTube / TikTok / Instagram / X (Twitter) / other supported post URL and wants the actual file — "grab this video", "save this clip", "get me that audio" — you do **not** need yt-dlp, a browser extension, or an apology. One primitive does it and returns a durable Vidfarm-hosted asset:
@@ -1920,7 +2131,9 @@ Both are async primitive jobs — poll `GET /api/v1/primitives/jobs/:jobId` unti
1920
2131
 
1921
2132
  **PAID PLANS ONLY.** These ride a paid third-party resolver billed to the wallet, so a free-plan customer gets `402 insufficient_funds`. Check the plan / cost mode before promising it.
1922
2133
 
1923
- **Free-plan users — the fallback is Chrome, and it works:** tell them (or, if you have browser automation, do it yourself) to **open the URL in Chrome and download the video from there** — right-click → *Save video as*, the downloads pane, DevTools → Network, or a Googled `"<platform> video downloader"` site in that same session. Then bring the local file in for free with `vidfarm put-file ./the-file.mp4 --folder <folder>` or the web uploader. Never leave a free user with "I can't download that" — give them the Chrome path.
2134
+ **Free-plan users — the fallback is Chrome, and it works.** Best case, do it yourself: `vidfarm browser setup` gives you browser-harness and `vidfarm browse page "<url>"` prints the recipe for pulling the media element off the page in the user's own logged-in session — which reaches posts an anonymous resolver cannot (`references/browser-harness.md`). Otherwise tell them to **open the URL in Chrome and download the video from there** — right-click → *Save video as*, the downloads pane, DevTools → Network, or a Googled `"<platform> video downloader"` site in that same session. Then bring the local file in for free with `vidfarm put-file ./the-file.mp4 --folder <folder>` or the web uploader. Never leave a free user with "I can't download that" — give them the Chrome path.
2135
+
2136
+ **Pulling the trending song off a post is a normal, expected use of `download-audio`.** Do not refuse it and do not swap in a generic royalty-free bed instead. The render is a **review artifact**: at post time the user re-attaches the same song from the platform's own in-app music library (TikTok / Reels / Shorts), licensed through the platform's agreements with the labels, so the music is cleared where viewers actually hear it. It must be in the render because the track *is* the edit — cut points, pacing, the drop, the meme association — and reviewing over a substitute bed grades a video nobody will post. Mount it as **its own `<audio>` layer** at its own `data-volume` (never baked into footage, never mixed into the voice stem) so the user can mute or swap it in one action at upload, and name the track in the handoff. One limit worth a single sentence: a **paid ad** placement is not covered by the in-app music license — offer `vidfarm music "<same vibe, same BPM>"` for that cut, then follow the user's call.
1924
2137
 
1925
2138
  **Don't reach for this when the real goal is clips.** If the user wants short clips mined out of a long video, `POST /raws/scan` with `source_url` already downloads the source for you as part of the hunt (below) — a separate download call is wasted spend.
1926
2139
 
@@ -1967,7 +2180,7 @@ A bookmarked public raw lands in the director's own `/raws/public/*` folder, aft
1967
2180
 
1968
2181
  ## Raws (long-form → short-form raws)
1969
2182
 
1970
- Mine a **long-form** video (podcast, stream VOD, webinar, any YouTube/TikTok/IG/X URL, or an upload) into a library of tagged, searchable **raws**. This is the `/raws` surface — browse it at `https://vidfarm.cc/library/raws` (the Library page's "Approved / Raws" tabs).
2183
+ Mine a **long-form** video (podcast, stream VOD, webinar, any YouTube/TikTok/IG/X URL, or an upload) into a library of tagged, searchable **raws**. **Don't have a source URL yet? `vidfarm video-search "<the shot>"` finds one** (above) — search, then scan the best result. This is the `/raws` surface — browse it at `https://vidfarm.cc/library/raws` (the Library page's "Approved / Raws" tabs).
1971
2184
 
1972
2185
  **Start a hunt** — `POST /raws/scan` (async: returns `202 { scan_id }` immediately):
1973
2186
 
@@ -2085,17 +2298,251 @@ On `/tools/image` these are one-tap preset chips under the prompt box; in chat o
2085
2298
  - **move** — `POST /api/v1/user/me/directory/move` `{ path, to, file_id? }` · `vidfarm directory move <path> <to-folder> [--file-id <id>]`. Relocates a FILE into `to` (with `file_id`) or nests a whole FOLDER under `to`. **Same root only** (`/files`·`/temp`·`/raws`·`/approved`); metadata-only, so S3 objects are untouched.
2086
2299
  - **copy** — `POST /api/v1/user/me/directory/copy` `{ path, to?, file_id?, new_name? }` · `vidfarm directory copy <path> [<to-folder>] [--file-id <id>] [--as <name>]`. Duplicates a file/folder sharing the same underlying S3 object (cheap, no re-upload). Same root only, `/files`·`/temp`·`/raws` (not `/approved` — a ready post is a single publishable unit; not `/projects` — read-only). Omit `to` to duplicate in place.
2087
2300
 
2301
+ **Sharing a folder publicly (crowdsourcing + agent-readable libraries).** Any folder in **any** root can carry share tokens — one folder, as many links as you want, each with its own mode:
2302
+
2303
+ - `read` — browse **and vector-search** the folder. Nothing else.
2304
+ - `upload` — read + upload files + create subfolders. **No rename, no delete.** This is the crowdsourcing link.
2305
+ - `edit` — upload + rename + delete inside the shared subtree.
2306
+
2307
+ Minting or editing a link is **paid** (unlike the rest of the directory routes, which are free on any plan); **visiting** one needs no account at all, so a link keeps working for its holders regardless of their tier. devcli twins: `vidfarm directory share <path> --mode read|upload|edit [--label <text>]` (prints the URL), `vidfarm directory shares [path]`, `vidfarm directory share-update <token> [--mode] [--label] [--disable|--enable]`, `vidfarm directory unshare <token>`.
2308
+
2309
+ A token is scoped to **exactly one subfolder and everything under it** — never a sibling, never a parent, so a leaked link cannot walk the rest of the drive. The shared base folder itself can never be renamed or deleted through its own token. Owner routes: `GET|POST /api/v1/user/me/directory/shares`, `PATCH|DELETE …/shares/<token>` (`{ path, mode, label }`; `disabled: true` cuts a link off instantly and is reversible). Public routes, no auth: `GET /api/v1/share/:token/directory` (`?path=`), `POST /api/v1/share/:token/directory/search` `{ query, path?, mode? }`, plus `…/directory/folders`, `…/directory/rename`, `…/directory/delete`, `…/attachments/upload`. The human page is `/directory/preview/<token>/<path…>`.
2310
+
2311
+ **Uploading over ~6 MB through a share link:** `…/attachments/upload` is a multipart POST through the API Lambda, whose request body caps at about 6 MB — a bigger file answers **413** before the handler runs. Use the two-step presigned path instead (the share page's own uploader does): `POST /api/v1/share/:token/attachments/presign` `{ file_name, content_type?, size_bytes?, folder_path? }` → `{ transport: "presigned", file_id, storage_key, folder_path, upload: { method, url, headers } }`; PUT the raw bytes to `upload.url` with those headers; then `POST /api/v1/share/:token/attachments/finalize` `{ file_id, file_name, content_type, size_bytes, storage_key, folder_path }` to record the file. A server with no presigned transport answers `transport: "server"` and you post the multipart form. Ceiling is the owner's own: 200 MB.
2312
+
2313
+ In the UI: the file explorer's folder kebab → **Share…**, the `⤴ Share` toolbar button, and the folder kebabs on `/library` (**Raws** and **Approved** tabs). `⤴ Manage Shares` lists every token you own.
2314
+
2315
+ **Working a link you were GIVEN — `vidfarm shared` (no account, no API key).** This is the visitor side, and it is how a gigworker's agent collaborates on a client's drive. `<link>` is the URL from the task brief (or a bare `dsh_…` token plus `--host`):
2316
+
2317
+ ```bash
2318
+ vidfarm shared info "$LINK" # folder, mode, what you may do
2319
+ vidfarm shared ls "$LINK" [subfolder] # browse
2320
+ vidfarm shared search "$LINK" "founder talking head, no captions"
2321
+ vidfarm shared get "$LINK" hero.mp4 --out ./work # one file (--all for the folder)
2322
+ vidfarm shared mkdir "$LINK" task-014-yvette # your own subfolder (upload/edit)
2323
+ vidfarm shared put "$LINK" final.mp4 --subfolder task-014-yvette
2324
+ ```
2325
+
2326
+ `shared put` runs presign → PUT → finalize, so it is not bound by the ~6 MB multipart ceiling; it falls back to multipart automatically when the server has no presigned transport.
2327
+
2328
+ **The crowdsourcing pattern (DollarPlatoon custom-request vending machine).** Two links per campaign, minted once and reused across every task:
2329
+
2330
+ ```bash
2331
+ vidfarm directory share /files/crowdsourced/acme --mode upload --label "Acme drop box"
2332
+ vidfarm directory share /raws/acme-brand --mode read --label "Acme footage (read only)"
2333
+ ```
2334
+
2335
+ Put both in the task payload as plain fields — `assets_link` (read), `upload_link` (upload), `upload_subfolder` — and state the proof requirement: *"create your subfolder in the upload link, put the MP4 + project files there, and submit the public MP4 url as the proof"*. Organize the drop box one of two ways, and say which in the task: **worker-named subfolder** (one link for the whole campaign, each worker runs `shared mkdir`) or **task-owned subfolder** (pre-create `/…/acme/task-014` and mint the link onto *that* folder, so a worker on one task cannot see another's). Collect with the ordinary owner commands (`directory ls`, `directory search --path …`) and close the batch with `directory share-update <token> --disable`. Editors who only need footage get a `read` link on `/raws` — vector search included, nothing writable.
2336
+
2337
+ **Driving the machines from the terminal — `vidfarm gigs`.** The whole loop is scriptable, from both sides, and the two halves of a task (the brief and the files) are posted together:
2338
+
2339
+ ```bash
2340
+ # CLIENT (paid plan — the DollarPlatoon key comes from your vidfarm account)
2341
+ vidfarm gigs machines # your two standing machines + gig ids + invite links
2342
+ vidfarm gigs add-task --task "60s explainer for acme.com" --price 0.50 --tags shortform \
2343
+ --assets-link "$READ_LINK" --upload-link "$DROP_LINK" --subfolder task-014 \
2344
+ --proof "MP4 in your subfolder" --proof "public MP4 url in the proof body"
2345
+ vidfarm gigs ring-bell --title "Acme wants 7 shorts this week" --machine custom_requests
2346
+ vidfarm gigs tasks # what is still unclaimed in the FIFO queue
2347
+ vidfarm gigs proofs --status pending # what came back, with the playable link
2348
+ vidfarm gigs approve PRF_01H… --feedback "Great hook, keeping it."
2349
+ vidfarm gigs reject PRF_01H… --tag not_selected # a pass — costs the worker NO reputation
2350
+
2351
+ # GIGWORKER (free, no vidfarm account: export DOLLARPLATOON_API_KEY=…)
2352
+ vidfarm gigs join-feed && vidfarm gigs feed # who is asking for videos right now
2353
+ vidfarm gigs join <invite-url> # or --registry to list every joinable machine
2354
+ vidfarm gigs work # work waiting across every machine you joined
2355
+ vidfarm gigs claim <gig-id> # claim off the FIFO queue — note the task id
2356
+ vidfarm gigs submit <gig-id> --task <task-id> --proof https://…/final.mp4
2357
+ ```
2358
+
2359
+ Key resolution is `--dp-key` → `DOLLARPLATOON_API_KEY` → `GIGDESK_API_KEY` → the paid account's own key via `GET /api/v1/user/me/marketplace`. **Review promptly: silence is approval** — an unreviewed proof auto-approves after the gig's review timeout (default 48h) and you pay for it.
2360
+
2361
+ A link is a **bearer credential**: whoever holds it has that mode. Prefer `upload` over `edit` for crowdsourcing (nobody can delete a colleague's work), keep one link per campaign rather than one per worker, and disable it the day the batch closes. **Free tier fallback:** minting is paid, so a free user puts a Google Drive / Dropbox / WeTransfer folder URL into the same `assets_link` / `upload_link` fields — worker agents treat them as plain URLs. What is lost: vector search, the scoped subtree, and the one-command `vidfarm shared put`.
2362
+
2363
+ Two things to know. **Search is included in `read`** — that is what makes a shared folder useful to a gigworker's AI agent: it finds footage by meaning instead of paging through folders. The query embedding is billed to the **folder's owner**, not the visitor. And **only `/files` and `/temp` accept direct uploads** — `/raws`, `/approved` and `/projects` have no plain-upload backend even for the owner (raws are scanned/imported, approved posts are published renders, projects are fork storage), so an `upload` link there only creates folders. To crowdsource footage, share a `/files` folder for `upload` and import the contributions into `/raws` yourself.
2364
+
2088
2365
  The web copilot exposes the same three as `browse_files action=rename|move|copy`. If you rename or move a character's folder, update the `id`, `sprite_card_path`, and `about_path` inside its manifest to match (and rename the `<character_id>.json` file itself).
2089
2366
 
2090
2367
  **Assume My Files is multi-offer.** A user often runs more than one product, offer, brand, or region, and namescopes assets into folders accordingly — by product (`acme-skincare/`, `zensleep/`), by offer/campaign (`summer-sale/`), by region (`us/`, `eu/`), by asset type (`logos/`, `ugc-clips/`), or any arbitrary scheme. There is **no fixed layout** — read the `folders` tree first and reason about how this user organized things. Before pulling assets for a task, infer which folder(s) match the product/offer/region the current composition is about (match folder names to the composition title, video context, and what the user said), then scope reads to that folder so you never mix one brand's logo/product-shot/music into another brand's video. If the target offer is ambiguous, ask which product/offer/region (or which folder) this work is for rather than guessing across offers.
2091
2368
 
2092
2369
  In the editor web copilot the same filesystem is exposed via the **`browse_files` tool** (`action=list` / `action=search` / `action=read` / `action=write` / `action=annotate` / `action=move` / `action=copy` / `action=rename`), so the copilot follows the identical reasoning: search or list to find the right offer's folder, then read an asset — or `write` a text doc (OFFER.md, awareness-levels.md, …) or import a media URL (`source_url`) into that folder, annotating anything worth finding again. `action=rename`/`move`/`copy` reorganize the tree (see the three routes above) — use them to keep character folders and asset names tidy. `browse_files list` defaults to `path='/'` when `path` is omitted, so the `/raws` (hunted raws) and `/temp` (scratch) roots surface alongside the My Files folders instead of being hidden; a `/raws` listing also accepts a `content_type` filter (exact shot-kind — `talking_head`, `b_roll`, `product_shot`, `screen_recording`, …), and every listing paginates via `offset` / `limit`. The devcli equivalents are `vidfarm files [--search]` / `get-file` / `put-file [--notes]` / `annotate-file` / `directory rename|move|copy`.
2093
2370
 
2371
+ ## Free browser sourcing — drive the user's own Chrome instead of paying
2372
+
2373
+ The sourcing ladder starts at *"your own browser control, if you have it."* **browser-harness is how you have it.** It attaches you to the user's already-running Chrome over one CDP websocket, so you can search, scroll, click and download on their own logged-in session and their own IP — at **$0**, with no Vidfarm plan, no API key, and no wallet.
2374
+
2375
+ That matters because the four routes an agent reaches for when sourcing footage are all **paid plans only**. A free-tier director asking the single most common question in the product — *"find me a clip of X"* — otherwise gets a 402. With browser-harness they get footage.
2376
+
2377
+ | Paid Vidfarm primitive | Free browser substitute | What you lose |
2378
+ |---|---|---|
2379
+ | `vidfarm video-search "<shot>"` ($0.0003/call) | `vidfarm browse videos "<shot>"` → Google Videos | You read the SERP yourself; no ranked JSON |
2380
+ | `vidfarm image-search "<shot>"` ($0.0003/call) | `vidfarm browse images "<shot>"` → Google Images | Full-res URLs need a click-through per result |
2381
+ | `vidfarm news-search "<topic>" --fresh w` ($0.0003/call) | `vidfarm browse news "<topic>"` → Google News | No `--fresh` operator; use Google's own Tools → time filter |
2382
+ | `vidfarm download-video <url>` (wallet resolver) | `vidfarm browse page "<url>"` → save the media off the page | Manual per URL; but a logged-in session reaches posts an anonymous resolver cannot |
2383
+ | `vidfarm recycle <reddit/x url>` | browse the thread and read it | No structured comment tree — you extract by hand |
2384
+
2385
+ **Say the trade honestly.** The paid primitives return clean ranked JSON in one call and are genuinely cheap — two orders of magnitude under one AI image attempt. Browser sourcing costs no money and more of your turns. In `minimize` it is the right call every time. In `hybrid` prefer it for a wide first sweep and pay for the primitive when you need many precise results fast. In `rich-ai` / `pure-videogen` don't bother — the spend is already authorized and your turns are worth more.
2386
+
2387
+ ### Setup — one command
2388
+
2389
+ ```bash
2390
+ vidfarm browser setup # installs browser-harness via uv, registers its skill, prints the Chrome step
2391
+ vidfarm browser status # what's installed
2392
+ vidfarm browser doctor # connection check (wraps `browser-harness --doctor`)
2393
+ ```
2394
+
2395
+ `setup` does three things and then stops at the one it cannot do for the user:
2396
+
2397
+ 1. `uv tool install --python 3.12 --upgrade --force browser-harness` (it prints the `uv` installer first if `uv` is missing).
2398
+ 2. Writes `browser-harness`'s own SKILL.md into `.agents/skills/browser-harness/SKILL.md` beside the vidfarm pack — **read that file before your first browse**; it carries the accessibility-tree-first workflow, tab handling, downloads, iframes and the CDP escape hatch. This page is the Vidfarm-side routing, not a replacement for it.
2399
+ 3. Prints the **one manual step**: Chrome → `chrome://inspect/#remote-debugging` → tick *"Allow remote debugging for this browser instance"*. Nothing can do this for the user. On macOS a per-connection permission sheet may follow — `browser-harness mac-approve` clears it.
2400
+
2401
+ `vidfarm doctor` reports it as `browser control`, at `⚠` when absent. It is optional: a box without it is a healthy box, just a more expensive one.
2402
+
2403
+ **Proactively offer it to every free-plan user.** Before you tell someone the search primitive needs a paid plan, offer the setup — it is about a minute, it is free forever, and it converts "I can't source that" into "I found six candidates." Same for anyone in cost mode `minimize`. Do not install it silently: it drives their personal browser, so ask first and say what it does.
2404
+
2405
+ ### The browse recipes
2406
+
2407
+ `vidfarm browse <videos|images|news|page> "<query|url>"` prints the recipe for one sourcing job — the Google surface to open, the extraction to run, and the vidfarm command it feeds:
2408
+
2409
+ ```bash
2410
+ vidfarm browse videos "warehouse worker packing orders POV 4K"
2411
+ vidfarm browse images "manila street market wide shot"
2412
+ vidfarm browse news "AI startup funding announced"
2413
+ vidfarm browse page "https://www.tiktok.com/@user/video/123…"
2414
+ vidfarm browse videos "…" --run # pipe it straight into browser-harness instead of printing
2415
+ vidfarm browse videos "…" --json # the same recipe as data
2416
+ ```
2417
+
2418
+ Default is **print, not run** — deliberately. Google's markup moves, and an agent that reads the recipe and adapts it beats one that runs it blind. Reach for `--run` when you have already browsed successfully this session.
2419
+
2420
+ **Query craft carries more weight here than anywhere else in the pack** — Google is the ranking function now, not Vidfarm. Use the shot formula (`[subject] + [action] + [shot/style] + [quality/orientation]`), the `site:` aims at Pexels / Pixabay / Mixkit / archive.org / Wikimedia, and the Creative-Commons YouTube operators. All of that is in `references/assets-and-sourcing.md` → *Google search for footage*; it applies unchanged whether you paid for the search or browsed it.
2421
+
2422
+ Surface parameters: the recipes use Google's current `udm=` (`2` images, `7` videos, `12` news). If a surface comes back looking wrong, rerun with `--legacy` for the older `tbm=isch|vid|nws`.
2423
+
2424
+ ### Collecting raws with it — the loop that matters
2425
+
2426
+ Browser sourcing is at its best on a **raws collection pass**, not on a single lookup. You are filling a shot pool, so batch it:
2427
+
2428
+ ```bash
2429
+ # 1. plan the shot list first (see "Phase 0" in SKILL.md) — never browse without one
2430
+ vidfarm storyboard ./work --init --frames "Hook,Problem,Reveal,CTA"
2431
+
2432
+ # 2. one browse per SHOT, not per video
2433
+ vidfarm browse videos "founder frustrated at desk vertical raw footage"
2434
+
2435
+ # 3. mine each good hit into short tagged raws — free, local
2436
+ vidfarm raws scan "<result url>" --duration 10 --aspect 9:16 --no-text --prompt "<the beat this covers>"
2437
+ vidfarm clipper "<result url>" --start 00:01:12 --end 00:01:19 # or one surgical cut
2438
+
2439
+ # 4. everything lands in the searchable local library, reusable across every later video
2440
+ vidfarm raws search "founder looking defeated"
2441
+ ```
2442
+
2443
+ If `raws scan` cannot bootstrap a remote URL without a key, that is exactly the gap browser control fills: save the file from the page in Chrome, then `vidfarm clipper ./saved.mp4` or `vidfarm put-file ./saved.mp4`.
2444
+
2445
+ **Check the free catalog before you browse at all.** `vidfarm public-raws --categories` and `vidfarm media search "<meaning>"` and `vidfarm iconscout "<meaning>" --free` cost nothing and cost no turns either. Browsing is rung 1 of the ladder, but the free shelves are rung 0.
2446
+
2447
+ ### Interactive mode — hand Chrome to the human instead
2448
+
2449
+ In `interactive` mode you have a better option than driving the browser yourself: **tell the user to drive it.** A person scrubbing a TikTok search picks better footage than any keyword extraction, and it costs them two minutes.
2450
+
2451
+ Give them the shot list, not a task: *"Search TikTok for `packing orders small business` and `day in the life warehouse`, grab 4–6 clips where the hands are visible and there's no burned-in text, drop them in `./raws-inbox/`."* Then import the folder. `vidfarm handoff raws --keywords "…" --platforms tiktok,youtube --purpose "<what the clips are for>"` mints that brief in full.
2452
+
2453
+ The two are complementary, not alternatives: browse yourself to find *which* sources are worth a human's attention, then hand the shortlist over for the taste call. Same shape as the image checkpoint — you write the prompt, they run the free generator.
2454
+
2455
+ ### Limits, and the honest caveats
2456
+
2457
+ - **It is the user's real browser.** Their sessions, cookies, history and open tabs are in reach. Ask before setting it up, keep to the pages the task needs, and never touch a logged-in surface the task didn't call for.
2458
+ - **Recordings are off by default and stay off** unless the user asks for them — they write page content to disk. `browser-harness recordings` shows the preference.
2459
+ - **Login walls: stop and ask.** Do not attempt credentials, MFA, or account selection.
2460
+ - **Captchas and rate limits are the real failure mode.** A burst of automated Google queries gets challenged. Space the searches, keep them wide rather than many, and if you get walled, fall back to the free catalog or the paid primitive rather than hammering.
2461
+ - **A public result is not a licensed asset.** Browsing changes what it costs to find footage, not what it costs to use it. Keep the source URL and the licence page for anything reaching a client render, and prefer public domain → CC0 → CC BY → explicit commercial stock → written permission, in that order.
2462
+ - **Don't reach for a browser when a fetch would do.** A public page, an API, a docs URL — `curl` it. The browser is for interaction, a logged-in session, JS-rendered results, and bot-protected pages.
2463
+ - **`vidfarm serve` is unaffected.** Browser control is for sourcing; the local editor, local render, `qa` and `stills` all run without it.
2464
+
2465
+ ## Image generation your own subscription already includes — free custom art in `minimize`
2466
+
2467
+ Vidfarm does not need to sell you an image model when the agent driving the terminal already has one. **If your own runtime includes image generation at no extra charge, that is a $0 rung on the asset ladder** — and it is the only free rung that produces *bespoke* art with no manual step and no waiting on the human.
2468
+
2469
+ This is the same house pattern as `vidfarm consult`: the devcli writes the brief, the agent already in the terminal executes it.
2470
+
2471
+ ### Who has it
2472
+
2473
+ | Host agent | Image generation included? | The tool |
2474
+ |---|---|---|
2475
+ | **Google Antigravity** | **Yes** | Gemini image generation (Nano Banana / Imagen) — part of the Gemini subscription |
2476
+ | **Gemini CLI** | **Yes** | same |
2477
+ | **OpenAI Codex / ChatGPT** | **Yes** | `gpt-image` — part of the ChatGPT plan |
2478
+ | **Claude Code** | **No** | Anthropic ships no image model. There is nothing to fall back on |
2479
+ | OpenCode / Cursor / anything else | **Depends on the configured model** | check your own tool list |
2480
+
2481
+ `vidfarm agent-image --check` prints this table plus a guess at the current host from its env markers. **The env guess is a hint. You are the authority** — look at your own tool list. Claiming a tool you don't have wastes a turn; missing one you do have costs the user money.
2482
+
2483
+ ### Why this is allowed in `minimize`
2484
+
2485
+ `minimize` means **$0 per video**, not "no AI". The rule it enforces is *do not bill the user's provider key or wallet by surprise*. Generation the user already paid for in a flat monthly subscription bills neither:
2486
+
2487
+ - Vidfarm charges **$0** — no primitive is called, no job is created, no wallet debit.
2488
+ - The provider charges **$0 extra** — the capability is inside the plan the user is already on.
2489
+
2490
+ So the ladder in `minimize` is:
2491
+
2492
+ 1. **Free stock** — `vidfarm media search "<meaning>" --type image|vector` (Openverse is keyless).
2493
+ 2. **IconScout** — `vidfarm iconscout "<meaning>" --free` for any icon, sticker, illustration, 3D prop or Lottie. Still beats generation on price *and* on quality: a designer's finished transparent vector, no prompt loop.
2494
+ 3. **Art the director already owns** — `vidfarm mask <image> --crop x,y,w,h` lifts an element out of a screenshot, infographic or their own site for $0.
2495
+ 4. **Your own included image generation** — this page. Bespoke art, $0, no human step.
2496
+ 5. **The human hand-off** — `vidfarm handoff image --theme "…" --items "a,b,c"`; they paste it into a free web generator.
2497
+ 6. **Billed generation** — `vidfarm generate image` (~$0.01–$0.05 on their own key). In `minimize` this needs the user's explicit `--yes`.
2498
+
2499
+ Rungs 1–3 come first even when you *do* have a free image tool: a real photo or a designer's vector still beats a generated approximation for most props, and it costs zero turns.
2500
+
2501
+ ### The command
2502
+
2503
+ ```bash
2504
+ vidfarm agent-image --check # do I have this here?
2505
+ vidfarm agent-image "cozy farm props" --items "barn,tractor,hay bale"
2506
+ vidfarm agent-image "a smiling mascot pineapple" --single --out ./mascot.png
2507
+ vidfarm agent-image "…" --items "…" --folder greenscreen/props # name the import folder
2508
+ vidfarm agent-image "…" --json # the brief as data
2509
+ ```
2510
+
2511
+ It prints the generation prompt, the plate rules, and the two follow-up commands. It calls nothing and costs nothing — printing a brief is free in every cost mode.
2512
+
2513
+ Flags mirror `vidfarm handoff image`: `--items`, `--style`, `--key-color`, `--out-dir`, `--grid`, `--single`, `--zoned`, plus `--out` (where you save the generated file) and `--folder` (where the finished asset is imported).
2514
+
2515
+ ### The loop
2516
+
2517
+ ```bash
2518
+ # 1. get the brief
2519
+ vidfarm agent-image "cozy farm props" --items "barn,tractor,hay bale"
2520
+
2521
+ # 2. generate with YOUR OWN tool, using the printed prompt, saving to ./sheet.png
2522
+ # (no vidfarm command — this step is your runtime's image tool)
2523
+
2524
+ # 3. cut it locally for $0
2525
+ vidfarm sticker-pack ./sheet.png --items "barn,tractor,hay bale" --out-dir ./stickers
2526
+
2527
+ # 4. persist it so the next video reuses it for free
2528
+ vidfarm put-file ./stickers/barn.png --folder greenscreen/props --notes "flat vector barn, transparent"
2529
+ ```
2530
+
2531
+ **The prompt body is shared verbatim with `vidfarm handoff image`.** A plate that keys cleanly and art that survives the cut are the same craft whoever runs the generator: one flat chroma plate, generous spacing, nothing touching or bleeding off the frame edge, crisp outer edges with no glow or drop shadow. The plate color is picked *against the subject* — green art on a green plate keys holes through the artwork — and the command tells you when it moved the plate and why. Details: `references/assets-and-sourcing.md` and the sticker-pack rules in `recipes/cutout-graphics-for-explainers.md`.
2532
+
2533
+ ### The honest limits
2534
+
2535
+ - **Do not pretend.** If you have no image tool, say so and drop to the next rung. A fabricated image path is worse than a $0.02 spend.
2536
+ - **Look at what you generated.** The cut is only as good as the plate. A soft edge, two objects touching, or an object cropped at the frame edge all produce a broken sticker — re-generate rather than shipping it.
2537
+ - **It is still generated art.** Every "prefer a real asset over a generated one" rule in the pack still applies: an icon from IconScout looks better than a generated icon, and the free stock photo looks better than a generated photo. Free does not mean *first*.
2538
+ - **It does not extend to video.** No agent subscription currently includes video generation, so AI *video* is still a billed Vidfarm primitive gated by cost mode. This rung is images only.
2539
+ - **Say what you did.** When a graphic in the deliverable came from your own image tool rather than from stock or a paid job, tell the user — they are entitled to know what the video is made of, and it is the proof that `minimize` really did cost $0.
2540
+
2094
2541
  ## Free-plan API keys — valid everywhere, gated per route
2095
2542
 
2096
2543
  A free (unpaid) account's `vidfarm-api-key` is a **real key**: it authenticates on every route, and `vidfarm login` / `whoami` work normally. Plan is enforced per route, not at auth:
2097
2544
 
2098
- - **Free on any plan** — `GET /api/v1/user/me` (identity), `/api/v1/user/me/provider-keys` (bring-your-own-key), `GET /api/v1/user/me/wallet` (reads $0.00), `GET /api/v1/user/me/tasks`, and the `/api/v1/user/me/directory*` file-tree routes (browse, search, folder, rename, move, copy, shares).
2545
+ - **Free on any plan** — `GET /api/v1/user/me` (identity), `/api/v1/user/me/provider-keys` (bring-your-own-key), `GET /api/v1/user/me/wallet` (reads $0.00), `GET /api/v1/user/me/tasks`, and the `/api/v1/user/me/directory*` file-tree routes (browse, search, folder, rename, move, copy) — but **not** `…/directory/shares*`: minting a public share link is paid. Visiting someone's link (`/api/v1/share/:token/*`, `/directory/preview/*`) needs no account at all. **The marketplace is paid-only end to end** — every `/marketplace*` page and route (the agent directory included) answers the upgrade wall for a free account, the sidebar Marketplace link is hidden for them, and the two DollarPlatoon vending machines are provisioned on the paid plan (on upgrade, for an account that started free).
2099
2546
  - **Paid routes answer `402 { type: "upgrade_required", upgrade_url: "/pricing", run_locally_url: "/help" }`** — never a 401. A `401` means the key is missing/invalid/revoked, so don't tell a free user to re-authenticate when they hit a 402.
2100
2547
  - When you see a 402: say plainly that the action needs a paid plan, then offer the two real paths — upgrade at `/pricing`, or keep going for free locally (`vidfarm serve`, local render, local decompose, own-provider keys).
2101
2548
 
@@ -2366,7 +2813,7 @@ The licensed harness also carries the **generative build workflow** guidance (ch
2366
2813
  | `vidfarm visibility <forkId> <private\|public>` | `PATCH .../compositions/:forkId/visibility` | set visibility |
2367
2814
  | `vidfarm clone <forkId>` | `POST .../compositions/:forkId/clone` | clone a fork |
2368
2815
  | `vidfarm share-link <forkId>` | `POST .../compositions/:forkId/share-links` | mint a share URL |
2369
- | `vidfarm approve --video <url\|file> --caption "…"` | `POST /api/v1/approved/posts` | approve post — takes media by **`url`**. Local `--video`/`--media` auto-upload to **durable My Files** via presign→S3→finalize (up to **200 MB**, bypasses the ~6 MB Lambda limit) then approve with that URL, so the share video **never expires**; also accepts a `/files…` path. `--temp` opts into the 30-day temp store (throwaway preview only). Prints `share_url` |
2816
+ | `vidfarm approve --video <url\|file> --caption "…"` | `POST /api/v1/approved/posts` | approve post — takes media by **`url`**. Local `--video`/`--media` auto-upload to **durable My Files** via presign→S3→finalize (up to **200 MB**, bypasses the ~6 MB Lambda limit) then approve with that URL, so the share video **never expires**; also accepts a `/files…` path. `--temp` opts into the 30-day temp store (throwaway preview only). `--thumbnail <url\|file>` picks the social-card poster; omit it and a frame ~1s into `--video` is extracted into `/files/approved`. Prints `share_url` |
2370
2817
  | `vidfarm posts` / `vidfarm post <id>` | `GET /api/v1/approved/posts[/:id]` | browse approved posts |
2371
2818
  | `vidfarm schedule <postId> --at <iso> --to <dest>` | `POST /api/v1/approved/posts/:postId/schedules` | schedule a post |
2372
2819
  | `vidfarm schedules <postId>` | `GET /api/v1/approved/posts/:postId/schedules` | browse scheduled posts |
@@ -2374,12 +2821,18 @@ The licensed harness also carries the **generative build workflow** guidance (ch
2374
2821
  | `vidfarm whoami` | `GET /api/v1/user/me` | who am I (also prints the active cost mode) |
2375
2822
  | `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 |
2376
2823
  | `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`. |
2824
+ | `vidfarm browser [status\|setup\|doctor]` | local (installs [browser-harness](https://github.com/browser-use/browser-harness) via `uv`) | **Free browser sourcing — the $0 substitute for the PAID `video-search` / `image-search` / `news-search` / `download-video` primitives.** `setup` runs `uv tool install --python 3.12 --upgrade --force browser-harness`, writes browser-harness's own SKILL.md into `.agents/skills/browser-harness/`, and prints the one step nothing can automate: Chrome → `chrome://inspect/#remote-debugging` → tick *Allow remote debugging* (macOS may then need `browser-harness mac-approve`). After that you drive the user's own logged-in Chrome over CDP. `status` = what's installed, `doctor` = connection check. `vidfarm doctor` reports it as `browser control` (⚠ when absent — it is optional, not required). **Offer it to every free-plan user and everyone in `cost-mode minimize` before saying a search needs a paid plan**, and ask first: it drives their personal browser. Aliases: `browser-harness`, `bh`. Full page: `references/browser-harness.md`. |
2825
+ | `vidfarm browse <videos\|images\|news\|page> "<query\|url>" [--limit N] [--legacy] [--run] [--json]` | local (pure text; `--run` pipes into browser-harness) | **The browse recipe for one sourcing job**: which Google surface to open (`udm=7` videos · `udm=2` images · `udm=12` news; `--legacy` for the old `tbm=…`), what to extract off the page, and the vidfarm command it feeds (`raws scan` / `clipper` / `put-file`). Prints rather than runs by default — Google's markup moves, so an agent that reads and adapts the recipe beats one that runs it blind; `--run` when you have already browsed successfully this session. `page` mode substitutes for `download-video` by pulling the media element off the post in the user's own session. |
2826
+ | `vidfarm agent-image "<subject>" [--items "a,b,c"] [--single] [--out ./sheet.png] [--folder <f>] [--check]` | local (pure text) | **Image generation the AGENT already pays for — free in EVERY cost mode, `minimize` included.** Google Antigravity / Gemini CLI (Nano Banana / Imagen) and OpenAI Codex / ChatGPT (`gpt-image`) include image generation in the subscription; **Claude Code does not** — Anthropic ships no image model. Prints the generation prompt (the same key-plate craft as `handoff image`), the steps, the local cut (`sticker-pack`/`cutout`) and the `put-file` import. Calls nothing and spends nothing, so it never gates and needs no `--yes`. `--check` (or no args) reports whether this host has the capability, from env markers plus the known-hosts table — **a hint only; your own tool list is the authority, so never claim a tool you do not have**. Free stock, `iconscout` and `mask` still come first. Aliases: `agent-imagegen`, `own-image`, `native-image`. Full page: `references/agent-included-imagegen.md`. |
2377
2827
  | `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), spells out what the local keyer actually needs (a crisp silhouette in a different color from the plate, sealed shapes, clear gaps between items — hollow art and plate-colored detail INSIDE a shape are fine now), and carries that `--key-color` into the follow-up. `--single` for one subject. `--zoned` asks instead for a color-block sheet (one panel colour per item) and hands back a `--zones RxC` follow-up — worth it when the pack's own colors fight one plate, but leave it off for a free consumer tool that may not follow a grid. |
2378
- | `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. |
2828
+ | `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 via `vidfarm browser setup` + `vidfarm browse` → `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. |
2379
2829
  | `vidfarm consult [coldstart\|awareness\|angles\|hooks\|placement]` | local (pure text) | **The consultation / brainstorm chain, KEYLESS.** Offer `vidfarm ideas` first — the interview is the deeper step a director opts into after they have seen a list of ideas, not the price of entry. The cloud runs these five steps as `brainstorm/*` primitives that need a provider key or wallet credits; this prints the **identical prompt** (same source module, so they cannot drift) for the agent already in the terminal to answer itself — $0, no key, no network. Bare `consult` = the map of the four chain steps and which artifacts already exist. Auto-reads `OFFER.md` / `OFFER_<NAME>.md` from `--dir` (two offer files → it makes you name one rather than guessing the wrong product); `--offer` takes a path **or** the offer text, and a path that resolves to nothing is an error, never silently treated as the offer. `--count` mirrors the cloud bounds. **`coldstart --short` is the short-form interview**: six fixed questions (offer line, price/checkout, best customer, their complaint verbatim, dream outcome, do they know this product category exists) instead of 12-30 generated ones — instant, identical every run, and still enough for every later step. Interview only, and it takes no `--count`. **Every step reads and appends `CONTEXT.md` in `--dir`** — the durable answer file, so a later session in a new terminal starts warm instead of re-interviewing the director. Tell the director the interview is skippable before you ask anything; mark skipped answers `UNKNOWN` and carry on. `--refs` inlines the full `SELLING_*.md` documents for byte parity — off by default because it is ~34KB of your context, and the brief points at `references/hooks-and-virality.md` instead. Each step names the artifact it writes (`OFFER.md` → `awareness-levels.md` → `persuasive-angles.md` → `ad-hooks.md`) and the next command. Aliases: `consultation`, `brainstorm`. Flow: `references/onboarding.md`. |
2380
2830
  | `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`. |
2381
2831
  | `vidfarm experiment [dir] [--init] [round …] [log <video> …] [--json]` | local (`EXPERIMENTS_DIARY.md`) | **Ad testing over weeks, not one video.** Owns the campaign ledger and ONLY that: sizes each round (`videos ÷ capacity = epochs`, where capacity is the SUM of per-channel posting rates — `--channels "tiktok_a x2, li_a 3/week, fb_a paused"` — and epoch slots are dealt out in proportion, warning on `channel-overposted`), ranks the north-star metric, flags outliers vs the median, and lints the method — two variables in one structured round, a winner promoted off one post, results read at mixed ages, a structured round handed to gigworkers, unspent capacity. Feedback, not a gate (exits 0). Also carries the FORMAT decision into planning: `--init` prints the copywriting-led menu (b-roll / talking head / process / loop background / satisfying / lifestyle / POV quote) and records the pick in Setup, which every round inherits. Two writes: `round --videos N --variable angle …` and `log <video> --comments N --channel <acct> --source flockposter --age 48h` (ALWAYS pass `--channel`: it keeps a per-account median so each video is ranked against its own account, not the fleet — account health moves numbers by multiples — and a second account's reading counts as the retest that clears `account-health-confound`) (or `log <video> --posted --channel <id>`, which only RECORDS a post). It deliberately does not re-wrap `channels` (capacity), `harness`/`qa` (constants), `handoff` (briefs), `dedupe` (per-channel copies) or `approve`+`schedule` (posting). Method: <https://vidfarm.cc/experiments.md>. Alias: `experiments`. |
2382
2832
  | `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` |
2833
+ | `vidfarm video-search "<query>" [--limit n] [--fresh d\|w\|m\|y] [--duration short\|medium\|long] [--resolution high\|standard] [--region r]` | `GET /api/v1/primitives/video-search` | **GOOGLE VIDEO SEARCH — how you SOURCE footage.** Returns real source URLs off the open web (TikTok, YouTube, Pexels/Pixabay/Mixkit, news, archive.org), which go straight into `vidfarm raws scan <url>` (mine clips) or `vidfarm download-video <url>` (collect the file). Search the **shot**, not the topic: `[subject]+[action]+[shot/style]+[quality/orientation]`. Google operators work — `site:pexels.com/videos`, `site:tiktok.com "packing orders" -dance`, `"exact phrase"`. **PAID PLAN · flat $0.0003 per call** whatever the result count, so ask for one WIDE page (`--limit 40`) instead of paging. Returns LINKS with **no licence** — check rights before reuse. Aliases: `videosearch`, `search-video` |
2834
+ | `vidfarm image-search "<query>" [--limit n] [--type-image photo\|clipart\|gif\|transparent] [--color c] [--size s] [--layout Square\|Tall\|Wide]` | `GET /api/v1/primitives/image-search` | Google image search — reference stills, textures, logos, product shots. Same operators. **PAID PLAN · flat $0.0003 per call.** For licence-checked, royalty-free assets prefer `vidfarm media search --type image` (free); these are LINKS with no licence. Aliases: `imagesearch`, `search-image` |
2835
+ | `vidfarm news-search "<query>" [--fresh d\|w\|m\|y] [--limit n] [--region r]` | `GET /api/v1/primitives/news-search` | Google News — recent real events, so an agent can build **timely** content. News finds the STORY; run `video-search` after for the VISUALS (searching both at once finds neither). **PAID PLAN · flat $0.0003 per call.** Full method: <https://vidfarm.cc/experimental/google-news-to-video.md>. Aliases: `news`, `newssearch`, `search-news` |
2383
2836
  | `vidfarm iconscout "<query>" [--asset icon\|illustration\|3d\|lottie] [--style sticker] [--free\|--premium] [--sort …] [--limit n]` | `GET /api/v1/primitives/iconscout/search` | **The cheap alternative to AI image generation.** Designer-made icons, STICKERS, illustrations, 3D props and Lottie. Reach for this BEFORE `generate image` for any of those: an AI attempt costs cents, needs a prompt loop, and rarely returns a clean transparent vector, while IconScout hands back a finished SVG / transparent PNG on the first try. **Search is FREE and never gates.** Needs **no key** — vidfarm's own IconScout account serves it. Aliases: `icons`, `stickers` |
2384
2837
  | `vidfarm iconscout get <uuid> [--format svg\|png\|…] [--size px] [--out file]` | `POST /api/v1/primitives/iconscout/download` | Download one asset to a durable vidfarm URL you can place. A **free** asset costs $0 (honour the returned `attribution`); a **premium** asset runs on vidfarm's IconScout subscription for a few cents on the wallet — still under one AI attempt. Saving your own `iconscout` key makes downloads free. Idempotent per uuid+format. |
2385
2838
  | `vidfarm provider-keys` / `vidfarm add-provider-key <p> <secret>` | `GET`·`POST /api/v1/user/me/provider-keys` | manage AI keys. `iconscout` is the one provider that packs TWO values into one secret: `<client_id>:<client_secret>` |
@@ -2389,7 +2842,7 @@ The licensed harness also carries the **generative build workflow** guidance (ch
2389
2842
  | `vidfarm download-audio <url>` | `POST /api/v1/primitives/audio/download` + poll | download just the AUDIO track (music/voice) off a website post into a durable audio file. **PAID PLAN**. Alias: `download-post-audio` |
2390
2843
  | `vidfarm recycle <source>` | `POST /api/v1/primitives/social/recycle` + poll | RECYCLE a Reddit/X source into reusable JSON ("tweet to tiktok", "reddit to tiktok"): thread + comments, subreddit threads, X thread + replies, or an account's posts — text, author + avatar, stats, media URLs. `--out` saves the full payload. **PAID PLAN**. Aliases: `recycle-social`, `tweet-to-video`, `reddit-to-video` |
2391
2844
 
2392
- > **Free plan / `cost-mode minimize`:** both download commands are gated by `guardBilled` and will refuse or warn. The free path is **Chrome**: open the URL in a real browser, save the file off the page (right-click → *Save video as*, downloads pane, or a Googled `"<platform> video downloader"` site), then `vidfarm put-file ./the-file.mp4 --folder <folder>` to bring it in for $0. The CLI prints these steps on a 402. Never tell a free user the video simply can't be downloaded.
2845
+ > **Free plan / `cost-mode minimize`:** both download commands are gated by `guardBilled` and will refuse or warn. The free path is **Chrome** and you can drive it yourself: `vidfarm browser setup` then `vidfarm browse page "<url>"` (see `references/browser-harness.md`). Otherwise the user opens the URL in a real browser and saves the file off the page (right-click → *Save video as*, downloads pane, or a Googled `"<platform> video downloader"` site), then `vidfarm put-file ./the-file.mp4 --folder <folder>` to bring it in for $0. The CLI prints these steps on a 402. Never tell a free user the video simply can't be downloaded.
2393
2846
  | `vidfarm files [--folder <path>]` | `GET /api/v1/user/me/attachments` | list My Files assets + folders |
2394
2847
  | `vidfarm files --search "…" [--folder <path>]` | `POST /api/v1/user/me/attachments/search` | find My Files assets by MEANING (keyword + vector over name/folder/notes) |
2395
2848
  | `vidfarm get-file <id> [dest] [--print]` | (resolve id → view_url, then stream/print) | read one My Files asset |
@@ -2407,7 +2860,7 @@ The licensed harness also carries the **generative build workflow** guidance (ch
2407
2860
  | `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) |
2408
2861
  | `vidfarm skills list\|add <name>\|update` | `GET /skill-pack/index.json` · `/skill-pack/:name/*` | install/refresh skill packs (see "Skill packs — import on demand") |
2409
2862
  | `vidfarm skill ls\|topics\|show <path\|topic>\|search "<term>"\|path` | (local — **offline, no account**) | **Read this pack straight off disk.** A full copy ships inside the devcli tarball and is pinned to the installed version. `search` greps all 23 files at once — the cheapest way to find one paragraph without loading a whole reference. **`topics` is the spoken-name index** (meme-recaption, product-explainer, captions, first-frame, blurred-plate, density, avatar, dedupe, …) and `show <topic>` prints just that SECTION, not the 650-line file it lives in |
2410
- | `vidfarm ideas [topic] [--topic "<offer>"] [--family <name>] [--families] [--count <n>] [--json]` | (local — **offline, free, no AI call**) | **"What should I post?"** — the 50-frame content-idea angle bank, read out of `references/content-ideas.md` so the CLI and the skill never drift. `--topic` fills every frame with the director's offer as a starter line; `--count` samples across families instead of truncating. It hands over frames, not finished titles — sharpen each one, then write hook/loop/payoff/bait. **Run this BEFORE `vidfarm consult` on a new director**: one line of offer buys 20+ ideas with no key and no interview, which is the easiest first win, and their reactions to the list make the later interview better |
2863
+ | `vidfarm ideas [topic] [--topic "<offer>"] [--family <name>] [--families] [--stages] [--stage <name\|n>] [--angles] [--angle <name>] [--grid] [--count <n>] [--json]` | (local — **offline, free, no AI call**) | **"What should I post?"** — the three content-idea banks, read out of `references/content-ideas.md` so the CLI and the skill never drift. `--topic` fills every frame with the director's offer as a starter line; `--count` samples across families instead of truncating. `--stages` prints the 5-stage awareness ladder (what each stage believes, what the video must do, its frames, its angles, and what it may ask for); `--angles` prints the 44 problem angles by family — hold the frame and change the angle when a topic is "already covered"; **`--grid --topic "<offer>" --count 30` lays out a balanced month**, one row per video, in the default stage mix. It hands over combinations, not finished titles — sharpen each one, then write hook/loop/payoff/bait. **Run this BEFORE `vidfarm consult` on a new director**: one line of offer buys 20+ ideas with no key and no interview, which is the easiest first win, and their reactions to the list make the later interview better |
2411
2864
  | `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 |
2412
2865
  | `vidfarm remove-background <video\|image>` | (local ONNX matting — free) | transparent-subject media for occlusion captions/cutouts (arbitrary/messy background; for a FLAT solid background use `remove-background-greenscreen`) |
2413
2866
  | `vidfarm capture <url>` | (local headless-Chrome capture) | website screenshots/assets for website-to-video flows |
@@ -2447,6 +2900,8 @@ What it flags:
2447
2900
  | `badge-chip-row` | error | 2+ sibling small rounded filled tags — the "✓ No Credit Card Needed · ✓ 30-Min Trial" strip |
2448
2901
  | `static-pill` | error | ONE filled, padded, ≥20px-radius capsule around static text — a stat/label badge like "10 hrs / week", "STEP 2", "EP.01". Skips active-word `spotlight`/`karaoke` highlights (the only legitimate pill) and mock social UI (chat bubbles, comment cards — mark yours `data-vf-mock-ui` if the heuristic misses it) |
2449
2902
  | `card-panel` / `glass-card` | error | A rounded box with a border/shadow/`backdrop-filter` wrapping 2+ elements. A tight legibility **band** (radius ≤8px, one text run, no border/shadow) stays legal |
2903
+ | `layout-template` | error | The frame composed like a **page**: 3+ stacked text blocks in one container ending in a call to action — headline + subheading + CTA, the web hero/modal body. Fires with or without the box around it, because the STACK is the tell. Three stacked lines with no CTA are a legitimate title card and pass |
2904
+ | `modal-scrim` | error | A full-frame backdrop that is **blurred AND dimmed** — the website-modal staging that pushes the picture back so a floating block pops. Blur alone passes (the blurred fill behind a 16:9 clip in a 9:16 frame is a real technique); it needs the dimming too, and a bed faded under `opacity:0.25` is an ambient texture wash, not staging, so it passes as well |
2450
2905
  | `gradient-text` | error | `background-clip:text` gradient headline fills |
2451
2906
  | `clickable-element` | error/warn | `<button>`, `<form>`, `<input>`; `<a href>` warns |
2452
2907
  | `web-framework-classes` | error/warn | Bootstrap/Tailwind class tokens (`btn`, `badge`, `card`, `hero`, `col-*`, `rounded-full`, `shadow-lg`, `backdrop-blur`, `bg-gradient-to-*`) or a linked CSS framework. A `<script>` CDN for GSAP/anime.js is fine |
@@ -2477,16 +2932,17 @@ The four modes, quoted as **cost per finished video**. The first two are spend p
2477
2932
 
2478
2933
  | Mode | Per video | Posture |
2479
2934
  |---|---|---|
2480
- | `minimize` | **$0 — explicitly free** | free local engines + free stock media only; billed ops refuse without `--yes` |
2935
+ | `minimize` | **$0 — explicitly free** | free local engines + free stock media, plus any image generation the AGENT's own subscription already includes; billed ops refuse without `--yes` |
2481
2936
  | `hybrid` *(default recommendation)* | **~$0.01–$1** | free where free, AI where it clearly wins; each billed op prints its cost |
2482
2937
  | `rich-ai` | **$1+** | AI video gen mints **reusable greenscreen raws** (saved to the library, reused later); motion is hyperframes HTML/CSS over the keyed raws |
2483
2938
  | `pure-videogen` | **$5+** | script in text → storyboard in images → frame-by-frame scene generation. No reuse, no HTML motion |
2484
2939
 
2485
2940
  **All of it bills to the user's own AI provider keys (BYOK)** — the keys saved with `vidfarm add-provider-key <provider> <key>` or at **Settings → Bring your own keys** (<https://vidfarm.cc/settings/developer>). The model providers charge those keys directly; Vidfarm wallet credits only come into play when the user deliberately runs on the platform key instead of their own. So `minimize` isn't "cheap", it's **zero**: nothing reaches a paid key at all.
2486
2941
 
2487
- `vidfarm cost-mode <minimize|hybrid|rich-ai|pure-videogen>` records a single spend preference (in `~/.vidfarm/cost-mode.json`) that every **billed** command honors: `generate`, `music`, `decompose`, `inspiration-decompose`, `create`, `replicate`, `inpaint`, `create-overlay`, `cutout --generate` (only the generation step; a bare `cutout` on an existing graphic is free), and the cloud paths of `render --target cloud`, `tts --cloud`, `stt --cloud`, `remove-greenscreen` (non-`--local`), `dedupe --cloud`. FREE local engines never gate (`render` local default, `tts --engine local`, `stt --engine whisper`, `remove-greenscreen --local`, `dedupe --local`, `cutout` on a file/url, all the file-editing verbs). `vidfarm media search` (the free stock catalog — pixabay/openverse/iconify music, SFX, images, icons, stock video) is also free and never gates. `vidfarm iconscout` **search** is free and never gates either; only `vidfarm iconscout get` on a PREMIUM asset can spend (a few cents on the wallet), and free assets cost $0.
2942
+ `vidfarm cost-mode <minimize|hybrid|rich-ai|pure-videogen>` records a single spend preference (in `~/.vidfarm/cost-mode.json`) that every **billed** command honors: `generate`, `music`, `decompose`, `inspiration-decompose`, `create`, `replicate`, `inpaint`, `create-overlay`, `cutout --generate` (only the generation step; a bare `cutout` on an existing graphic is free), and the cloud paths of `render --target cloud`, `tts --cloud`, `stt --cloud`, `remove-greenscreen` (non-`--local`), `dedupe --cloud`. FREE local engines never gate (`render` local default, `tts --engine local`, `stt --engine whisper`, `remove-greenscreen --local`, `dedupe --local`, `cutout` on a file/url, all the file-editing verbs). `vidfarm media search` (the free stock catalog — pixabay/openverse/iconify music, SFX, images, icons, stock video) is also free and never gates. `vidfarm iconscout` **search** is free and never gates either; only `vidfarm iconscout get` on a PREMIUM asset can spend (a few cents on the wallet), and free assets cost $0. `vidfarm video-search` / `image-search` / `news-search` (Google) are **paid-plan** but flat **$0.0003 per call** — two orders of magnitude under one AI image attempt — so they do not gate in any cost mode; in `minimize`, one wide search beats one generation every time. They are still **paid-plan** routes, though — on a free plan they 402, and the answer there is `vidfarm browser setup` + `vidfarm browse videos|images|news "<query>"`, which is free and never gates.
2488
2943
 
2489
2944
  - **minimize ($0 videos)** — a billed op is **refused** unless you add `--yes`; the error names the free local alternative (which now includes the matching `vidfarm media search` for music/SFX/image/video). Use this to guarantee no surprise AI spend. Before paying to generate music, sound effects, or images, try `vidfarm media search "<meaning>" --type <bgm|sfx|image|vector|icon|video>` first — free royalty-free assets instead of a billed `music`/`generate` call. **Check the keyless sources first — Openverse (CC/CC0 music, SFX, images) and iconify (icons) need no account at all**, so they always work in `minimize`. Photos/vectors/stock-video need a **free Pixabay key** that **may already be saved** — check `vidfarm provider-keys` (or web **Settings → Bring your own keys** / <https://vidfarm.cc/settings/developer>) before assuming a short result means "no key." If absent, save one once: `vidfarm add-provider-key pixabay <key>` (free key from <https://pixabay.com/api/docs/>), the Settings surface, or hand it to the desktop AI agent to run that command. **For icons, STICKERS, illustrations, 3D props and Lottie, use `vidfarm iconscout "<meaning>" --style sticker --free` instead** — it needs no key at all, search is free, and free assets download for $0 (a credit line is the only price). Prefer it over a generated graphic in every mode, not just `minimize`.
2945
+ - **minimize can use IMAGE GENERATION — when the agent already owns it.** `minimize` bans *billed* AI, not AI. If the agent driving the terminal includes image generation in its own subscription — **Google Antigravity / Gemini CLI (Nano Banana / Imagen) and OpenAI Codex / ChatGPT (`gpt-image`) do; Claude Code does NOT**, because Anthropic ships no image model — then generating a graphic costs Vidfarm $0 and the provider $0 extra, so it is allowed with no `--yes` and no gate. `vidfarm agent-image --check` reports whether this host has it (env sniffing + a known-hosts table — treat it as a hint and check your own tool list); `vidfarm agent-image "<subject>" --items "a,b,c"` prints the prompt, the plate rules and the cut + import commands. Order on the ladder: free stock → `iconscout` → `mask` → **your own image tool** → the human hand-off below → a confirmed billed `generate`. It is images only — no agent subscription includes video generation, so AI video stays gated. Full page: `references/agent-included-imagegen.md`.
2490
2946
  - **minimize still gets CUSTOM images — via a free manual generator.** A refused `generate` is not the end of the road. Offer the user the manual loop (ask once, then make it the session default): **you write the prompt → they run it free in <https://meta.ai>, free-tier ChatGPT, or a free Hugging Face image Space (<https://huggingface.co/spaces>) → they hand the PNG back** via `vidfarm put-file ./sheet.png` or web **My Files**. Ask for **one sheet holding every graphic you need**, gridded on a **flat pure-green plate** (`#00FF00`), no text — one round trip instead of N, which saves the user's time and your tokens. Then split it locally for $0: `vidfarm mask ./sheet.png --crop x,y,w,h --flat "#00FF00" --out prop-a.png`, once per element (drop `--flat` and let local ONNX matting handle it if the tool ignored the green background). Full prompt template + loop: recipe `recipes/cutout-graphics-for-explainers.md` (“Free manual image-gen”).
2491
2947
  - **hybrid (~$0.01–$1 per video)** *(default recommendation)* — billed ops run but print a one-line cost notice each, charged to the user's BYOK key.
2492
2948
  - **rich-ai ($1+ per video)** — billed ops run without gating; cost is still printed. AI *video* generation is the line item that pushes a video well past $1 — quote it before running. Spend it on **reusable greenscreen raws**, not on finished shots: `vidfarm avatar "<who>" --say "<line>"` for presenters, `vidfarm create-overlay "<subject>"` / `cutout --generate` for props and illustrations, or `generate video` prompted onto a flat key-color plate. The primitives key the plate in the same job and also hand back `greenscreen_source_url`, so re-keying at a different tolerance is free. Then **animate in hyperframes HTML/CSS over the keyed raws** — generated seconds cost money, motion doesn't — and **persist every asset**: `vidfarm put-file ./keyed.webm --folder greenscreen/<name> --notes "<what it is, when to reuse it>"` (notes are vector-embedded → `vidfarm files --search`), or `vidfarm clipper ./generated.mp4 --folder greenscreen-cast --name "<name>"` for footage-shaped raws in `/raws`. Both stores are **local by default** under `~/.vidfarm`; on a **paid/Pro plan** mirror them with `vidfarm sync push /files` and `vidfarm sync push /raws` (`sync pull` elsewhere, `--dry-run` first). Before generating, always search what already exists — `vidfarm raws search "<meaning>"` then `vidfarm public-raws --category greenscreen --query "<meaning>"`. That is what makes the mode amortize: the next video can reuse the same cast in `hybrid`/`minimize` for ~$0.
@@ -2514,7 +2970,8 @@ Local, wallet-free Vidfarm is a **three-part toolchain** that composes — insta
2514
2970
  ```bash
2515
2971
  npm install -g @officexapp/vidfarm-devcli # the `vidfarm` orchestrator
2516
2972
  npm install -g hyperframes # Vidfarm's open-source render/animation engine (whitelabel)
2517
- brew install ffmpeg # or apt install ffmpeg a system ffmpeg on PATH is honored first; ffmpeg-static is bundled as a fallback
2973
+ # ffmpeg is BUNDLED (ffmpeg-static + a per-platform ffprobe) install one only if doctor asks:
2974
+ # brew install ffmpeg / apt install ffmpeg / winget install Gyan.FFmpeg
2518
2975
  vidfarm doctor # ✓/⚠/✗ for node, ffmpeg, hyperframes, Chrome, auth, keys, skills
2519
2976
  ```
2520
2977
 
@@ -2591,7 +3048,10 @@ vidfarm skill show harnesses/README.md # or an exact path
2591
3048
  vidfarm skill search "greenscreen" # grep all of it — find the paragraph, then open that file
2592
3049
  vidfarm skill path # where the bundled copy lives
2593
3050
 
2594
- vidfarm ideas --families # the 50-frame idea bank, by family
3051
+ vidfarm ideas --families # the 50 content frames, by family
3052
+ vidfarm ideas --stages # the 5-stage awareness ladder, in full
3053
+ vidfarm ideas --angles # the 44 problem angles, by family
3054
+ vidfarm ideas --grid --topic "<offer>" --count 30 # a balanced month: stage x angle x frame
2595
3055
  vidfarm ideas --topic "bookkeeping for trades" --count 20
2596
3056
  ```
2597
3057
 
@@ -2694,7 +3154,7 @@ The point of onboarding is to build **durable, reusable context** in My Files, n
2694
3154
  2. **Awareness level** (Eugene Schwartz — problem-aware, solution-unaware, …) → `awareness-levels.md`. If it's genuinely unknown after thinking it through, note that ads for **every** level should be made and tested. Use `brainstorm/awareness_stages`.
2695
3155
  3. **Persuasive angles** → `persuasive-angles.md`, via `brainstorm/angles`.
2696
3156
  4. **Hooks** → `ad-hooks.md`, via `brainstorm/hooks`. **Grade what comes back against `references/hooks-and-virality.md`** — the three gates, situation-vs-label, and the unguessable test — instead of shipping the raw list. And never rank a generated batch with the same reasoning that wrote it; the rubric catches defects, it doesn't pick winners.
2697
- 4b. **Content ideas, second pass** → update `content-ideas.md`. Step 0 already produced a list from one line of offer; now that the offer document and the awareness stage exist, work the 50-frame angle bank in `references/content-ideas.md` against them again and rewrite the weak picks. A solution-unaware audience wants different frames than a product-aware one, which is exactly what step 0 could not know. This is what the director actually posts from between chats, and it is the answer to "what should I post?" for the next month.
3157
+ 4b. **Content ideas, second pass** → update `content-ideas.md`. Step 0 already produced a list from one line of offer; now that the offer document and the awareness stage exist, work all three banks in `references/content-ideas.md` against them again and rewrite the weak picks. Now you can set the awareness stage per idea and spread the set across the ladder, which is exactly what step 0 could not do — a solution-unaware audience wants different frames, different angles and a different ask than a product-aware one. This is what the director actually posts from between chats, and it is the answer to "what should I post?" for the next month.
2698
3158
  5. **Brand assets & demos** — ask if they have logos/mascots/themes (suggest a `/brand-assets/` folder, e.g. `/brand-assets/logo.png`) or product demos / screen recordings (suggest a `/product-demos/` folder). `browse_files list` / `vidfarm files` first to see what they already uploaded; filenames should be descriptive and every asset worth finding later should get **notes** (`annotate-file` / `browse_files annotate`) so `files --search` works months from now. If they have a recurring character/mascot, set up its `/files/characters/<slug>/` trio now — `<character_id>.json` (e.g. `character_zara.json`) + `character_sprite_card.png` + `character_about.md` (see "Recurring characters are first-class").
2699
3159
  6. **Budget** — ask roughly what they want to spend per video, and map it to the Cost spectrum (free reuse+local render → pennies for cloud render → ~$1 for some AI scenes → $10+ for heavy AI gen). This sets which approach you default to and whether AI **video** generation is on the table (ask permission before using it; image gen is cheap and fine). Budget can also be revisited per editor project.
2700
3160
  - **While you're on money, set the graphics default: IconScout, not AI image generation.** Any icon, sticker, illustration, 3D prop, or Lottie should come from `vidfarm iconscout "<meaning>" --style sticker` — a designer's finished transparent asset on the first try, for a fraction of one AI attempt. **It needs no key and no setup**: vidfarm's own IconScout account serves it, search is free, and free assets download for $0 (a credit line is the only price). Say this out loud during onboarding — it's the single biggest per-video saving a new director can adopt on day one, and it holds in **every** cost mode, not just `minimize`. A director who already pays IconScout can save their own key once (`vidfarm add-provider-key iconscout "<client_id>:<client_secret>"`, or **Settings → Developer**) and then downloads cost them nothing here.
@@ -2740,23 +3200,72 @@ When a director asks "make me a video", the default sequence is:
2740
3200
 
2741
3201
  Prefer specific templates over primitives when a template exists that already captures the desired production pattern.
2742
3202
 
2743
- ## Content ideas — the angle bank
3203
+ ## Content ideas — frames, awareness stages, and problem angles
2744
3204
 
2745
3205
  Read this when a director says **"give me content ideas"**, "what should I post", "I need 30 videos for the month", "I'm out of ideas", or when a batch run needs N *different* videos instead of N variants of one video.
2746
3206
 
2747
3207
  **This also runs FIRST for a brand-new director, before the cold-start interview.** It needs one line of offer, not an interview; it is offline, free, and keyless; and it hands the director 20+ titled videos in about a minute. That is the easiest win available on turn one, and their reactions to the list ("this one, not that one") are better raw material than anything an interview gets cold. Run it, save `content-ideas.md`, then offer the interview as the way to turn ideas into a strategy — `references/onboarding.md` → *Start with content ideas*.
2748
3208
 
2749
- **What this is.** A fixed bank of **50 content frames**. A frame is a reusable shape for a video's subject not a hook line, not a script. You take the director's topic (their offer, their niche, their product, their audience's world) and pour it into a frame: `the rise of` + `dropshipping supplements` → *"The rise of the supplement dropship store"*. One topic against 50 frames is 50 distinct videos, and they do not read as repeats, because each frame changes what the video is *about*, not just how it opens.
3209
+ **What this is — three banks, not one.** An idea is a point in a small grid, and this reference holds all three axes:
3210
+
3211
+ | Axis | Bank | Question it answers |
3212
+ |---|---|---|
3213
+ | **Subject** | the director's own pool of adjacent topics | *What is this one about, in the niche?* (settling the dinner argument · eating what you actually craved · reading a menu before you commit) |
3214
+ | **Frame** | 50 content frames | *What is the video the story of?* (`the rise of`, `then vs now`, `one decision that changed everything`) |
3215
+ | **Awareness** | 5 stages | *What does the viewer already know?* (unaware → problem-aware → solution-aware → product-aware → most-aware) |
3216
+ | **Angle** | 44 problem angles | *From which side do we talk about the problem?* (the hidden cost, the myth, the confession, the honest downside) |
3217
+
3218
+ A **frame** is a reusable shape for a video's subject — not a hook line, not a script. You pour the director's topic into it: `the rise of` + `dropshipping supplements` → *"The rise of the supplement dropship store"*. An **angle** decides which face of the problem that video shows; the same frame at two angles is two genuinely different videos. An **awareness stage** decides who it is allowed to be for — the same idea aimed at a stranger and at a buyer needs different first ten seconds and a different ask.
3219
+
3220
+ **The grid is where the volume comes from.** 50 frames × 44 angles × 5 stages, over a pool of adjacent subjects, is not a number to take literally, but it is why "I need 30 videos this month" is an easy ask, not a hard one. Vary **two** axes across a set and it never reads as repeats. Vary only one and it does — and the axis most often left frozen is the subject, because the offer line is right there and it is easy to paste.
2750
3221
 
2751
3222
  **How to use it (the loop).**
2752
3223
 
2753
3224
  1. **Get the topic.** In priority order: read the director's **`OFFER.md`** if one exists (see `onboarding.md`); **if they named a URL** — "content ideas for my offer example.com" — **fetch the site and read it** (home page, plus the pricing and about pages when they exist) and pull the offer, the audience, the promise, the objections, and the product vocabulary straight off the page; otherwise ask for the offer, the niche, and the audience in one question. Never generate ideas against a topic you guessed. When you work from a URL, **state the offer you read back in one line before the list** ("Reading example.com: a $49/mo bookkeeping tool for solo trades") so the director can correct it before you produce 20 ideas off a wrong premise — and offer to save that line plus the ideas as `OFFER.md` + `content-ideas.md` in their folder.
2754
- 2. **Pick frames, don't dump the list.** Choose 1020 frames that actually fit the topic and the audience's awareness stage a solution-unaware audience wants `what everyone gets wrong` and `how it works`; a product-aware audience wants `then vs now`, `cheap vs expensive`, `one decision that changed everything`. Say the frame name next to each idea so the director can ask for more of that shape.
2755
- 3. **Write each idea as a title, not a frame.** Output `"The one pricing mistake that killed our first 400 orders"`, not `"one mistake that changed everything about pricing"`. A frame that stays abstract is not an idea yet.
2756
- 4. **Then run it through the hook harness.** A content idea is the *subject*; it is not the four charges. Every idea a director picks still needs hook / loop / payoff / bait written before the timeline — `references/hooks-and-virality.md`. The frames on this list are deliberately curiosity-shaped, which makes the loop easy to name, but never skip that pass.
2757
- 5. **Batch it properly.** If the director wants the whole set produced, that is scripting mode with a `HARNESS.md``recipes/bulk-scripting-with-a-harness.md`. One frame per video, one line in the plan file.
3225
+ 2. **Name the problem in the director's words, once — then write 48 adjacent ways to say it.** Every angle is a lens on *a problem*; if you have not written the problem down in one sentence, the angles all collapse into the same vague video. Take it from `OFFER.md`, from the site's own copy, or ask: *"What is the thing that is going wrong for them right now, in their words?"* That sentence is the *first* entry in a **subject pool**, never the only one see *The subject pool* below. One frozen phrase is what turns 50 frames into 50 versions of one video.
3226
+ 3. **Spread across awareness stages, not just frames.** Most directors post everything at one stage usually product-aware, because that is the stage they live in and then wonder why the account does not grow. Cover the ladder deliberately; the default monthly mix is in *Spreading a month across the ladder* below. Say the stage next to each idea.
3227
+ 4. **Pick frames and angles, don't dump the lists.** Choose 10–20 combinations that actually fit the topic. Label each idea `frame · angle · stage` so the director can say "more like that one" and you know exactly which axis they mean.
3228
+ 5. **Write each idea as a title, not a frame.** Output `"The one pricing mistake that killed our first 400 orders"`, not `"one mistake that changed everything about pricing"`. A frame that stays abstract is not an idea yet.
3229
+ 6. **Then run it through the hook harness.** A content idea is the *subject*; it is not the four charges. Every idea a director picks still needs hook / loop / payoff / bait written before the timeline — `references/hooks-and-virality.md`. The frames on this list are deliberately curiosity-shaped, which makes the loop easy to name, but never skip that pass.
3230
+ 7. **Batch it properly.** If the director wants the whole set produced, that is scripting mode with a `HARNESS.md` — `recipes/bulk-scripting-with-a-harness.md`. One idea per video, one line in the plan file, with its stage and angle recorded so the set stays balanced.
2758
3231
 
2759
- **Give lots when asked.** "Give me content ideas" means volume. Return **20+ titled ideas** by default, grouped by frame family, not three polite suggestions. The director prunes; you supply.
3232
+ **Give lots when asked.** "Give me content ideas" means volume. Return **20+ titled ideas** by default, grouped by frame family or by awareness stage, not three polite suggestions. The director prunes; you supply.
3233
+
3234
+ ### The subject pool — adjacent, not literal
3235
+
3236
+ **The most common defect in a generated list is not a bad frame. It is one frozen phrase.** The offer line goes in verbatim, and every title carries it:
3237
+
3238
+ > The history of deciding where to eat tonight
3239
+ > The rise of deciding where to eat tonight
3240
+ > The future of deciding where to eat tonight
3241
+ > The science of deciding where to eat tonight
3242
+
3243
+ The frame moved four times. The video did not move once. A director reads that list and correctly says it is one idea with four openings.
3244
+
3245
+ **The fix is a pool, not a sentence.** Before you write a single title, write **4–8 adjacent subjects** inside the same niche — different ways the same audience says the same life, from different sides of it:
3246
+
3247
+ | Frozen | Adjacent pool for the same offer |
3248
+ |---|---|
3249
+ | deciding where to eat tonight | settling the food argument · picking a restaurant before you read a single review · the craving you cannot place · eating what you actually wanted · the group chat that never picks · reading a menu before you commit |
3250
+
3251
+ Now the same four frames are four videos:
3252
+
3253
+ - *The history of settling the food argument*
3254
+ - *The rise of picking dinner by review score*
3255
+ - *The future of eating what you actually craved*
3256
+ - *The science of the craving you cannot place*
3257
+
3258
+ **Adjacent means inside the niche, and true.**
3259
+
3260
+ - ✅ **Adjacent:** the same audience, the same day, the same pain seen from another side — the group chat, the diet rule, the menu, the argument, the craving, the five open tabs, the walk to a place that turned out wrong.
3261
+ - ❌ **Off topic:** a different business. "The rise of the restaurant industry" is not this offer's video; "the psychology of ordering the same thing every time" is.
3262
+ - ❌ **A rebrand of the product line.** Swapping adjectives on the offer sentence — *finding where to eat tonight*, *choosing where to eat tonight* — is the frozen phrase wearing a hat. If the subject has not changed, the video has not changed.
3263
+
3264
+ **Where the pool comes from.** The audience's own vocabulary: the objection, the workaround they already tried, the moment before the search, the moment after the wrong choice, the person who is not the buyer but is in the room. `OFFER.md`, the site copy, and real comments are all pools you can read out rather than invent.
3265
+
3266
+ **Do it for each lens.** The subject can sit on the *problem*, on the *category*, or on the *product* — and the pool is per lens, because a frame that claims a past cannot take a new product as its subject. Rotate the pool as you go down the list: no two ideas in a row should repeat the same phrase.
3267
+
3268
+ **One rule to check the finished list.** Read the titles with the frames covered up. If what is left is the same sentence 20 times, you produced one idea, not 20.
2760
3269
 
2761
3270
  ### The 50 frames
2762
3271
 
@@ -2834,6 +3343,175 @@ Read this when a director says **"give me content ideas"**, "what should I post"
2834
3343
  - the complete breakdown
2835
3344
  - the rabbit hole
2836
3345
 
3346
+ ### The awareness ladder — 5 stages
3347
+
3348
+ Eugene Schwartz's ladder, as a production instrument. The stage decides **what the first ten seconds are allowed to assume** and **what the video is allowed to ask for**. An idea is not finished until it has a stage, because the same subject at the wrong stage is a video that talks past the viewer.
3349
+
3350
+ `vidfarm ideas --stages` prints this ladder; `--stage <name|n>` prints one stage.
3351
+
3352
+ **Stage 1 · unaware** — they do not have a name for the problem yet, and they are not looking for one.
3353
+
3354
+ - **Believes:** nothing is wrong; this is just how it is. They are on the app to be entertained.
3355
+ - **Video must:** be interesting on its own merits, then leave one splinter — a situation they recognise from their own week.
3356
+ - **Frames that fit:** the rise of · the psychology of · what nobody noticed · the untold story · one event that changed everything · the rabbit hole
3357
+ - **Angles that fit:** the daily friction · the two kinds of people · the confession · the screen recording · the industry does this on purpose
3358
+ - **Ask:** none. A follow at most. Naming a price here burns the video.
3359
+ - **Never:** open with the problem stated as a problem — they do not agree it is one yet.
3360
+
3361
+ **Stage 2 · problem-aware** — they feel the pain and can describe it, but they think it is unavoidable or their own fault.
3362
+
3363
+ - **Believes:** "this part of my job is just miserable." They blame themselves, their discipline, or bad luck.
3364
+ - **Video must:** articulate the pain better than they can, then move the blame off them and onto a cause.
3365
+ - **Frames that fit:** why it failed · what everyone gets wrong · the biggest mistakes · expectation vs reality · problem vs solution · the chain reaction
3366
+ - **Angles that fit:** the hidden cost · the slow leak · the advice that broke it · the wrong metric · the expensive lesson · the day it broke
3367
+ - **Ask:** a comment or a save. "Which one is you?" works; a link does not.
3368
+ - **Never:** name the product in the first half. They have not accepted that a solution category exists.
3369
+
3370
+ **Stage 3 · solution-aware** — they accept a fix exists somewhere, but not that this *kind* of fix is the one.
3371
+
3372
+ - **Believes:** "someone has solved this, but the options I have seen are junk / too expensive / not for me."
3373
+ - **Video must:** make the category legible and prove the mechanism. This is the explainer stage.
3374
+ - **Frames that fit:** how it works · why it works · myth vs reality · simple vs complicated · cause vs effect · the complete guide
3375
+ - **Angles that fit:** the mechanism · the false solution · the myth · the experiment · what pros do differently · the receipts
3376
+ - **Ask:** "Want the breakdown?" — a comment keyword, a saved post, a free resource.
3377
+ - **Never:** compare to named competitors yet; that is a stage-4 conversation and it reads as defensive here.
3378
+
3379
+ **Stage 4 · product-aware** — they know your product exists, and they are weighing it against alternatives and against doing nothing.
3380
+
3381
+ - **Believes:** "it might work, but not for my situation / not at that price / not worth the switch."
3382
+ - **Video must:** face one specific objection and answer it with evidence, not adjectives.
3383
+ - **Frames that fit:** then vs now · cheap vs expensive · beginner vs expert · best vs worst · one decision that changed everything · theory vs evidence
3384
+ - **Angles that fit:** the price objection · the "it won't work for me" objection · the honest downside · the before/after · the client story · the risk reversal
3385
+ - **Ask:** the direct one. Link, demo, trial, DM keyword.
3386
+ - **Never:** re-explain the problem from scratch. They have heard it; repeating it wastes the hook.
3387
+
3388
+ **Stage 5 · most-aware** — buyers, users, and the people who already like the director.
3389
+
3390
+ - **Believes:** "I'm in. What is new, and what am I missing?"
3391
+ - **Video must:** give a reason to act now, or a use they had not thought of.
3392
+ - **Frames that fit:** what happened next · the complete breakdown · how it changed · the future of · after it disappeared
3393
+ - **Angles that fit:** the window closing · what just changed · the file itself · the process, unedited · the number nobody posts
3394
+ - **Ask:** the offer, plainly, with the deadline or the limit that makes now different from next month.
3395
+ - **Never:** pad it. This audience wants the update, not the setup.
3396
+
3397
+ **Mapping to the `brainstorm/awareness_stages` primitive.** The cloud primitive takes a 2×2 — `problem_awareness` × `solution_awareness` — which collapses this ladder: `problem_unaware + solution_unaware` = stage 1; `problem_aware + solution_unaware` = stage 2; `problem_aware + solution_aware` = stages 3–4; and stage 5 is the customer list, which the primitive does not model. Use the ladder to plan the mix, and the primitive when the director wants generated angles for one specific state (`references/onboarding.md`).
3398
+
3399
+ ### Spreading a month across the ladder
3400
+
3401
+ A month of posts at one stage is the most common failure in a director's calendar, and it looks like "good videos, no growth" (all stage 4) or "big views, no sales" (all stage 1). Default mix for 30 posts, adjusted afterwards for the account's size:
3402
+
3403
+ | Stage | Share of a 30-post month | Why |
3404
+ |---|---|---|
3405
+ | 1 · unaware | 9 (30%) | Reach. This is what brings new people in; it is the only stage that grows the audience. |
3406
+ | 2 · problem-aware | 9 (30%) | The conversion engine of organic. Cheap to make, and it recruits from stage 1. |
3407
+ | 3 · solution-aware | 6 (20%) | The explainer library. Long-lived; these keep working for months. |
3408
+ | 4 · product-aware | 3 (10%) | Objection handling. Also the best paid-ad candidates. |
3409
+ | 5 · most-aware | 3 (10%) | Launches, updates, deadlines. More than this reads as constant selling. |
3410
+
3411
+ `vidfarm ideas --grid --topic "<offer>" --count 30` lays a month out in exactly this mix, and draws each row's angle and frame from the stage's own lists above.
3412
+
3413
+ **Skew it deliberately.** A brand-new account with no audience runs 1 and 2 heavier and can skip 5 entirely. An account with traffic but no sales inverts the top: more 3 and 4. A launch week is allowed to be mostly 4 and 5 for that week only — then go back to the mix.
3414
+
3415
+ ### The problem angles — 44 lenses
3416
+
3417
+ An angle is **which side of the problem the video approaches from**. It is not a hook, not a frame, and not a format. Two videos on the same subject at two angles do not feel like repeats, which is why the angle bank — not the frame bank — is what you reach for when the director says *"I already covered that topic."*
3418
+
3419
+ `vidfarm ideas --angles` prints the bank, `--angle <family or name>` filters it, `--grid --topic "<offer>"` pairs angles with frames.
3420
+
3421
+ **Pain & consequence — what it is costing them**
3422
+
3423
+ - the daily friction — the small annoyance they have stopped noticing, shown in full
3424
+ - the hidden cost — what it silently costs per month, counted in their units, not dollars
3425
+ - the slow leak — nothing breaks; it just bleeds, and the video shows the bleed rate
3426
+ - the worst case — where this ends if nothing changes, played out on one real example
3427
+ - the thing they already tried — name their failed workaround before they can bring it up
3428
+
3429
+ **Enemy & blame — moving the fault off the viewer**
3430
+
3431
+ - the industry does this on purpose — the incentive that keeps the problem alive
3432
+ - the advice that broke it — a popular tip, followed correctly, producing the damage
3433
+ - the middleman — who takes a cut for work the viewer could do or skip
3434
+ - the tool everyone recommends — why the default choice is the wrong one here
3435
+ - the rule nobody questions — an unwritten norm that has no reason behind it
3436
+
3437
+ **Belief & myth — what they are sure of that is not true**
3438
+
3439
+ - the myth — the sentence the niche repeats, taken apart
3440
+ - the false solution — the fix that treats the symptom and hides the cause
3441
+ - the wrong metric — they are optimising the number that does not pay them
3442
+ - the survivor's tale — the success story that is unrepeatable, and why
3443
+ - the advice that expired — true five years ago, wrong now, still repeated
3444
+
3445
+ **Mechanism & proof — why this actually works**
3446
+
3447
+ - the mechanism — the how, drawn out in steps a stranger can follow
3448
+ - the receipts — the numbers on screen, unretouched, with the ugly ones left in
3449
+ - the experiment — a real A/B, including the version that lost
3450
+ - the before/after — same input, two treatments, one frame each
3451
+ - third-party proof — someone with no stake saying it
3452
+
3453
+ **Identity & status — who they become**
3454
+
3455
+ - the two kinds of people — a sorting line the viewer places themselves on
3456
+ - the tell — the small signal that gives an amateur away
3457
+ - the room you get into — what changes socially, not functionally
3458
+ - what pros do differently — the boring habit behind the impressive result
3459
+ - the permission slip — telling them the thing they wanted to stop doing is fine to stop
3460
+
3461
+ **Confession & story — I lived this**
3462
+
3463
+ - the confession — the mistake the director made, named with the number attached
3464
+ - the expensive lesson — what it cost to learn, stated first, before the lesson
3465
+ - the day it broke — one dated incident, told in order
3466
+ - the client story — someone else's arc, with their permission and their words
3467
+ - the comment that started it — a real DM or reply as the cold open
3468
+
3469
+ **Insider & access — you were not supposed to see this**
3470
+
3471
+ - the screen recording — the actual doing, unedited, no narration for the first beat
3472
+ - the number nobody posts — the metric the niche hides
3473
+ - what gets said off-camera — the version without the marketing voice
3474
+ - the file itself — hand over the template, the sheet, the prompt, on screen
3475
+ - the process, unedited — full length, real time, mess included
3476
+
3477
+ **Objection & risk — why they do not buy**
3478
+
3479
+ - the price objection — say the price out loud and defend it with arithmetic
3480
+ - the "it won't work for me" objection — the edge case they think they are
3481
+ - the "I don't have time" objection — the real time cost, measured
3482
+ - the risk reversal — what happens if it fails, and who carries that
3483
+ - the honest downside — who this is genuinely wrong for, named plainly
3484
+
3485
+ **Urgency & change — why now and not later**
3486
+
3487
+ - the window closing — a real deadline, limit, or seasonal edge
3488
+ - what just changed — a new rule, price, platform change, or release
3489
+ - the cost of waiting — the same decision made now vs in six months, priced
3490
+ - the first-mover gap — what the early ones get that the late ones cannot
3491
+
3492
+ ### Frame × angle × stage — the grid
3493
+
3494
+ The grid is the answer to "give me 30 different videos" and to "I already made a video about that."
3495
+
3496
+ 1. Write the problem in one sentence.
3497
+ 2. Pick the **stage** first — it constrains the other two, and it decides the ask.
3498
+ 3. Pick an **angle** that fits that stage (each stage above lists its five).
3499
+ 4. Pick a **frame** that carries the angle (each stage above lists its six).
3500
+ 5. Write the title. If the title does not say the angle out loud, the pairing was wrong — go back to step 3, not step 4.
3501
+
3502
+ Worked example, one topic (`bookkeeping for solo trades`), one frame family, four angles, four different videos:
3503
+
3504
+ | Stage | Angle | Frame | Title |
3505
+ |---|---|---|---|
3506
+ | 1 | the daily friction | the psychology of | *"Why every tradie has a glovebox full of receipts"* |
3507
+ | 2 | the hidden cost | why it failed | *"The £3,400 a year that disappears in your van"* |
3508
+ | 3 | the false solution | myth vs reality | *"A shoebox is not a filing system, and HMRC agrees"* |
3509
+ | 4 | the price objection | cheap vs expensive | *"£49 a month vs the accountant's £900 catch-up bill"* |
3510
+
3511
+ **When a director says "I already covered that."** Hold the frame, change the angle. Same subject, new video, and it is the cheapest idea in the bank to produce because the research is already done.
3512
+
3513
+ **When a set feels repetitive.** Check which axis you froze — and check the **subject** first, because it is the one that hides. Thirty ideas that vary only the frame, on one pasted offer sentence, at one stage and one angle, are thirty versions of one video. Vary two axes minimum, and never let the subject be the constant.
3514
+
2837
3515
  ### Frame → format notes
2838
3516
 
2839
3517
  The frame also suggests how to build it, which saves a planning round:
@@ -2849,10 +3527,14 @@ The frame also suggests how to build it, which saves a planning round:
2849
3527
 
2850
3528
  ### Do not
2851
3529
 
2852
- - **Do not hand back the raw 50-item list as the answer.** The list is your instrument; ideas applied to the director's topic are the deliverable.
2853
- - **Do not stack two frames in one title** ("the untold story of why it failed"). One frame per video, or the video has two subjects and lands neither.
2854
- - **Do not use a frame the topic can't honestly fill.** `the untold story of` a two-week-old product is a lie the audience catches. Pick a frame the facts support.
3530
+ - **Do not paste the offer sentence into every frame.** `<frame> + <the one topic string>`, 50 times, is a template filled in, not a set of ideas. Build the subject pool first and rotate it. If two titles in a row share their whole subject phrase, the second one is a duplicate.
3531
+ - **Do not read the offer so literally that only the product's own words are allowed.** Adjacent subjects inside the niche are the point — the argument, the workaround, the moment before, the person in the room. Off topic is the failure; adjacent is the job.
3532
+ - **Do not hand back a raw bank as the answer.** The three lists are your instrument; ideas applied to the director's topic are the deliverable.
3533
+ - **Do not stack two frames in one title** ("the untold story of why it failed"). One frame per video, or the video has two subjects and lands neither. Two *angles* in one video fail the same way.
3534
+ - **Do not use a frame or an angle the topic can't honestly fill.** `the untold story of` a two-week-old product is a lie the audience catches, and `the receipts` with no receipts is worse. Pick what the facts support.
2855
3535
  - **Do not treat the frame as the hook.** "The history of X" spoken flat at `start:0` is a banned opener shape — the hook still has to name a situation. `references/hooks-and-virality.md`.
3536
+ - **Do not ship a set that sits at one awareness stage.** It is the single most common defect in a month of posts, and neither the frame nor the angle can repair it. Label the stage on every idea so the imbalance is visible before production, not after.
3537
+ - **Do not sell at stage 1 or 2.** The ask belongs to the stage. A link in a stage-1 video costs the reach that made the video worth making.
2856
3538
 
2857
3539
  ## Primitive: image_remove_background
2858
3540
 
@@ -2935,6 +3617,57 @@ vidfarm avatar "friendly 30-something founder in a grey hoodie" \
2935
3617
  vidfarm avatar "cheerful barista in an apron" --say "One flat white, coming up." --local
2936
3618
  ```
2937
3619
 
3620
+ ## Primitives: video-search / image-search / news-search (Google)
3621
+
3622
+ Three synchronous searches that hand you real URLs off the open web. They are the **sourcing front door**: the media catalog answers *"give me a clip of X"*, Google answers *"give me THE shot"* — because it indexes TikTok, YouTube, Pexels/Pixabay/Mixkit, archive.org, and every news site at once.
3623
+
3624
+ | Route | devcli | What it is for |
3625
+ | --- | --- | --- |
3626
+ | `GET\|POST /api/v1/primitives/video-search` | `vidfarm video-search "<query>"` | Find **source footage** → feed `raws scan` / `download-video` |
3627
+ | `GET\|POST /api/v1/primitives/image-search` | `vidfarm image-search "<query>"` | Reference stills, textures, logos, product shots |
3628
+ | `GET\|POST /api/v1/primitives/news-search` | `vidfarm news-search "<query>"` | Recent real events, for **timely** content |
3629
+
3630
+ - **Paid plans only.** They sit behind `requireAuth`, so a free-plan key gets `402 upgrade_required`. Free users get the catalog (`media search`, free) and the public raws shelves instead.
3631
+ - **Flat $0.0003 per CALL**, whatever the result count. So ask for a **wide page once** (`--limit 40`) instead of paging twice. It is billed to the wallet under the `google_search` cost center.
3632
+ - **They return LINKS, never files and never a licence.** A public video is not a licensed video. Check rights before reuse; for licence-checked assets use `media search` (free).
3633
+
3634
+ Parameters (query string on GET, JSON body on POST — same names either way):
3635
+
3636
+ | Param | Applies to | Notes |
3637
+ | --- | --- | --- |
3638
+ | `q` (aliases `query`, `text`) | all | **required** |
3639
+ | `max_results` (alias `limit`) | all | default 25; max 50 for video, 100 for image/news |
3640
+ | `region` | all | `wt-wt` (worldwide, default), `us-en`, `ph-en`, … |
3641
+ | `timelimit` | video, news | freshness: `d` \| `w` \| `m` \| `y` |
3642
+ | `duration`, `resolution` | video | `short\|medium\|long`, `high\|standard` |
3643
+ | `color`, `size`, `type_image`, `layout` | image | `type_image`: `photo\|clipart\|gif\|transparent` |
3644
+ | `safesearch` | video, image | `off` (default) \| `moderate` \| `on` |
3645
+
3646
+ Responses:
3647
+
3648
+ ```jsonc
3649
+ // video-search
3650
+ { "kind": "video", "query": "...", "count": 40, "charged_usd": 0.0003,
3651
+ "results": [{ "title", "url", "description", "duration", "thumbnail",
3652
+ "publisher", "uploader", "published", "embed_url", "view_count" }] }
3653
+ // image-search
3654
+ { "results": [{ "title", "image_url", "thumbnail_url", "source_page", "width", "height", "source" }] }
3655
+ // news-search
3656
+ { "results": [{ "title", "url", "body", "date", "source", "image" }] }
3657
+ ```
3658
+
3659
+ `url` on a video result is the **watch page** — exactly what `POST /raws/scan` takes as `source_url` and what `videos/download` takes to collect the file. That is the whole pipeline:
3660
+
3661
+ ```bash
3662
+ vidfarm video-search "warehouse worker packing orders POV 4K" --limit 40
3663
+ vidfarm raws scan "https://www.youtube.com/watch?v=..." --clips 8 # mine clips out of it
3664
+ vidfarm download-video "https://www.tiktok.com/@x/video/123" # or collect the one file
3665
+ ```
3666
+
3667
+ **How to write the query** — the difference between a useless and a great result is the query, so this is worth the tokens. Full playbook in `references/assets-and-sourcing.md` → *Google search for footage*. In short: search the **shot**, not the topic — `[subject] + [action] + [shot/style] + [quality/orientation]` — and use Google operators (`site:pexels.com/videos`, `site:tiktok.com`, `"exact phrase"`, `-dance`).
3668
+
3669
+ **News finds the STORY, video-search finds the VISUALS.** Run them as two stages; searching for both at once finds neither. The full timely-content method is the standalone prompt at `https://vidfarm.cc/experimental/google-news-to-video.md`.
3670
+
2938
3671
  ## Primitive: videos/download — **Vidfarm downloads videos off websites for you**
2939
3672
 
2940
3673
  **Capability statement (say this plainly when a user asks "can you download this video?"): yes — on a paid plan, Vidfarm downloads a video straight off a website URL for you.** Hand it a YouTube / TikTok / Instagram / X (Twitter) / other supported post URL and it returns a durable Vidfarm-hosted file. No local yt-dlp, no browser extension, no "I can't access that URL." The route is intentionally broader than its old name suggests: it returns either a normal MP4 for video posts, or a slideshow payload for photo/carousel posts.
@@ -3441,7 +4174,7 @@ Use this when a coding agent is doing the work locally or the user wants a repro
3441
4174
  3. Read `./work/.harness/agent-guide.md` and `./work/.harness/context.json` before editing.
3442
4175
  4. Make deterministic edits to `composition.html` and optionally `composition.json`.
3443
4176
  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.
3444
- 6. **QA before you render: `vidfarm qa ./work`.** Free, instant, devcli-only. It blocklists HTML slop (CTA buttons, benefit chip rows, a lone pill around a static stat/label, frosted cards, gradient text, web-page classes/fonts), checks the caption font regime + safe zone, flags oversized captions and static walls of text, and flags a blank/fading first frame (the thumbnail). It cannot see pixels, so *where in the frame* the caption sits is still on you — which is why every run ends with a **`▶ NOW WATCH THE VIDEO`** block: render, `vidfarm stills ./work --sheet`, open the contact sheet, and judge each caption against its actual picture. Do that before you report the video as done. 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.
4177
+ 6. **QA before you render: `vidfarm qa ./work`.** Free, instant, devcli-only. It blocklists HTML slop (CTA buttons, benefit chip rows, a lone pill around a static stat/label, frosted cards, gradient text, web-page classes/fonts) and the frame-level version of it (`layout-template`: a headline + subheadline + CTA stack, `modal-scrim`: a blurred-and-dimmed backdrop staging a floating block), checks the caption font regime + safe zone, flags oversized captions and static walls of text, and flags a blank/fading first frame (the thumbnail). It cannot see pixels, so *where in the frame* the caption sits is still on you — which is why every run ends with a **`▶ NOW WATCH THE VIDEO`** block: render, `vidfarm stills ./work --sheet`, open the contact sheet, and judge each caption against its actual picture. Do that before you report the video as done. 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.
3445
4178
  7. Render with `vidfarm render <forkId> --dir ./work --wait`.
3446
4179
  7b. **Review the render as a whole before you approve — this is the step that most changes quality.** `vidfarm qa` and `lint` are static checks on the DOM; neither can see the video. Tile ~12 stills into one contact sheet and read it as an image — `vidfarm stills ./work --sheet` does both in one command (add `--at 0,2,4,…` to pick the timestamps): consistent margins, one type scale, one accent colour, deliberate pacing, no jarring join, no dead band under top-anchored content, end card settled ≥2s before the last frame. Compare frames from two different scenes — a frozen render (overlay pass without `-loop 1`, assets outside the composition root) passes duration, frame-count and audio-hash checks while every frame is identical. Check the mix by measurement, not by ear. Full method + the six most common defects: `references/reviewing-renders.md`.
3447
4180
  8. **Ask about deduplication before you approve** — "is this going out more than once (several accounts, another platform, a re-post later)?" If yes, run `vidfarm dedupe ./final.mp4 [--variants N]` on the **exported** MP4 (free, local ffmpeg, no re-render) and approve each variant separately. Asking here rather than after publication is what avoids paying for a second render. See `references/core-workflows.md` → *Deduplicate before you publish*.
@@ -3856,7 +4589,7 @@ Use this only when the director signals they do not know where to start.
3856
4589
  1. Read `references/onboarding.md`. Agree on one **working folder** for all of this director's Vidfarm work, and run every command from it.
3857
4590
  2. **Give them content ideas before you ask them anything.** Take the offer in one line (or a URL you read), run `vidfarm ideas --topic "<line>"`, sharpen the frames into 20+ titled videos, and save `content-ideas.md`. Offline, free, keyless. Their reactions to the list are the first real context you get.
3858
4591
  3. Offer the interview as the next step, not as a gate: `vidfarm consult coldstart --short` (six fixed questions) or the full `coldstart`. Say every question is skippable. Capture product context into `OFFER.md` and the durable answers into `CONTEXT.md`, in the working folder and mirrored to the right My Files folder.
3859
- 4. Determine awareness stages, persuasive angles, and hooks with the brainstorm primitives, then revisit `content-ideas.md` now that the awareness stage is known.
4592
+ 4. Determine awareness stages, persuasive angles, and hooks with the brainstorm primitives, then revisit `content-ideas.md` now that the awareness stage is known — re-label each idea with its stage and spread the month across the ladder (`vidfarm ideas --stages`, `vidfarm ideas --grid --topic "<offer>" --count 30`).
3860
4593
  5. Ask about brand assets, demos, and recurring characters; organize them in My Files.
3861
4594
  6. Ask about budget and map it to the cost spectrum before recommending expensive generation.
3862
4595
  - Set the graphics default in the same breath: icons, stickers, illustrations, 3D props and Lottie come from `vidfarm iconscout`, never from an image model. No key, no setup, search is free, free assets are $0.