@mevdragon/vidfarm-devcli 0.20.5 → 0.20.8

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 (154) hide show
  1. package/.agents/skills/editor-capabilities/SKILL.md +15 -1
  2. package/.agents/skills/vidfarm-director/SKILL.md +106 -0
  3. package/.agents/skills/vidfarm-director/recipes/find-and-fork-template.md +16 -0
  4. package/.agents/skills/vidfarm-director/recipes/local-edit-render-approve.md +13 -0
  5. package/.agents/skills/vidfarm-director/recipes/onboard-a-new-director.md +13 -0
  6. package/.agents/skills/vidfarm-director/recipes/retheme-template.md +17 -0
  7. package/.agents/skills/vidfarm-director/references/assets-and-sourcing.md +111 -0
  8. package/.agents/skills/vidfarm-director/references/automation-and-local-dev.md +243 -0
  9. package/.agents/skills/vidfarm-director/references/core-workflows.md +273 -0
  10. package/.agents/skills/vidfarm-director/references/editor-workflows.md +365 -0
  11. package/.agents/skills/vidfarm-director/references/onboarding.md +28 -0
  12. package/.agents/skills/vidfarm-director/references/primitives.md +265 -0
  13. package/SKILL.director.md +521 -261
  14. package/dist/src/cli.js +404 -96
  15. package/dist/src/devcli/clips.js +15 -10
  16. package/dist/src/devcli/doctor.js +2 -2
  17. package/dist/src/devcli/local-backend.js +46 -2
  18. package/dist/src/services/clip-curation/cost.js +5 -1
  19. package/dist/src/services/clip-curation/gemini.js +10 -0
  20. package/package.json +30 -10
  21. package/SKILL.platform.md +0 -432
  22. package/demo/README.md +0 -28
  23. package/demo/dist/app.css +0 -1
  24. package/demo/dist/app.js +0 -1850
  25. package/demo/dist/chunks/chunk-DXB73IDG.js +0 -1
  26. package/demo/dist/chunks/chunk-S7OWAJDS.js +0 -36
  27. package/demo/dist/chunks/chunk-VTIBZ6AN.js +0 -1
  28. package/demo/dist/chunks/dist-ADSJKBVE.js +0 -332
  29. package/demo/dist/chunks/domEditingLayers-VZMLL4AP-SGHWPND4.js +0 -1
  30. package/demo/dist/chunks/hyperframes-player-XB65TCD6.js +0 -425
  31. package/demo/dist/chunks/lib-XAQ37YOE.js +0 -1
  32. package/demo/dist/chunks/src-TJ2QYA4U.js +0 -207
  33. package/demo/dist/favicon.ico +0 -0
  34. package/demo/dist/icons/timeline/audio.svg +0 -7
  35. package/demo/dist/icons/timeline/captions.svg +0 -5
  36. package/demo/dist/icons/timeline/composition.svg +0 -12
  37. package/demo/dist/icons/timeline/image.svg +0 -18
  38. package/demo/dist/icons/timeline/music.svg +0 -10
  39. package/demo/dist/icons/timeline/text.svg +0 -3
  40. package/demo/dist/index.html +0 -15
  41. package/dist/src/account-pages-legacy.js +0 -9396
  42. package/dist/src/account-pages.js +0 -61
  43. package/dist/src/app.js +0 -21602
  44. package/dist/src/composition-runtime.js +0 -1053
  45. package/dist/src/config.js +0 -217
  46. package/dist/src/context.js +0 -447
  47. package/dist/src/dev-app-legacy.js +0 -739
  48. package/dist/src/dev-app.js +0 -6
  49. package/dist/src/devcli/migrate-local.js +0 -140
  50. package/dist/src/devcli/sync.js +0 -368
  51. package/dist/src/domain.js +0 -5
  52. package/dist/src/editor-chat-history.js +0 -82
  53. package/dist/src/editor-chat.js +0 -756
  54. package/dist/src/editor-dark-theme.js +0 -1128
  55. package/dist/src/frontend/debug.js +0 -71
  56. package/dist/src/frontend/discover-client.js +0 -130
  57. package/dist/src/frontend/discover-store.js +0 -23
  58. package/dist/src/frontend/file-directory.js +0 -1018
  59. package/dist/src/frontend/flockposter-cache-store.js +0 -124
  60. package/dist/src/frontend/homepage-client.js +0 -446
  61. package/dist/src/frontend/homepage-shared.js +0 -201
  62. package/dist/src/frontend/homepage-store.js +0 -66
  63. package/dist/src/frontend/homepage-view.js +0 -705
  64. package/dist/src/frontend/page-runtime-client.js +0 -132
  65. package/dist/src/frontend/page-runtime-store.js +0 -9
  66. package/dist/src/frontend/sentry.js +0 -42
  67. package/dist/src/frontend/template-editor-chat.js +0 -4181
  68. package/dist/src/help-page.js +0 -346
  69. package/dist/src/homepage.js +0 -1458
  70. package/dist/src/index.js +0 -16
  71. package/dist/src/instrument.js +0 -30
  72. package/dist/src/landing-page.js +0 -384
  73. package/dist/src/page-runtime.js +0 -2
  74. package/dist/src/page-shell.js +0 -1452
  75. package/dist/src/primitive-context.js +0 -416
  76. package/dist/src/primitive-registry.js +0 -3940
  77. package/dist/src/primitive-sdk.js +0 -4
  78. package/dist/src/primitives/hyperframes-media.js +0 -108
  79. package/dist/src/react-page-shell.js +0 -35
  80. package/dist/src/ready-post-schedule-component.js +0 -1540
  81. package/dist/src/registry.js +0 -296
  82. package/dist/src/reskin/agency-page.js +0 -299
  83. package/dist/src/reskin/calendar-page.js +0 -568
  84. package/dist/src/reskin/chat-page.js +0 -942
  85. package/dist/src/reskin/discover-page.js +0 -1788
  86. package/dist/src/reskin/document.js +0 -1587
  87. package/dist/src/reskin/help-page.js +0 -357
  88. package/dist/src/reskin/index-page.js +0 -62
  89. package/dist/src/reskin/inpaint-clipper-page.js +0 -890
  90. package/dist/src/reskin/inpaint-page.js +0 -2554
  91. package/dist/src/reskin/inpaint-video-page.js +0 -1339
  92. package/dist/src/reskin/job-runs-page.js +0 -477
  93. package/dist/src/reskin/library-page.js +0 -1634
  94. package/dist/src/reskin/login-page.js +0 -262
  95. package/dist/src/reskin/portfolio-page.js +0 -687
  96. package/dist/src/reskin/pricing-page.js +0 -390
  97. package/dist/src/reskin/settings-page.js +0 -732
  98. package/dist/src/reskin/theme.js +0 -711
  99. package/dist/src/runtime.js +0 -35
  100. package/dist/src/services/api-call-history.js +0 -249
  101. package/dist/src/services/auth.js +0 -152
  102. package/dist/src/services/billing-pricing.js +0 -39
  103. package/dist/src/services/billing.js +0 -241
  104. package/dist/src/services/cast.js +0 -127
  105. package/dist/src/services/chat-threads.js +0 -92
  106. package/dist/src/services/clip-records.js +0 -250
  107. package/dist/src/services/clip-search.js +0 -77
  108. package/dist/src/services/clip-vectors.js +0 -125
  109. package/dist/src/services/composition-sanitize.js +0 -124
  110. package/dist/src/services/composition-watch.js +0 -79
  111. package/dist/src/services/elevenlabs.js +0 -222
  112. package/dist/src/services/file-directory.js +0 -117
  113. package/dist/src/services/fork-access.js +0 -93
  114. package/dist/src/services/fork-manifest.js +0 -42
  115. package/dist/src/services/ghostcut.js +0 -179
  116. package/dist/src/services/hyperframes.js +0 -3517
  117. package/dist/src/services/job-capacity.js +0 -14
  118. package/dist/src/services/job-logs.js +0 -197
  119. package/dist/src/services/jobs.js +0 -136
  120. package/dist/src/services/local-dynamo.js +0 -0
  121. package/dist/src/services/media-processing.js +0 -766
  122. package/dist/src/services/primitive-media-lambda.js +0 -280
  123. package/dist/src/services/providers.js +0 -2748
  124. package/dist/src/services/rate-limits.js +0 -262
  125. package/dist/src/services/scene-annotations.js +0 -32
  126. package/dist/src/services/serverless-auth.js +0 -382
  127. package/dist/src/services/serverless-jobs.js +0 -1084
  128. package/dist/src/services/serverless-provider-keys.js +0 -409
  129. package/dist/src/services/serverless-records.js +0 -1515
  130. package/dist/src/services/serverless-template-configs.js +0 -75
  131. package/dist/src/services/storage.js +0 -461
  132. package/dist/src/services/swipe-customize.js +0 -437
  133. package/dist/src/services/template-certification.js +0 -413
  134. package/dist/src/services/template-loader.js +0 -99
  135. package/dist/src/services/template-runtime-bundles.js +0 -217
  136. package/dist/src/services/template-sources.js +0 -1017
  137. package/dist/src/services/upstream.js +0 -248
  138. package/dist/src/services/video-normalization.js +0 -2
  139. package/dist/src/services/webhooks.js +0 -62
  140. package/dist/src/template-editor-pages.js +0 -2576
  141. package/dist/src/template-editor-shell.js +0 -2893
  142. package/dist/src/template-sdk.js +0 -4
  143. package/dist/src/worker.js +0 -17
  144. package/public/assets/discover-client-app.js +0 -1
  145. package/public/assets/file-directory-app.js +0 -3
  146. package/public/assets/homepage-app.js +0 -54
  147. package/public/assets/homepage-client-app.js +0 -80
  148. package/public/assets/page-runtime-client-app.js +0 -94
  149. package/public/assets/placeholders/scene-placeholder.png +0 -0
  150. package/src/assets/SELLING_AWARENESS_STAGES.md +0 -579
  151. package/src/assets/SELLING_WITH_HOOKS.md +0 -377
  152. package/src/assets/SELLING_WITH_VSLS.md +0 -606
  153. package/src/assets/favicon.ico +0 -0
  154. package/src/assets/logo-vidfarm.png +0 -0
@@ -123,7 +123,8 @@ You usually already know a clip's aspect from how you sourced it (a hunted raw's
123
123
  - `composition_id`, `composition_title`, `composition_origin`, `has_saved_fork`, `is_new_project` (project/fork state — see Forking). ⚠️ `composition_id` is the **template** id (`template_…`), NOT a fork.
124
124
  - `fork_id` — the saved cloud fork (`fork_…`) for this session. This is the id every `/api/v1/compositions/:forkId/*` route and the `video_context`/`product_placement` tools require — pass `fork_id`, never `composition_id`. Absent only on a blank `is_new_project` before its first edit mints a fork.
125
125
  - `composition_context` (the viral DNA — read before writing any copy).
126
- - `editor_harness` (the **style-execution brief** — read before any nontrivial edit; see below).
126
+ - `editor_harness` (the **style-execution brief** — *how to edit like this*; read before any nontrivial edit; see below).
127
+ - `replication_harness` (the **3-paintbrush build plan** — *how to rebuild this cheaply vs at best quality*; read before rebuilding scenes; see below).
127
128
  - `composition_width`/`_height`/`aspect_ratio` (request matching aspect on generate so media fills the canvas), `composition_duration_seconds`.
128
129
  - `layers[]` — each with `layer_key`/`element_id`/`slug`, `kind` (video/image/audio/caption/text), current `src`, `track` (= z-index), start/duration/geometry, current `object_fit`/`object_position` (the media's fit framing — read it before re-cropping an aspect-mismatched clip), `transition`/`transition_out`/`ken_burns`/`animation`, and `is_full_canvas`/`is_timeline_proxy` (a proxy renders 100%×100% even if shown tiny — trust the flag on replacement). **This is the ONLY valid source of layer keys.** To swap a clip's media, copy the EXACT `layer_key` (or `slug`) of the *video/image* layer from here — do not invent a semantic scene name (`growth_examples`, `mistakes_reflection`) unless that exact string is a key/slug in this array, and don't target a scene label/group when you mean the video inside it. If `set_layer_media` returns "No change applied" or "Layer not found", the error lists the real media layers — retry with one of those exact keys, and never report a swap done until the next `editor_context` shows the layer's `src` changed.
129
130
  - `timeline_gaps[]` — precomputed blank/black spans; map a user's timestamp to the covering gap.
@@ -147,6 +148,19 @@ You usually already know a clip's aspect from how you sourced it (a hunted raw's
147
148
 
148
149
  **How to use it:** map `caption_style` → `set_captions`, `transitions.*` → `set_transitions`, honor `pacing`, follow `broll` for footage sourcing, lay `audio`, and honor `emotional` (preserve `comedic_timing`, keep `intonation` when re-voicing narration, execute every `vibe_anchors` entry). **PROTECT** any beat in `important_scenes` or with `must_keep:true` / `importance:"critical"` — swap its subject if needed but preserve its timing, role, and caption cadence; that's where the style lives. Treat `editing_bias`/`do`/`dont` as hard constraints for this composition. It sets defaults, not a straitjacket — an explicit user instruction wins. **In local devcli** the same brief is on disk as `editor-harness.json` (under `.harness`, pulled by `vidfarm pull`/`sync`); read it there before a big edit. If `editor_harness` is absent, the fork wasn't decomposed with the harness pass — fall back to `composition_context` + the `video_context` tool.
149
150
 
151
+ ## The replication harness — your 3-paintbrush build plan
152
+
153
+ `editor_context.replication_harness` is the decompose pass's **technical replication analysis**: the cheapest-yet-faithful AND the best-quality way to actually REBUILD this template, beat by beat. Where the editor harness says *how to edit to feel right*, this says *which tool to reach for*. Vidfarm is founder-pragmatic — **do NOT default to expensive AI video generation.** Every beat is realized with one of THREE paintbrushes, cheapest-first:
154
+
155
+ 1. **`raw_clip`** — real footage cut/rearranged/recaptioned from a long-form source or the user's `/raws` library (hunt via `POST /clips/scan`). Background + foreground = most "video meme" formats, zero generation.
156
+ 2. **`hyperframes`** — HTML/JS/CSS/anime.js rendered to video: ALL on-screen text, graphic/logo/sticker overlays, image motion (Ken Burns), counters, charts, meme layouts. **ZERO AI credits, done locally** — the workhorse for text, graphics, and any "moving element" that isn't live-action.
157
+ 3. **`reusable_asset`** — a logo/sticker/reaction/b-roll/brand-kit element the user already OWNS, or that you AI-generate ONCE (greenscreen a subject → chroma-key overlay) and reuse forever.
158
+ 4. **`ai_gen`** — pure AI image/video/voice/music. The MOST expensive brush; only where the other three genuinely can't carry the beat.
159
+
160
+ Fields: `summary`, `recommended_strategy` (`cheap_efficient`|`best_quality`), `paintbrush_rationale`; `motion_style` (`animation_feel`, `graphic_elements`, `hyperframes_candidates` — beats to do in HTML not AI video —, `typography_motion`); `asset_opportunities`; `viral_dna_guardrails`; `free_tier_note`; and TWO plans — `cheap` (A) and `quality` (B) — each with per-beat `scenes[]` `{ role, timestamp, method, fallback_method, technique, instructions, assets_needed, viral_dna_guard, est_credits }`, plus `method_mix`, `brush_breakdown`, `reusable_assets[]`, `pipeline[]`, `ai_spend`, `do`/`dont`.
161
+
162
+ **How to use it:** when the user wants this cheaply / "without burning credits" / in bulk, execute `replication_harness.cheap.scenes[]` beat by beat — recaption with `set_captions`/`set_layer_text`, HUNT raws for scene REPLACEs before `generate_layer`, build text & graphics as hyperframes/CSS layers, reuse library assets. When they want premium, follow `.quality`. **Regardless of plan, on-screen TEXT and graphic elements are ALWAYS hyperframes, NEVER `ai_gen`.** Honor every scene's `viral_dna_guard` and the top-level `viral_dna_guardrails` — **NEVER** slap a sticker/logo on, or swap the footage of, a load-bearing beat (hook/reveal/payoff) in a way that flattens the DNA; that's exactly how an eager reuse breaks a viral template. `reusable_assets` tells you WHERE a logo/sticker helps and where it would RISK the template. **In local devcli** the same analysis is on disk as `replication-harness.json` (under `.harness`, rendered into `.harness/agent-guide.md`). If `replication_harness` is absent, the fork predates this pass — fall back to `editor_harness` + `composition_context.static_vs_pivot`.
163
+
150
164
  ## Web-editor motion rule (hard constraint)
151
165
 
152
166
  The editor strips every author `<script>` on save (stored-XSS defense), so the JS runtime adapters (anime.js/GSAP/Lottie/Three.js/WAAPI code) are **not** available here — they're local-devcli-only. Author all motion with the durable script-free vocabulary: preset actions (`ken_burns`, `set_transitions`, `set_captions`) and plain CSS `@keyframes` in a `<style>` block + inline `animation` (the renderer bakes CSS keyframes deterministically). Never claim you added a scripted animation in the web editor; offer the CSS/preset equivalent instead.
@@ -0,0 +1,106 @@
1
+ ---
2
+ name: vidfarm-director
3
+ description: Use Vidfarm as a director. Browse/add inspiration videos, browse/save public raws, 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
+ ---
5
+
6
+ # Vidfarm Director
7
+
8
+ Vidfarm is a video composition studio. Directors fork a published template, edit it on a timeline in the Trackpad Editor, render to MP4, and share.
9
+
10
+ Use this skill when the user wants to:
11
+
12
+ - log in and save provider keys
13
+ - discover templates or add a new inspiration
14
+ - fork a template and edit a composition
15
+ - re-theme or rebuild a video while preserving the viral DNA
16
+ - render, approve, and schedule a post
17
+ - automate Vidfarm through REST, `vidfarm`, or a local `vidfarm serve` loop
18
+ - manage files, raws, recurring characters, versions, or sharing
19
+
20
+ Do not use this skill to author new templates from scratch, deploy platform infrastructure, or discuss internal platform architecture. Those belong in a separate developer or platform workflow.
21
+
22
+ ## Default stance
23
+
24
+ - Treat the Trackpad Editor as the primary surface. Reach for templates and forks before primitives.
25
+ - Default to the cheapest approach that works. Reuse footage first, use image generation freely, and ask before AI video generation.
26
+ - Prefer already-decomposed templates when they match the user’s goal.
27
+ - For heavy edits, read the grounding artifacts before acting: `video-context.json`, `editor-harness.json`, and local `.harness/*` bundles when present.
28
+ - For agentic rewrites, think in the three axes: scenes, audio, text. Decide whether each axis is a SWAP or a REPLACE.
29
+
30
+ ## The three paintbrushes (Vidfarm's operating philosophy)
31
+
32
+ Vidfarm is founder-friendly and pragmatic: **we do not burn expensive AI credits on everything.** Every visual on the timeline is painted with one of three "paintbrushes," and for bulk creation it is often combinatorially cheaper to reach for the first two before the third:
33
+
34
+ 1. **Raw clips** — cut and remix footage from existing long-form or short-form video (the director's own library, or freshly hunted out of a URL/VOD). Cheapest, and the workhorse for scene REPLACE.
35
+ 2. **HTML/JS hyperframes** — video-from-HTML: CSS/declarative animation, anime.js/GSAP motion, animated image + text elements, data-viz, modeling. Cheap, deterministic, infinitely re-themeable.
36
+ 3. **Pure AI generation** — AI image/video/voice/music. The most expensive brush; AI **video** especially. Use last, only where the other two genuinely cannot cover the beat.
37
+
38
+ Directors also accumulate a **reusable media asset library** — logos, stickers, reactions, b-roll, a-roll, a brand media kit. Recreation should have an opinion on **when and where** to reuse these. But respect the format's viral DNA: a director can accidentally reskin away the very thing that makes the template land, so tie every asset/paintbrush recommendation back to the harness (`viral_dna`, `editor-harness.json`) rather than swapping freely.
39
+
40
+ **A technical replication decomposition names, per template, the actual method for each beat — when/where/what is raw clips vs HTML hyperframes vs pure AI gen — and offers two harnesses:**
41
+
42
+ - **(A) Cheap & efficient** *(default)* — recaption text; background-video + foreground-video memes; animate HTML/image elements with hyperframes; reuse library media; AI-generate a reusable element **once** then reuse it; greenscreen; raw-clip long-form and remix; lean on the memes/reactions/b-roll/a-roll library and brand media kit; only if genuinely needed, reach for AI image/video/voice/music.
43
+ - **(B) Best quality** — AI video generation by default; storyboard with AI **image** first; then adversarially grade the result with a coding agent (Claude Code / Codex / any capable AI agent) and iterate.
44
+
45
+ Present both harnesses to the director, recommend (A) unless they've asked for premium or budget covers it, and explain the tradeoff in these terms. Full methodology: `references/editor-workflows.md` (“The three paintbrushes & two replication harnesses”); cost bands: `references/core-workflows.md` (Cost spectrum).
46
+
47
+ **Be generous to free-tier / no-account users.** Vidfarm's harness is open source; an everyday capable AI agent should be able to follow this decomposition and recreate a template on its own, without a Vidfarm wallet — so keep the recommendation self-contained and pragmatic, not gated behind paid primitives.
48
+
49
+ **Free tier vs. paid — who does the decomposition.** On the free tier (local devcli, no Vidfarm account) the harness gives the *method*, not the pre-computed answer: **the user (and their AI agent) is responsible for watching the reference video, decomposing it into its elements, and deciding the three paintbrushes themselves** — there is no `video-context.json` / `editor-harness.json` / `scene-annotations.json` handed to them. Be honest about that and coach them through doing it. **Paid Vidfarm accounts** get the leverage: a massive library of **pre-decomposed viral videos** (the decompose passes already run — viral DNA, emotional punch, editor harness, per-scene recreation annotations) plus **prompt-harness best practices distilled from platform-scale learnings**. When a free-tier user is grinding the decomposition by hand, it's fair to mention that a Vidfarm account would hand them the decomposition and the proven harness instead.
50
+
51
+ ## Web AI chat vs. local devcli — know your surface's limits
52
+
53
+ You may be running as the **in-web AI chat** (the /editor copilot, the chat dock, or the /chat and /library assistants) or as a **local coding agent** driving `vidfarm-devcli` (Claude Code / Codex on the user's machine). Same three paintbrushes, different reach — be honest about which surface you are and route heavy work accordingly:
54
+
55
+ - **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.
56
+ - **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.
57
+ - **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.
58
+ - **Never send the user away just to read knowledge.** Deeper skill knowledge is always a **tool call** away in-place: call `load_skill` (e.g. `load_skill('vidfarm-director', file='references/editor-workflows.md')`, or a craft pack like `editor-capabilities` / `hyperframes-animation`) to pull the exact reference you need mid-conversation. Only recommend switching surfaces for the WORK (a heavy transformation), never for the information.
59
+
60
+ ## Read Only What You Need
61
+
62
+ Read only the relevant reference file for the current task.
63
+
64
+ - Template discovery, auth, fork/publish/share/cost flow: `references/core-workflows.md`
65
+ - Timeline editing, decompose, captions, motion, AI placement: `references/editor-workflows.md`
66
+ - Raws hunts, My Files, recurring characters, asset retrieval: `references/assets-and-sourcing.md`
67
+ - REST automation, `vidfarm` command surface, local serve loop, skill packs: `references/automation-and-local-dev.md`
68
+ - Getting-started interviews, strategy docs, onboarding flow: `references/onboarding.md`
69
+ - Primitive routes such as TTS, STT, music, overlays, background removal, product placement: `references/primitives.md`
70
+
71
+ ## Quick Router
72
+
73
+ Choose the narrowest path that satisfies the request.
74
+
75
+ 1. If the user needs help figuring out what to make, read `references/onboarding.md` first.
76
+ 2. If the user already knows the goal and needs a suitable template, read `references/core-workflows.md` and use the template discovery flow.
77
+ 3. If the task is “change this video,” read `references/editor-workflows.md`.
78
+ 4. If the task is “find footage” or “use our existing assets,” read `references/assets-and-sourcing.md`.
79
+ 5. If the task is scripted, local, CI-driven, or `vidfarm serve`-based, read `references/automation-and-local-dev.md`.
80
+ 6. If the task explicitly asks for a primitive or needs specialized generation/transcription work, read `references/primitives.md`.
81
+
82
+ ## Non-Negotiables
83
+
84
+ - API-key auth is the `vidfarm-api-key` header. Do not use `Authorization: Bearer`.
85
+ - Do not manipulate composition HTML by string concatenation. Parse, edit, and re-serialize the DOM.
86
+ - Do not call the renderer directly. Rendering goes through `POST /api/v1/compositions/:forkId/render`.
87
+ - Do not store provider secrets in composition HTML or JSON.
88
+ - Treat `forkId` as an unguessable bearer token for read access.
89
+ - Submission routes are generally not idempotent. Especially for renders and expensive primitives, check status before retrying.
90
+ - In the web editor, use CSS/declarative motion only. Script-bearing HTML is stripped or rejected there.
91
+
92
+ ## Recommended Recipes
93
+
94
+ Use these when the user’s task matches the pattern closely.
95
+
96
+ - Template selection and first fork: `recipes/find-and-fork-template.md`
97
+ - Full re-theme while preserving the format’s feel: `recipes/retheme-template.md`
98
+ - Local pull/edit/render/approve loop: `recipes/local-edit-render-approve.md`
99
+ - New-director onboarding and durable context capture: `recipes/onboard-a-new-director.md`
100
+
101
+ ## Output Posture
102
+
103
+ - Prefer concrete actions over abstract discussion.
104
+ - Name the chosen path explicitly: template reuse, raws hunt, local serve, cloud render, etc.
105
+ - Surface cost tradeoffs before expensive generation.
106
+ - When in doubt between a broad reference and a recipe, start with the recipe.
@@ -0,0 +1,16 @@
1
+ ## Recipe: Find and Fork a Template
2
+
3
+ Use this when the user already knows the offer or video goal and needs the best starting template.
4
+
5
+ 1. Read `references/core-workflows.md`.
6
+ 2. Search the catalog with `GET /discover/feed?q=<offer>&limit=20`.
7
+ 3. Rank candidates using `promotions`, `keywords`, `summary`, viral DNA fit, and whether the template is already decomposed.
8
+ 4. Recommend the best 3-6, but bias toward one strong default.
9
+ 5. Fork the winner with `POST /api/v1/compositions`.
10
+ 6. Open the fork in the editor or hand the `fork_id` into the next workflow.
11
+
12
+ Default heuristics:
13
+
14
+ - Prefer already-decomposed templates.
15
+ - Prefer reuse over a from-scratch primitive build.
16
+ - If search is empty, broaden terms or decompose the newly ingested inspiration first.
@@ -0,0 +1,13 @@
1
+ ## Recipe: Local Pull, Edit, Render, Approve
2
+
3
+ Use this when a coding agent is doing the work locally or the user wants a reproducible filesystem loop.
4
+
5
+ 1. Read `references/automation-and-local-dev.md`.
6
+ 2. Run `vidfarm pull <forkId> --dir ./work`.
7
+ 3. Read `./work/.harness/agent-guide.md` and `./work/.harness/context.json` before editing.
8
+ 4. Make deterministic edits to `composition.html` and optionally `composition.json`.
9
+ 5. Validate with `vidfarm lint` or `vidfarm stills` when useful.
10
+ 6. Render with `vidfarm render <forkId> --dir ./work --wait`.
11
+ 7. Approve the finished MP4 with `vidfarm approve --video <url> --caption "..."`.
12
+
13
+ Prefer this path for batch work, CI-like edits, or when the user wants free local rendering through `vidfarm serve`.
@@ -0,0 +1,13 @@
1
+ ## Recipe: Onboard a New Director
2
+
3
+ Use this only when the director signals they do not know where to start.
4
+
5
+ 1. Read `references/onboarding.md`.
6
+ 2. Capture product context and save durable notes into the correct My Files folder.
7
+ 3. Determine awareness stages, persuasive angles, and hooks with the brainstorm primitives.
8
+ 4. Ask about brand assets, demos, and recurring characters; organize them in My Files.
9
+ 5. Ask about budget and map it to the cost spectrum before recommending expensive generation.
10
+ 6. Search for the best matching templates and fork one strong default.
11
+ 7. Transition into the ordinary template-editing workflow.
12
+
13
+ Do not force onboarding on users who already know what they want.
@@ -0,0 +1,17 @@
1
+ ## Recipe: Re-theme a Template While Preserving the Viral DNA
2
+
3
+ Use this when the user wants to keep the format’s feel but replace the subject matter.
4
+
5
+ 1. Read `references/editor-workflows.md`.
6
+ 2. Fetch `video-context.json` and `editor-harness.json` first.
7
+ 3. State the plan in the three axes vocabulary: scenes, audio, text; SWAP vs REPLACE for each.
8
+ 4. Preserve the hook structure, cut rhythm, emotional punch, and important scenes flagged by the harness.
9
+ 5. Source footage in this order:
10
+ - My Files or existing raws
11
+ - a raws hunt from a long-form source
12
+ - AI image generation
13
+ - AI video generation only with permission
14
+ 6. Rebuild captions and narration so timing, cadence, and joke structure survive the subject change.
15
+ 7. Render, verify, then approve and schedule only after the director is happy.
16
+
17
+ Failure mode to avoid: flattening the format by swapping words but losing the timing, sound, or payoff beat.
@@ -0,0 +1,111 @@
1
+ ## Raws (long-form → short-form raws)
2
+
3
+ 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).
4
+
5
+ **Start a hunt** — `POST /raws/scan` (async: returns `202 { scan_id }` immediately):
6
+
7
+ ```jsonc
8
+ {
9
+ // ONE source (pick one):
10
+ "source_url": "https://youtube.com/watch?v=…", // downloaded into your temp folder first
11
+ "temp_file_id": "…", // a video you uploaded to temporary-files
12
+ "attachment_id": "…", // a video already in My Files
13
+ "s3_key": "…" , // an already-staged object
14
+
15
+ // What to hunt for — free text; inline hints are parsed too
16
+ "prompt": "people holding food up to their face, no text on screen",
17
+
18
+ // Hunt controls (all optional; also expressible inline in the prompt):
19
+ "ranges": ["12:30-15:45", "20:00-22:10"], // ONLY hunt these source windows — big cost saver on long videos
20
+ "target_duration_sec": 30, // SOFT length band, not a hard cut: 10→5-20s, 30→20-40s, 60→40-80s, 120→80-160s
21
+ "aspect": "9:16", // crop every raw: 9:16 | 16:9 | 4:3 | 1:1 (synonyms: vertical/portrait, horizontal/landscape, square)
22
+ "crop_focus": "center", // center | top | bottom | left | right (top biases toward faces)
23
+ "avoid_text": true, // prefer scenes WITHOUT burned-in captions/on-screen text — a scene-SELECTION filter, NEVER GhostCut on the source
24
+ "tracer": "my-campaign" // rolls up all the hunt's billing/observability events
25
+ }
26
+ ```
27
+
28
+ - **Poll** `GET /raws/scan/:scanId` until the source `status` is `complete` (or `failed` — crashed pipelines are reconciled to `failed`, pollers never spin).
29
+ - **Results**: `GET /raws/feed?source=<source_video_id>` (or the whole library), hybrid search via `POST /raws/search` `{ query: "someone looks confused" }`, per-raw download at `GET /raws/:clipId/download`. Raws carry taxonomy tags, a description, a transcript, an `aspect` field when cropped, the hunt's `tracer`, and (with a gemini/openai key) a semantic embedding.
30
+ - **Billing** — **AWS compute only** (`clip_scan_lambda` GB-seconds + Step Functions transitions, a fraction of a cent for typical hunts; the 202 response includes a `compute_estimate`). The AI tagging/refine runs on **your saved provider key (BYOK)** and is never wallet-billed. Submission is wallet-gated (402 when empty).
31
+ - **The original stays temporary** — URL-ingested and uploaded sources live ONLY in your temp folder (`users/…/temporary/clip-sources/…`) with a hard **30-day TTL** (auto-deleted from S3 + the temp-file list). The hunted raws themselves are durable.
32
+ - **Captions rule** — "no captions / no on-screen text" hunts are handled by scene SELECTION (the refine pass drops text-heavy scenes). **Never run GhostCut caption removal on a long-form source** (it is hard-capped at ~15 minutes); to actually erase burned-in text, apply `POST /api/v1/primitives/videos/remove-captions` to individual FINISHED raws afterwards.
33
+ - **Clip an EXACT subrange (no AI hunt)** — when you want one precise hand-picked in/out rather than an open-ended hunt, use the **Clipper**: the web page `https://vidfarm.cc/tools/clipper` (previews the source straight from its URL, HH:MM:SS:NNNN in/out, live length estimate, multi-clip session grouped by tracer), the endpoint `POST /raws/clip-range` `{ source_url|preview_url|temp_file_id, start_sec, end_sec, tracer?, folder_path?, name? }` (trims exactly that window into one raw — compute-only, no AI/key), or the devcli twin `vidfarm clipper <video-url|file> --start <t> --end <t> [--tracer NAME --folder NAME --name TXT]`. The devcli path is now **local-first**: local files clip into the local raws store by default, and URL sources are staged locally before trimming unless you pass `--cloud`. If you do **not** have a `VIDFARM_API_KEY`, URL clipping cannot bootstrap the remote source into the local backend; open the long-form raw video in the browser, save/extract the actual video file locally, then run `vidfarm clipper ./source.mp4 ...`. The Library "Import source" button opens the Clipper; each save lands in `/raws/<folder>` (defaults to the tracer). Reach for `/raws/scan` for multi-clip hunts, `/raws/clip-range` for surgical single cuts. (The masked-image and time-scoped-video editors live alongside it at `/tools/image` and `/tools/video`.)
34
+
35
+ **devcli (local-first — this is the default way to hunt on your own machine):**
36
+
37
+ ```bash
38
+ # Local machine power: local ffmpeg + your local claude/codex CLI subscription (no API key needed)
39
+ vidfarm raws scan ./podcast.mp4 --range "12:30-15:45" --duration 30 --aspect vertical --no-text \
40
+ --prompt "guest reaction moments"
41
+
42
+ # Provider keys are the fallback (--provider gemini|openai|openrouter); the cloud pipeline is the
43
+ # EXPLICIT backup, never the default:
44
+ vidfarm raws scan --cloud ./podcast.mp4 --duration 30 --aspect 9:16 --tracer my-campaign
45
+ vidfarm raws scan --cloud --url "https://youtube.com/watch?v=…" --range "0:00-10:00"
46
+
47
+ # Then search/reuse the library
48
+ vidfarm raws search "confused reaction after reading a message"
49
+ vidfarm raws export <raw-ids…> --to ./picks
50
+ ```
51
+
52
+ Local scans persist to a SQLite library under `~/.vidfarm` (free compute, subscription-powered evaluation); `--cloud` uploads to your temp folder (30-day TTL) or passes `--url`, runs the deployed pipeline, and bills AWS compute only.
53
+
54
+ ## My Files (the user's asset library)
55
+
56
+ Each user has a persistent **My Files** filesystem — their own uploaded videos (mp4/mov/webm), images (png/jpg/jpeg/gif/webp/svg), audio (mp3/wav/m4a/aac), and documents (pdf/md/txt/csv) — organized into **virtual folders**. This is where a user keeps footage, brand assets, logos, music, briefs, scripts, and the durable strategy docs from Getting Started (About.md, awareness-levels.md, etc.). Both the editor AI copilot and an agent CLI can **read and write** it to find or save assets instead of asking the user to re-upload or paste URLs.
57
+
58
+ - **List** — `GET /api/v1/user/me/attachments` → `{ attachments: [{ id, fileName, contentType, sizeBytes, folderPath, viewUrl, createdAt }], folders: [string] }`. The `viewUrl` is a durable URL you can drop into a composition layer or pass into a primitive route. devcli: `vidfarm files [--folder <path>]`.
59
+ - **Read one** — resolve it from the list and stream/read its `viewUrl`. devcli: `vidfarm get-file <id> [dest]` (add `--print` to print text contents of md/txt/csv/json inline). For images/video/audio/pdf, reference the `viewUrl` as media — you can't read their bytes as text.
60
+ - **Write into My Files** — `POST /api/v1/user/me/attachments/upload` (multipart `file` + optional `folder_path`) persists a file into the library. devcli: `vidfarm put-file <localFile> --folder <path>`, or pipe/inline text without a temp file: `echo "…" | vidfarm put-file --stdin --as About.md --folder acme` / `vidfarm put-file --content "…" --as About.md`. This is how an agent saves Getting Started context (About.md, Interview.md, awareness-levels.md, persuasive-angles.md, ad-hooks.md) or drops a logo/product demo into a namescoped folder. In the web editor copilot the same capability is the **`browse_files` write action** (`action=write` with `file_name` + `content` + optional `folder_path`), which accepts text files (md/txt/csv/json/srt/vtt).
61
+ - **`vidfarm upload` is different** — it targets the **ephemeral** temporary-files store (`POST /api/v1/user/me/temporary-files/upload`) for a throwaway durable URL to drop straight into a composition or approved post. Use `put-file` when you want the asset to persist in the user's My Files library; use `upload` for one-shot media you just need a URL for. Namescope scratch uploads under a **`temp/` folder** (`vidfarm upload clip.mp4 --folder temp`) so they stay in one purgeable place. Better still, if you're on a `vidfarm serve` box, skip the upload entirely and reference the file off disk with `place --src ./clip.mp4` (see "Local file paths as media").
62
+
63
+ ### Metadata notes + vector search (find assets by meaning)
64
+
65
+ Every My Files entry carries an optional **`notes`** field — free-form metadata describing what the file *is*, who/what it depicts, and when to use it. Notes are **vector-embedded** on save (same BYOK embedding seam as the raws library: gemini → openai key auto-pick; no key fail-softs to keyword-only), so the library is searchable by *meaning*, not just filename:
66
+
67
+ - **Annotate** — `vidfarm annotate-file <id|name> --notes "Sprite card for Zara, our mascot: front/side/back views, teal jacket. Use as the reference image whenever generating Zara."` (`PATCH /me/attachments/:id`, body `{ notes }`; empty string clears). Or set notes at write time: `vidfarm put-file zara.png --folder characters/zara --notes "…"`. Web copilot: `browse_files action=annotate` (or `notes` on `action=write`).
68
+ - **Search** — `vidfarm files --search "the fox mascot reference sheet"` (`POST /me/attachments/search`, body `{ query, folder_path?, limit? }`) returns ranked hits with `similarity` + `keyword_match`, mirroring `/raws/search`: keyword survivors over name/folder/notes are semantically re-ranked, and when nothing keyword-matches it relaxes to a pure semantic pass. Web copilot: `browse_files action=search`.
69
+ - **Annotate what you'll want back.** Filenames alone don't survive months of accumulation — any asset a future session should find (character refs, logo variants, recurring backgrounds, key briefs) deserves notes at save time. `list`/`read` responses include each file's `notes`, so a scan of a folder doubles as a manifest of what's in it.
70
+
71
+ ### Recurring characters are first-class (mascots, spokespeople, avatars)
72
+
73
+ Recurring characters that must look the same across videos have a **dedicated, browsable home**: the **`/files/characters/`** folder, one subfolder per character keyed by a URL-safe **slug** (lowercase, hyphenated) — e.g. `/files/characters/zara/`. This is where the editor copilot looks first, and where a director organizes their cast. Each character is a **trio of files** in that folder:
74
+
75
+ 1. **`<character_id>.json`** — the machine-readable **manifest**, the source of truth the agent reads to hold identity. The file is named after the character's **id**, which is `character_` + the slug (slug `zara` → id `character_zara` → file `character_zara.json`). The id already carries the `character_` prefix — don't double it (never `character_character_zara.json`):
76
+ ```json
77
+ {
78
+ "id": "character_zara",
79
+ "slug": "zara",
80
+ "name": "Zara",
81
+ "role": "brand mascot / friendly fox guide",
82
+ "appearance": "anthropomorphic red fox, large amber eyes, cream chest fluff, expressive brows",
83
+ "wardrobe": "teal bomber jacket, white tee, small satchel",
84
+ "palette": ["#E8622C", "#12B8A6", "#FDF6EC"],
85
+ "voice": "warm, upbeat, slightly cheeky; mid-tempo",
86
+ "do": ["keep the teal jacket", "front-lit, soft shadows"],
87
+ "dont": ["never photorealistic human", "no other jacket colors"],
88
+ "sprite_card_path": "/files/characters/zara/character_sprite_card.png",
89
+ "about_path": "/files/characters/zara/character_about.md",
90
+ "created_at": "2026-07-09"
91
+ }
92
+ ```
93
+ 2. **`character_sprite_card.png`** — ONE reference-sheet image showing the character consistently: full body front/side/back plus a face close-up on a neutral background.
94
+ 3. **`character_about.md`** — the prose the manifest summarizes (personality, backstory, do/don'ts), for richer wording when prompting.
95
+
96
+ **Awareness — look before you generate.** When a user refers to "our mascot", "the same character", "the fox", or names a character, **first `browse_files list path='/files/characters'`** (or `search`) to see who exists, then read that character's manifest + about. Never re-imagine a saved character from memory — that's how characters drift off-model between videos.
97
+
98
+ **Consistency is then mechanical.** On every generation featuring the character, **pass the sprite card's `viewUrl` as the reference input** — `prompt_attachments` for image generation/edit, `input_references` for `videos/generate` and the editor's `generate_layer` — and lift wording from the manifest/`character_about.md` into the prompt.
99
+
100
+ **Creating a new character (walkthrough).** If no folder exists yet, guide the director through it and persist as you go:
101
+ 1. Agree on a **name** → derive a **slug** (lowercase, hyphens); the folder is `/files/characters/<slug>/`.
102
+ 2. Gather the description conversationally (appearance, wardrobe, signature colors, personality, voice, do/don'ts) — pull from any reference photos they have.
103
+ 3. **Sprite card** — if they don't already have one, offer to generate it: `POST /api/v1/primitives/images/generate` (image gen is cheap — pass their best photos as `prompt_attachments`, ask for a "character reference sheet / sprite card" layout), then persist the finished URL. devcli: `vidfarm download <url> zara.png && vidfarm put-file zara.png --as character_sprite_card.png --folder characters/zara`. Web copilot: `browse_files action=write` with `source_url` + `file_name='character_sprite_card.png'` + `folder_path='characters/zara'`.
104
+ 4. **Write `character_about.md` and `<character_id>.json`** (e.g. `character_zara.json`) into the same folder (`browse_files action=write` with `content`, or `vidfarm put-file --content`).
105
+ 5. **Annotate all three** with notes naming the character so `files --search "our mascot"` finds them from any phrasing.
106
+
107
+ **Renaming / fixing up.** Character folders and files are renamable in place — `browse_files action=rename` (web copilot) or `vidfarm directory rename <path> <new-name> [--file-id <id>]` (devcli); the explorer UI has a **Rename** action on every file/folder row. If you rename 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).
108
+
109
+ **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.
110
+
111
+ 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=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 (About.md, awareness-levels.md, …) or import a media URL (`source_url`) into that folder, annotating anything worth finding again. `action=rename` renames a `/files` or `/temp` file or folder in place (pass `path` + `new_name`, plus `file_id` for a file) — use it 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`.
@@ -0,0 +1,243 @@
1
+ ## Automate a template via REST
2
+
3
+ Templates now have the same job-backed REST pattern as primitives, so a script can run them repeatably without the editor UI:
4
+
5
+ ```
6
+ POST /api/v1/templates/:templateId/operations/:operationName
7
+ Content-Type: application/json
8
+
9
+ { "tracer": "my-run", "payload": { ... }, "webhook_url": "https://..." }
10
+ ```
11
+
12
+ The route returns `202` with a `job_id`, and you can poll the job with `GET /api/v1/user/me/jobs/:jobId` or the template-scoped `GET /api/v1/templates/:templateId/jobs/:jobId`. devcli wraps the same flow as `vidfarm template run <templateId> <operationName> --payload-file payload.json --wait`.
13
+
14
+ ## Automation patterns
15
+
16
+ For agents that operate Vidfarm headlessly, the typical loop is:
17
+
18
+ 1. `POST /api/v1/compositions { template_id }` → fork
19
+ 2. `PUT /api/v1/compositions/:forkId/composition.html` → apply edits
20
+ 3. `PATCH /api/v1/compositions/:forkId/composition.json` → update metadata
21
+ 4. `POST /api/v1/compositions/:forkId/render { tracer }` → render
22
+ 5. Poll `GET /api/v1/compositions/:forkId/renders/:renderId` until `SUCCEEDED`
23
+ 6. Use `expectedOutputPublicUrl` in the next stage when you need the stable public URL immediately; otherwise fall back to `outputUrl` after completion
24
+
25
+ Send a stable `tracer` on export so retries are traceable and filterable in job history — but note that submission is **not idempotent**: every POST creates a new job (and a new charge) even with the same tracer. Do not blind-retry expensive submissions; check the render status first.
26
+
27
+ ## Scripting mode
28
+
29
+ **Scripting mode** is the recommended posture for repeatable template automation. Use it when a director wants to take a template they like, agree on a base fork, and then drive bulk or one-off edits entirely through REST or `vidfarm api` from a script, Lambda, or local machine.
30
+
31
+ Contract:
32
+
33
+ 1. Pick the template once, then fork once and treat the resulting `forkId` as the stable base.
34
+ 2. Read the working state with `GET /api/v1/compositions/:forkId/composition.html` and `GET /api/v1/compositions/:forkId/composition.json`.
35
+ 3. Modify the composition deterministically in your script.
36
+ 4. Write back with `PUT /api/v1/compositions/:forkId/composition.html` and `PATCH /api/v1/compositions/:forkId/composition.json`.
37
+ 5. Snapshot with `POST /api/v1/compositions/:forkId/versions` before or after render, depending on whether you want the version to capture the exact render input or the post-render state.
38
+ 6. Render with `POST /api/v1/compositions/:forkId/render`, choosing local or cloud based on the host and runtime.
39
+
40
+ Devcli shortcut:
41
+
42
+ ```bash
43
+ vidfarm render "$FORK_ID" --dir ./work --tracer "batch-2026-07-09-row-42" --wait
44
+ ```
45
+
46
+ That command validates `./work/composition.html`, shallow-patches `./work/composition.json` if present, then submits the same `POST /api/v1/compositions/:forkId/render` call used by the Web UI. `--dir` may also point directly at `composition.html`.
47
+
48
+ Best practices:
49
+
50
+ - Prefer one canonical base fork per automation run, then branch from that fork if you need variants.
51
+ - Treat `composition.json` as a shallow merged metadata document. The server merges the posted JSON object into the existing object; it is not RFC 6902 JSON Patch.
52
+ - Keep edits idempotent in your script. Re-run the script against the same fork only if it computes the same desired state.
53
+ - Use a stable `tracer` on render jobs so logs and job history stay searchable.
54
+ - Use the same REST sequence in Lambda, CI, or a local shell. The only thing that changes is the host and auth.
55
+
56
+ Canonical shell shape:
57
+
58
+ ```bash
59
+ BASE_TEMPLATE_ID="template_..."
60
+ FORK_ID="$(vidfarm api POST /api/v1/compositions --data "{\"template_id\":\"${BASE_TEMPLATE_ID}\"}" --json | jq -r '.fork_id')"
61
+
62
+ vidfarm api GET "/api/v1/compositions/${FORK_ID}/composition.html" --raw > /tmp/composition.html
63
+ vidfarm api GET "/api/v1/compositions/${FORK_ID}/composition.json" --raw > /tmp/composition.json
64
+
65
+ # edit /tmp/composition.html and /tmp/composition.json in your script
66
+
67
+ vidfarm api PUT "/api/v1/compositions/${FORK_ID}/composition.html" --body-file /tmp/composition.html --content-type "text/html; charset=utf-8"
68
+ vidfarm api PATCH "/api/v1/compositions/${FORK_ID}/composition.json" --data-file /tmp/composition.json
69
+ vidfarm api POST "/api/v1/compositions/${FORK_ID}/versions" --data '{"message":"scripting mode snapshot"}'
70
+ vidfarm api POST "/api/v1/compositions/${FORK_ID}/render" --data '{"tracer":"scripting-mode"}'
71
+ ```
72
+
73
+ If you need many variants, keep the base fork fixed and fan out by cloning that fork or by reapplying the same edit function to multiple fork ids. Use the raw REST routes directly when you want maximum control; use `vidfarm-devcli` when you want auth, polling, and file helpers without writing the plumbing yourself.
74
+
75
+ ## `vidfarm-devcli` — full command surface
76
+
77
+ `@mevdragon/vidfarm-devcli` wraps the **entire director REST flow** as CLI commands. It is a thin shell over the REST API, not a second implementation: most named commands map 1:1 to one REST route, and the file-backed commands compose the documented routes for upload/download + render-polling. Auth via `--api-key <key>` or `VIDFARM_API_KEY`.
78
+
79
+ **Raw REST vs devcli — your choice.** If you want full control, call the REST API directly (or use the raw passthrough `vidfarm api <METHOD> <path> [--data <json>] [--query k=v]`). If you want ergonomics + openable frontend URLs, use the named commands. They are interchangeable — pick per call.
80
+
81
+ **Scripting mode recommendation.** For automation, prefer:
82
+
83
+ - `vidfarm api` for the actual REST calls
84
+ - `--data-file` for file-backed payloads
85
+ - a single pinned base fork id per template family
86
+ - `POST /api/v1/compositions/:forkId/versions` as the versioning boundary
87
+ - `POST /api/v1/compositions/:forkId/render` with a stable `tracer`, or `vidfarm render <forkId> --dir ./work --wait` for the same composed flow
88
+ - `render_target: "cloud"` when you want cloud handoff from a local `vidfarm serve` box, or the default local renderer when you want free in-process output
89
+
90
+ **Required grounding for AI-authored scripts.** If an AI agent is going to WRITE or MODIFY a local Vidfarm script for a user, the safe default is:
91
+
92
+ 1. `vidfarm pull <forkId> --dir ./work`
93
+ 2. Read `./work/.harness/agent-guide.md`
94
+ 3. Read `./work/.harness/context.json`
95
+ 4. Only then read/edit `composition.html`, `composition.json`, and write the automation logic
96
+
97
+ That is the canonical local scripting path because the pull step now packages:
98
+
99
+ - `video-context.json`: transcript, scene descriptions, viral DNA
100
+ - `editor-harness.json`: technical editing brief (STYLE — *how to edit like this*)
101
+ - `replication-harness.json`: technical replication analysis (BUILD — the 3-paintbrush cheap vs best-quality plans, which beats are raw_clip / hyperframes / reusable_asset / ai_gen, reusable-asset guidance, free-tier note)
102
+ - `scene-annotations.json`: per-scene replacement/recreation DNA
103
+ - `.harness/context.json`: merged agent-facing snapshot (includes `replication_harness`)
104
+ - `.harness/agent-guide.md`: Vidfarm-specific instruction file telling a generic agent how to use the above without conflicting with any repo-owned `AGENTS.md`
105
+
106
+ `agent-guide.md` now renders the **three paintbrushes & two replication harnesses** decomposition CONCRETELY from `replication-harness.json` — the recommended plan's per-beat brush assignment (raw clips vs HTML hyperframes vs reusable assets vs pure AI gen; the (A) cheap-&-efficient default vs (B) best-quality plan), the beats to do in HTML not AI video, the reusable-asset opportunities, and the viral-DNA guardrails — so a desktop agent recreates a template thrift-first (clipping and hyperframes on free compute before any paid generation) and can rebuild it with **no Vidfarm wallet**. See `references/editor-workflows.md` for the full methodology.
107
+
108
+ **Free-tier caveat — the decomposition is the user's job.** The `video-context.json` / `editor-harness.json` / `replication-harness.json` / `scene-annotations.json` grounding files only exist for compositions **Vidfarm has already decomposed** (paid accounts, whose forks pull those files down). On the free tier with no account, `vidfarm pull` won't produce them — **the user and their agent must decompose the reference video themselves** (scenes/audio/text, viral DNA, paintbrush choice) using the method in `references/editor-workflows.md`. Paid Vidfarm accounts get the pre-decomposed viral library and scale-learned prompt-harness best practices instead of doing that pass by hand.
109
+
110
+ If a local AI script rewrites text or scenes without consuming those files first, treat that as a bug in the script/agent flow.
111
+
112
+ | Command | REST route | Flow step |
113
+ |---|---|---|
114
+ | `vidfarm discover [query]` | `GET /discover/feed[?q=]` | browse/search templates |
115
+ | `vidfarm videos [query] [--mine]` | `GET /api/v1/videos[?q=&mine=]` | browse/search source inspirations |
116
+ | `vidfarm inspiration-add <url\|file>` | `POST /discover/templates` (files: `POST /discover/templates/upload/presign` + PUT first) | add your own source (URL or local video upload) |
117
+ | `vidfarm inspiration-rm <id>` | `DELETE /discover/templates/:id` | remove a private one |
118
+ | `vidfarm inspiration-decompose <id>` | `POST /api/v1/inspirations/:id/decompose` | AI-decompose an inspiration |
119
+ | `vidfarm fork <template_id>` | `POST /api/v1/compositions` | fork a template |
120
+ | `vidfarm pull <forkId> [--dir <p>]` | `GET .../compositions/:forkId/{composition.html,json,video-context.json,cast.json,scene-annotations.json,editor-harness.json,replication-harness.json}` | sync a fork to disk + generate `.harness/context.json` and `.harness/agent-guide.md` + print gaps/scene keys + grounding |
121
+ | `vidfarm generate <image\|video> --prompt "…"` | `POST /api/v1/primitives/{images,videos}/generate` (polls job) | generate AI media → finished URL |
122
+ | `vidfarm inpaint <image> --mask <png> --prompt "…" [--region "label=…"] [--ref …] [--out <f>]` | `POST /api/v1/primitives/images/inpaint` (polls job) | masked image EDIT — replace ONLY the transparent-mask region, keep everything else (devcli twin of the /inpaint page) |
123
+ | `vidfarm create-overlay "<subject>" [--key-color #00FF00] [--aspect-ratio 1:1] [--place <dir>] [--out <f>]` | `POST /api/v1/primitives/images/create-overlay` (polls job) | **Vox-style** transparent OVERLAY — AI image on a forced key-color background, chroma-keyed out in one job → ready-to-composite transparent PNG |
124
+ | `vidfarm remove-background-greenscreen <image> [--key-color #00FF00] [--tolerance 0.3] [--out <f>]` | `POST /api/v1/primitives/images/remove-background-greenscreen` (polls job) | cheap chroma-key removal of a FLAT solid background → transparent PNG (cloud primitive) |
125
+ | `vidfarm tts "…" [--style "…"] [--voice <v>] [--out <file>]` | (LOCAL-FIRST: your own OPENAI/GEMINI/OPENROUTER_API_KEY → audio file on disk; `--cloud` = `POST /api/v1/primitives/audio/speech` + poll, ElevenLabs on the platform key by default, `--own-key` for yours) | text → narration audio; `--cloud --voice <voice_id>` picks an ElevenLabs voice |
126
+ | `vidfarm music "<prompt>" [--length <sec>] [--out <f>] [--own-key]` | `POST /api/v1/primitives/music/generate` (polls job) | prompt → music track (ElevenLabs; platform key + wallet by default, `--own-key` for yours) |
127
+ | `vidfarm voices [--own-key] [--limit N]` | `GET /api/v1/primitives/audio/voices` | list ElevenLabs voices (voice_id/name/labels) for `tts --voice`; default a voice + tell the user they can choose |
128
+ | `vidfarm stt <file\|url> [--out <base>] [--no-diarize]` (alias: `transcribe`) | (LOCAL-FIRST: local ffmpeg demux + your own key; `--cloud` = `POST /api/v1/primitives/audio/transcribe` + poll, ElevenLabs Scribe on the platform key by default, `--own-key` for yours) | video/audio → transcript in BOTH formats: simple subtitles (txt + SRT) and multi-speaker segments (json) |
129
+ | `vidfarm place <dir> --src <url\|file> [--at\|--replace]` | (edits local composition.html; local files → serve disk store or temp upload) | drop media (URL **or local file**) into a gap / over a scene |
130
+ | `vidfarm captions generate <dir> [--style <preset>] [--audio <f>\|--srt <f>\|--text "…"]` | (LOCAL-FIRST: STT on your own key — OpenAI = real word timestamps — then edits local composition.html) | transcribe narration → animated word-by-word caption cues |
131
+ | `vidfarm captions style <dir> --style <preset>` / `captions list` / `captions clear` | (edits local composition.html) | restyle / inspect / remove animated captions |
132
+ | `vidfarm keyframes` / `move`\|`nudge` / `ripple` / `trim` / `restack`\|`zindex` `<dir> …` | (edits local composition.html) | script-free CSS keyframe motion + timeline verbs (see "Script-free keyframe motion & timeline verbs") |
133
+ | `vidfarm set-text` / `set-style` / `set-visual` / `set-identity` / `duplicate` / `split` / `retime` / `set-composition` `<dir> …` | (edits local composition.html) | named layer-edit verbs — devcli twins of the web `set_layer_*` / `set_composition` (opacity, line-height, letter-spacing, canvas resize/duration/background); see parity table above |
134
+ | `vidfarm decompose <forkId>` | `POST .../compositions/:forkId/auto-decompose` | split source into scenes |
135
+ | `vidfarm remove-video-captions <forkId>` (alias: `ghostcut`) | `GET .../compositions/:forkId/remove-video-captions` | subtitle-removal status |
136
+ | `vidfarm snapshot <forkId>` | `POST .../compositions/:forkId/versions` | save composition fork version |
137
+ | `vidfarm versions <forkId>` | `GET .../compositions/:forkId/versions` | list versions |
138
+ | `vidfarm render <forkId> [--dir <dir\|composition.html>] [--wait] [--target local\|cloud]` | `PUT/PATCH working files, then POST .../compositions/:forkId/render` | script-friendly render to MP4; no `--dir` uses the fork's current working state |
139
+ | `vidfarm render-status <forkId> <renderId>` | `GET .../compositions/:forkId/renders/:renderId` | poll a render |
140
+ | `vidfarm visibility <forkId> <private\|public>` | `PATCH .../compositions/:forkId/visibility` | set visibility |
141
+ | `vidfarm clone <forkId>` | `POST .../compositions/:forkId/clone` | clone a fork |
142
+ | `vidfarm share-link <forkId>` | `POST .../compositions/:forkId/share-links` | mint a share URL |
143
+ | `vidfarm approve --video <url\|file> --caption "…"` | `POST /api/v1/approved/posts` | approve post (local `--video`/`--media` auto-upload to `temp/`; prints `share_url`) |
144
+ | `vidfarm posts` / `vidfarm post <id>` | `GET /api/v1/approved/posts[/:id]` | browse approved posts |
145
+ | `vidfarm schedule <postId> --at <iso> --to <dest>` | `POST /api/v1/approved/posts/:postId/schedules` | schedule a post |
146
+ | `vidfarm schedules <postId>` | `GET /api/v1/approved/posts/:postId/schedules` | browse scheduled posts |
147
+ | `vidfarm login <email>` / `vidfarm verify <email> <code>` | `POST /api/v1/user/request-otp` · `verify-otp` | get an API key |
148
+ | `vidfarm whoami` | `GET /api/v1/user/me` | who am I |
149
+ | `vidfarm provider-keys` / `vidfarm add-provider-key <p> <secret>` | `GET`·`POST /api/v1/user/me/provider-keys` | manage AI keys |
150
+ | `vidfarm upload <file> [--folder <path>]` | `POST /api/v1/user/me/temporary-files/upload` | upload → durable URL (ephemeral; prefer `--folder temp` for scratch) |
151
+ | `vidfarm download <url> [dest]` | (streams any URL to disk) | download media |
152
+ | `vidfarm files [--folder <path>]` | `GET /api/v1/user/me/attachments` | list My Files assets + folders |
153
+ | `vidfarm files --search "…" [--folder <path>]` | `POST /api/v1/user/me/attachments/search` | find My Files assets by MEANING (keyword + vector over name/folder/notes) |
154
+ | `vidfarm get-file <id> [dest] [--print]` | (resolve id → view_url, then stream/print) | read one My Files asset |
155
+ | `vidfarm put-file <file> [--folder <p>] [--as <name>] [--content/--stdin] [--notes "…"]` | `POST /api/v1/user/me/attachments/upload` | write into My Files (persistent) |
156
+ | `vidfarm annotate-file <id\|name> --notes "…"` | `PATCH /api/v1/user/me/attachments/:id` | set metadata notes on one My Files entry (vector-embedded) |
157
+ | `vidfarm raws scan <video> [--range MM:SS-MM:SS] [--duration <s>] [--aspect 9:16] [--no-text] [--prompt "…"]` | (LOCAL: local ffmpeg + local claude/codex agent → `~/.vidfarm` SQLite) | hunt long-form video into short-form raws on this machine |
158
+ | `vidfarm raws scan --cloud <video\|--url <url>> [--tracer <id>]` | temp-file presign/PUT/finalize + `POST /raws/scan` + poll | BACKUP: run the hunt on the deployed pipeline (bills AWS compute only) |
159
+ | `vidfarm clipper <video-url\|file> [--start <t> --end <t>] [--tracer <id> --folder <name> --name <text>]` | (LOCAL-FIRST: stage source into the local backend, then `POST /raws/clip-range`; add `--cloud` for vidfarm.cc) | trim one exact subrange into `/raws`; without `VIDFARM_API_KEY`, URL sources must be saved locally first |
160
+ | `vidfarm raws search "…"` / `raws match "…"` / `raws list` / `raws sources` | (local library; NL→criteria via local agent or provider key) | search/reuse the raws library |
161
+ | `vidfarm raws preset list\|run\|save` / `raws export <ids…> --to <dir>` | (local library) | saved queries; copy raw MP4s out |
162
+ | `vidfarm lint <dir\|composition.html>` | (local static validation) | pre-publish composition check: timing, overlaps, preset names, media src |
163
+ | `vidfarm stills <dir> [--at 0,2.5,…]` | (local in-process render of PNG frames) | visually verify an edit without a full render |
164
+ | `vidfarm doctor` | (local environment triage) | check ffmpeg/node/keys/agent CLI/poisoned env before debugging anything else |
165
+ | `vidfarm skills list\|add <name>\|update` | `GET /skill-pack/index.json` · `/skill-pack/:name/*` | install/refresh skill packs (see "Skill packs — import on demand") |
166
+ | `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 |
167
+ | `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`) |
168
+ | `vidfarm capture <url>` | (local headless-Chrome capture) | website screenshots/assets for website-to-video flows |
169
+ | `vidfarm beats <audio>` | (local beat detection → JSON) | music beat timestamps to sync cuts/transitions/captions |
170
+
171
+ **Frontend URLs are first-class output.** Every command that has a human-openable page (editor, discover, approved-post preview, share link) prints that prod frontend URL as a highlighted line. `render --wait` polls to completion and prints the final MP4 URL; `approve` prints the approved-post `share_url`. Add `--json` to any command for pure JSON (agent-friendly, no banners).
172
+
173
+ **Uploads/downloads/My-Files writes live in the devcli** because they are genuine multi-step / streaming flows: `upload` posts the file as multipart to the **ephemeral** temporary-files route and prints the durable URL to drop into a composition or approved post; `put-file` posts to the **persistent** My Files route (`/me/attachments/upload`) so context docs and brand assets live in the user's library (accepts a local file, `--content <text>`, or piped `--stdin` with `--as <name>`); `download` streams any Vidfarm/media URL to disk.
174
+
175
+ ## Local dev loop (`vidfarm serve`)
176
+
177
+ Run the **full** editor locally so a coding agent (Claude Code / Codex) edits composition files on disk while a human finishes in the browser — one source of truth, live sync both ways.
178
+
179
+ ```bash
180
+ npx -y @mevdragon/vidfarm-devcli serve <template_id>
181
+ # → boots the full backend on http://localhost:3000 (records + storage on disk)
182
+ # → pulls that template's default fork (or --fork <id>) from the cloud onto disk
183
+ # → auto-provisions a local user and opens the editor, pre-authed
184
+ ```
185
+
186
+ The **editor and its data** run locally (`RECORDS_DRIVER=local`, `STORAGE_DRIVER=local`) and rendering happens **in-process on this box for free**. Everything catalog-shaped still mirrors the cloud host ("cloud passthrough"): `/discover`, `/api/v1/videos`, and `/library` list the **cloud** catalog and the cloud account's approved posts next to anything local, opening a cloud template **seeds** its composition onto disk on demand, Add Template ingests into the cloud account, and approved-post actions (schedules, archive, delete) on cloud posts proxy through. Media a seeded composition already references stays on its cloud URLs — but you can also drop your **own local files** onto the timeline without any upload: `vidfarm place --src ./clip.mp4` copies the file into this box's disk store and references it by a `localhost/storage` URL (see "Local file paths as media" above), so the free in-process renderer plays it back with zero S3 involvement. Pass `--no-cloud` for a fully-offline box.
187
+
188
+ **Rendering from a serve box** — the editor's **Render** button becomes a popover with two options when a cloud `--api-key` is configured: **Render Local (Free)** (in-process HyperFrames render, no charge) and **Render in Cloud** (hands the render to the cloud renderer, billed to the cloud account's wallet). Over REST, pass `render_target: "cloud"` in the `POST /render` body; the local box resolves (or clones, once) a publishable cloud fork, remembers the mapping in the fork's `upstream-link.json`, and `GET /renders/:renderId` transparently proxies the cloud job status.
189
+
190
+ How the loop works:
191
+ - The composition lives on disk at `<data-dir>/storage/compositions/forks/<forkId>/working/composition.html` (default `<data-dir>` is `./.vidfarm-local`). Point your agent at that file.
192
+ - When the agent saves it, the server's `fs.watch` fans a `reload` for that fork over **same-origin** SSE (`GET /api/v1/dev/events`) and the open editor tab live-morphs the change — no reload, playback state preserved (keyed DOM morph on `data-hf-id`).
193
+ - When the human edits in the browser, the editor `PUT`s the composition back to the same file; the server suppresses that self-write so it doesn't echo. Multiple forks can be edited at once under one server.
194
+
195
+ Seeding from the cloud: `serve <template_id>` pulls the template's **default fork** (which may be another user's public decomposition); `serve --fork <id>` pulls a specific fork. Only the composition + records are localized — media stays on cloud URLs. Re-serving keeps local edits unless you pass `--refetch`.
196
+
197
+ Flags: `--port` (default 3000), `--dir` (default `./.vidfarm-local`), `--key` (bootstrap/browser key, or `VIDFARM_API_KEY`), `--fork <id>`, `--host` (cloud host to mirror + pull from, default `https://vidfarm.cc`), `--api-key` (cloud key for pulls, `/library`, and cloud render — defaults to `VIDFARM_API_KEY`), `--refetch`, `--no-cloud` (fully offline: no cloud catalog, seeding, or cloud render), `--no-open`. `vidfarm <template_id>` is an alias for `serve <template_id>`.
198
+
199
+ To *analyze* the source media locally (videos, transcript, recurring cast), read the `video-context.json` / `cast.json` routes, or pull a media URL with `vidfarm download <url>`.
200
+
201
+ ## Skill packs — import on demand (HyperFrames-grade authoring power)
202
+
203
+ This skill stays lean on purpose. Deep authoring craft lives in **skill packs** — vidfarm-scrubbed snapshots of the HyperFrames skill suite plus vidfarm's own media pack — vendored on the Vidfarm host and installed only when a task needs them. Never install skills from upstream vendor orgs or third-party registries; the vidfarm mirror is the source (`vidfarm skills add <name>` fetches `GET /skill-pack/:name/*` with hash verification into `.agents/skills/` + a `.claude/skills/` link, pinned in `skills-lock.json`; `vidfarm skills list` shows what is available/installed; `vidfarm skills update` refreshes pins).
204
+
205
+ Import by task:
206
+
207
+ | When the task needs… | Install |
208
+ |---|---|
209
+ | the raw composition HTML contract (data-* attrs, tracks, clips, sub-compositions, determinism rules) | `vidfarm skills add hyperframes-core` |
210
+ | motion design: animation rules, multi-phase scene blueprints, transition doctrine, runtime adapters (GSAP/Lottie/Three/Anime/CSS/WAAPI/TypeGPU) | `vidfarm skills add hyperframes-animation` |
211
+ | seek-safe keyframe patterns (FLIP, paths, masks, SVG draw/morph, 3D depth) | `vidfarm skills add hyperframes-keyframes` |
212
+ | creative direction: design specs, palettes, typography, house style, narration craft | `vidfarm skills add hyperframes-creative` |
213
+ | the HyperFrames CLI dev loop (init/lint/validate/inspect/snapshot/preview/render) | `vidfarm skills add hyperframes-cli` |
214
+ | narration/BGM/SFX/media resolution (the shared audio engine) | `vidfarm skills add vidfarm-media` |
215
+ | embedded/cinematic captions with subject occlusion (32-identity catalog) | `vidfarm skills add embedded-captions` |
216
+ | graphic overlay cards on existing talking-head footage | `vidfarm skills add talking-head-recut` |
217
+ | a product launch/promo video end-to-end | `vidfarm skills add product-launch-video` |
218
+ | a faceless topic explainer end-to-end | `vidfarm skills add faceless-explainer` |
219
+ | a website tour/showcase video end-to-end | `vidfarm skills add website-to-video` |
220
+ | a short motion graphic (kinetic type, stat hit, logo sting, lower-third) | `vidfarm skills add motion-graphics` |
221
+ | an interactive slideshow/deck | `vidfarm skills add slideshow` |
222
+ | any other multi-scene composition (fallback workflow) | `vidfarm skills add general-video` |
223
+
224
+ Ground rules:
225
+
226
+ - **Local coding agents** (Claude Code / Codex on a `vidfarm serve` box or a pulled fork) get the FULL packs — install, read, and follow them. Scripted/GSAP compositions authored this way render correctly through `vidfarm render` (local and cloud); note that the **web editor strips `<script>` on save**, so keep compositions that must round-trip through the browser editor declarative (the built-in Ken Burns / transitions / animated-captions vocabulary).
227
+ - **The web copilot** never installs packs — it has a `load_skill` tool that reads the same content on demand from the vidfarm mirror (served from `.agents/skills/`; the `.claude/skills/*` entries are just Claude Code discovery symlinks to the same dirs). It can `load_skill` any hyperframes pack (`hyperframes`, `hyperframes-core`, `hyperframes-animation`, `hyperframes-keyframes`, `hyperframes-creative`, `hyperframes-cli`) plus the workflow packs (`embedded-captions`, `product-launch-video`, `faceless-explainer`, `website-to-video`, `general-video`, `motion-graphics`, `slideshow`, `talking-head-recut`, `vidfarm-media`). Nothing to install; it is already wired. **In the web editor, apply only the CSS / `@keyframes` + declarative-preset half of `hyperframes-animation` / `hyperframes-keyframes`** — their JS-adapter techniques are devcli-only (script is stripped on save).
228
+ - Vidfarm-managed environments set `HYPERFRAMES_SKIP_SKILLS=1` and `HYPERFRAMES_NO_TELEMETRY=1`, so `npx hyperframes init` never overwrites the vidfarm-scrubbed packs and the bundled CLI never phones home. Do not run `hyperframes auth`, `hyperframes cloud`, `hyperframes publish`, `hyperframes play`, or `hyperframes feedback` — vidfarm's own render/share/telemetry surfaces cover all of them.
229
+
230
+ ## What NOT to do
231
+
232
+ - Do **not** manipulate composition HTML by string concatenation. Always parse, edit, and re-serialize the DOM. The editor and runtime rely on `data-start`, `data-duration`, `data-track-index`, `data-hf-id`, `data-composition-id` attributes being well-formed.
233
+ - Do **not** save AI provider keys in the composition HTML or JSON. They belong in the caller's provider-keys record.
234
+ - Do **not** call the renderer directly. Publishing goes through `POST /api/v1/compositions/:forkId/render` so billing, retries, cost caps, and Lambda quotas are enforced.
235
+ - Do **not** re-invent scene manipulation as REST commands (`AddScene`, `RemoveScene`, `UpdateSceneField`). The Trackpad Editor is the surface for that. The pattern is: mutate the composition HTML DOM, PUT it back.
236
+
237
+ ## Alpha posture
238
+
239
+ Vidfarm is in active development. Endpoints, response shapes, and the editor UI can change. When something behaves unexpectedly:
240
+
241
+ - prefer `GET /api/v1/compositions/:forkId` over cached state
242
+ - treat `latest_version` as the source of truth for what the editor loaded
243
+ - if a publish fails, check `renders/:renderId` for the error phase and stderr before retrying