@vibeframe/cli 0.113.28 → 0.113.30

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.
package/dist/index.js CHANGED
@@ -6557,6 +6557,19 @@ function notFoundError(path2) {
6557
6557
  function generalError(msg, suggestion) {
6558
6558
  return { success: false, error: msg, code: "ERROR", exitCode: 1 /* GENERAL */, suggestion, retryable: false };
6559
6559
  }
6560
+ function costCapError(opts) {
6561
+ return {
6562
+ success: false,
6563
+ error: `Estimated cost $${opts.estimatedCostUsd.toFixed(2)} exceeds --max-cost $${opts.maxCostUsd.toFixed(2)}.`,
6564
+ code: "COST_CAP_EXCEEDED",
6565
+ exitCode: 1 /* GENERAL */,
6566
+ suggestion: "Raise --max-cost or reduce the stage/provider scope.",
6567
+ retryWith: opts.retryWith,
6568
+ recoverable: true,
6569
+ retryable: false,
6570
+ data: opts.data
6571
+ };
6572
+ }
6560
6573
  function exitWithError(err) {
6561
6574
  if (isJsonMode()) {
6562
6575
  console.error(JSON.stringify({
@@ -6571,6 +6584,9 @@ function exitWithError(err) {
6571
6584
  if (err.suggestion) {
6572
6585
  console.error(source_default.dim(` ${err.suggestion}`));
6573
6586
  }
6587
+ if (err.retryWith && err.retryWith.length > 0) {
6588
+ console.error(source_default.dim(` Retry: ${err.retryWith[0]}`));
6589
+ }
6574
6590
  console.error();
6575
6591
  }
6576
6592
  process.exit(err.exitCode);
@@ -26882,12 +26898,12 @@ colors:
26882
26898
  ---
26883
26899
 
26884
26900
  `;
26885
- const intro = style ? `Visual identity for **${name}**, scaffolded from the **${style.name}** style (after ${style.designer}). Customise freely \u2014 this file is the single source of truth for every scene's palette, typography, and motion.` : `Visual identity for **${name}**. Fill the sections below before authoring any scene HTML or generating any backdrop. Pick a named style with \`vibe scene list-styles\` if you want a credible starting point.`;
26886
- const moodLine = style ? `**Mood:** ${style.mood} \xB7 **Best for:** ${style.bestFor}` : `**Mood:** _(one line \u2014 what should the viewer FEEL?)_`;
26901
+ const intro = style ? `Visual identity for **${name}**, scaffolded from the **${style.name}** style (after ${style.designer}). Customise freely - this file is the single source of truth for every scene's palette, typography, and motion.` : `Visual identity for **${name}**. Fill the sections below before authoring any scene HTML or generating any backdrop. Pick a named style with \`vibe scene list-styles\` if you want a credible starting point.`;
26902
+ const moodLine = style ? `**Mood:** ${style.mood} \xB7 **Best for:** ${style.bestFor}` : `**Mood:** _(one line - what should the viewer FEEL?)_`;
26887
26903
  const palette = style ? `${style.palette.map((c) => `- \`${c}\``).join("\n")}
26888
26904
 
26889
- ${style.paletteNotes}` : `- _hex_ \u2014 primary
26890
- - _hex_ \u2014 accent
26905
+ ${style.paletteNotes}` : `- _hex_ - primary
26906
+ - _hex_ - accent
26891
26907
 
26892
26908
  _2\u20133 colours max. Declare explicit hex values; never name colours abstractly._`;
26893
26909
  const typography = style ? style.typography : `_One family, two weights. State the role of each (headline / label / body)._`;
@@ -26901,7 +26917,7 @@ _2\u20133 colours max. Declare explicit hex values; never name colours abstractl
26901
26917
  const avoid = style ? style.avoid.map((a) => `- ${a}`).join("\n") : `- _anti-pattern 1_
26902
26918
  - _anti-pattern 2_
26903
26919
  - _anti-pattern 3_`;
26904
- return `${frontmatter}# ${name} \u2014 Design
26920
+ return `${frontmatter}# ${name} - Design
26905
26921
 
26906
26922
  > **Hard-gate (BUILD flow only).** This file is the visual contract for
26907
26923
  > the scene-project flow (\`vibe build\`, \`vibe scene ...\`, composition
@@ -26945,12 +26961,12 @@ ${avoid}
26945
26961
  ---
26946
26962
 
26947
26963
  _Browse other named styles: \`vibe scene list-styles\`_
26948
- ${style ? `_This file was seeded by \`vibe scene init --visual-style "${style.name}"\`._` : `_Seed this file from a named style: \`vibe scene init <dir> --visual-style "<name>"\`._`}
26964
+ ${style ? `_This file was seeded by \`vibe init --visual-style "${style.name}"\`._` : `_Seed this file from a named style: \`vibe init <dir> --visual-style "<name>"\`._`}
26949
26965
  `;
26950
26966
  }
26951
26967
  function buildScriptMd(name, kind = DEFAULT_SCENE_KIND) {
26952
- const intent = kind === "product" ? "Product walkthrough \u2014 what each section demonstrates, in order." : kind === "motion" ? "Motion piece \u2014 the message and the beats of on-screen text/graphics." : kind === "aivideo" ? "AI-video script \u2014 the spoken/voiced narrative the generated shots illustrate." : "Narrative script \u2014 scene-by-scene story, dialogue, and voiceover.";
26953
- return `# ${name} \u2014 Script
26968
+ const intent = kind === "product" ? "Product walkthrough - what each section demonstrates, in order." : kind === "motion" ? "Motion piece - the message and the beats of on-screen text/graphics." : kind === "aivideo" ? "AI-video script - the spoken/voiced narrative the generated shots illustrate." : "Narrative script - scene-by-scene story, dialogue, and voiceover.";
26969
+ return `# ${name} - Script
26954
26970
 
26955
26971
  > **Authoring order:** SCRIPT.md (this file) \u2192 STORYBOARD.md (beats + cues)${kindHasCast(kind) ? " \u2192 CHARACTERS.md (cast bible)" : ""}.
26956
26972
  > ${intent}
@@ -26978,7 +26994,7 @@ Voiceover / on-screen: \u2026
26978
26994
  `;
26979
26995
  }
26980
26996
  function buildCharactersMd(name) {
26981
- return `# ${name} \u2014 Characters
26997
+ return `# ${name} - Characters
26982
26998
 
26983
26999
  > Each character is referenced from STORYBOARD beats via the \`characters:\` cue.
26984
27000
  > The reference sheet + identity block keep keyframes and image-to-video on-model
@@ -26987,8 +27003,8 @@ function buildCharactersMd(name) {
26987
27003
  ## hero
26988
27004
 
26989
27005
  - **Reference sheet:** \`assets/characters/hero.png\` (a clean, front-lit full-body
26990
- or portrait sheet \u2014 the identity anchor for keyframe edits).
26991
- - **Identity:** one paragraph of fixed, on-model traits \u2014 age, build, hair,
27006
+ or portrait sheet - the identity anchor for keyframe edits).
27007
+ - **Identity:** one paragraph of fixed, on-model traits - age, build, hair,
26992
27008
  wardrobe, palette. Keep this stable across every beat.
26993
27009
  - **Range:** expressions / poses this character should hit.
26994
27010
 
@@ -27006,14 +27022,14 @@ tts: auto
27006
27022
  imageProvider: openai
27007
27023
  ---
27008
27024
 
27009
- # ${name} \u2014 Storyboard
27025
+ # ${name} - Storyboard
27010
27026
 
27011
27027
  Edit these beats before running \`vibe build\`. Each beat starts with
27012
27028
  YAML cues that drive narration, backdrop generation, and timing.
27013
27029
  Pacing: keep beats 6-15 seconds (split longer ones); a 90s video should
27014
27030
  have 6-8 beats, not 3 long ones.
27015
27031
 
27016
- ## Beat hook \u2014 Hook
27032
+ ## Beat hook - Hook
27017
27033
 
27018
27034
  \`\`\`yaml
27019
27035
  narration: "Introduce the promise in one crisp sentence."
@@ -27024,7 +27040,7 @@ duration: 4
27024
27040
  Show the core visual identity immediately. Keep copy short enough for one
27025
27041
  screen and one spoken breath.
27026
27042
 
27027
- ## Beat proof \u2014 Proof
27043
+ ## Beat proof - Proof
27028
27044
 
27029
27045
  \`\`\`yaml
27030
27046
  narration: "Show the mechanism or proof point that makes the promise believable."
@@ -27035,7 +27051,7 @@ duration: 4
27035
27051
  Use this beat for the concrete differentiator: command, workflow, metric, or
27036
27052
  before/after.
27037
27053
 
27038
- ## Beat close \u2014 Close
27054
+ ## Beat close - Close
27039
27055
 
27040
27056
  \`\`\`yaml
27041
27057
  narration: "Close with the action the viewer should remember."
@@ -27048,7 +27064,7 @@ final beat.
27048
27064
  `;
27049
27065
  }
27050
27066
  function buildProjectAgentsMd(name) {
27051
- return `# ${name} \u2014 Scene Authoring Project
27067
+ return `# ${name} - Scene Authoring Project
27052
27068
 
27053
27069
  This is the canonical cross-agent guidance file for this scene project.
27054
27070
  Claude Code imports it through \`CLAUDE.md\`; Codex, Cursor, Aider,
@@ -27087,10 +27103,10 @@ contradict DESIGN.md are rejected by the Hyperframes \`hyperframes\`
27087
27103
  skill.
27088
27104
 
27089
27105
  Single-asset requests (\`vibe generate image|video|speech|...\`) do NOT
27090
- consult this file \u2014 run the generate command directly.
27106
+ consult this file - run the generate command directly.
27091
27107
 
27092
27108
  Browse named styles: \`vibe scene list-styles\`. Re-seed from one with
27093
- \`vibe scene init . --visual-style "Swiss Pulse"\` (idempotent).
27109
+ \`vibe init . --visual-style "Swiss Pulse"\` (idempotent).
27094
27110
 
27095
27111
  ## Brief and local media
27096
27112
 
@@ -27102,8 +27118,9 @@ after init, those two files are the working source of truth.
27102
27118
  Use \`media/\` for user-provided source files: product photos, screenshots,
27103
27119
  logos, B-roll, recorded narration, or reference clips. Keep those inputs
27104
27120
  inside this project so build references stay project-relative. Do not put user
27105
- media in \`references/\`; that directory is reserved for local composition
27106
- rules installed by VibeFrame.
27121
+ media in \`references/\`; older VibeFrame versions vendored composition rules
27122
+ there, and current installs keep the rules under \`.agents/skills/hyperframes/\`
27123
+ via \`vibe scene install-skill\`.
27107
27124
 
27108
27125
  When a beat should reuse a local file, reference it from \`STORYBOARD.md\`
27109
27126
  with a project-relative path:
@@ -27159,7 +27176,7 @@ project-level agent loop; it provides \`--json\` commands, dry runs, cost caps,
27159
27176
  \`requiresConfirmation\`, \`fixOwner\`, deterministic repair, and render
27160
27177
  inspection for the host agent to reason over.
27161
27178
 
27162
- Copy-paste agent prompts \u2014 plain prompts, not a built-in command:
27179
+ Copy-paste agent prompts - plain prompts, not a built-in command:
27163
27180
 
27164
27181
  \`\`\`text
27165
27182
  Build this VibeFrame project into renders/final.mp4. Use --json for every
@@ -27187,9 +27204,9 @@ target duration/aspect ratio, clean render inspection, any AI review score >= 90
27187
27204
  no unresolved unacknowledged host-agent issues.
27188
27205
  \`\`\`
27189
27206
 
27190
- ## Skills \u2014 USE THESE FIRST
27207
+ ## Skills - USE THESE FIRST
27191
27208
 
27192
- **Load the \`hyperframes\` skill before authoring scenes** \u2014 it encodes the
27209
+ **Load the \`hyperframes\` skill before authoring scenes** - it encodes the
27193
27210
  composition rules, motion principles, type system, and visual-identity gate.
27194
27211
  If your agent has it installed globally it is already available; otherwise run
27195
27212
  \`vibe scene install-skill\`, which runs upstream's installer and writes
@@ -27201,7 +27218,7 @@ semantics, VibeFrame pipeline conventions) that are NOT in generic web docs.
27201
27218
 
27202
27219
  | Skill | Command | When to use |
27203
27220
  | ----------------- | ---------------- | ------------------------------------------------------------------------------------- |
27204
- | **hyperframes** | \`/hyperframes\` | Cinematic-quality composition \u2014 DESIGN.md hard-gate, named styles, motion principles |
27221
+ | **hyperframes** | \`/hyperframes\` | Cinematic-quality composition - DESIGN.md hard-gate, named styles, motion principles |
27205
27222
  | **vibe-scene** | \`/vibe-scene\` | VibeFrame's authoring loop, AI assets, lint feedback, pipeline integration |
27206
27223
  | **gsap** | \`/gsap\` | GSAP tweens, timelines, easing |
27207
27224
 
@@ -27212,22 +27229,22 @@ npx skills add heygen-com/hyperframes
27212
27229
  \`\`\`
27213
27230
 
27214
27231
  Restart your agent session (or reload the skill list) after installing.
27215
- If skills aren't available, follow the **Key Rules** below \u2014 they cover
27232
+ If skills aren't available, follow the **Key Rules** below - they cover
27216
27233
  the framework-level minimum, not the cinematic craft layer.
27217
27234
 
27218
27235
  ## Project structure
27219
27236
 
27220
- - \`DESIGN.md\` \u2014 visual identity contract (palette, type, motion, transitions)
27221
- - \`STORYBOARD.md\` \u2014 per-beat narration/backdrop/duration cues for \`vibe build\`
27222
- - \`media/\` \u2014 user-provided source files (photos, logos, clips, voice recordings)
27223
- - \`index.html\` \u2014 root composition (timeline)
27224
- - \`compositions/scene-*.html\` \u2014 per-scene HTML authored by you or the agent
27225
- - \`assets/\` \u2014 generated/canonical build media (narration audio, images, video)
27226
- - \`.agents/skills/hyperframes/\` \u2014 upstream composition rules, when installed here rather than globally
27227
- - \`transcript.json\` \u2014 Whisper word-level transcript (if narration exists)
27228
- - \`hyperframes.json\` \u2014 HF registry config (speak to both toolchains)
27229
- - \`vibe.config.json\` \u2014 canonical VibeFrame config (providers, budget)
27230
- - \`renders/\` \u2014 output MP4s
27237
+ - \`DESIGN.md\` - visual identity contract (palette, type, motion, transitions)
27238
+ - \`STORYBOARD.md\` - per-beat narration/backdrop/duration cues for \`vibe build\`
27239
+ - \`media/\` - user-provided source files (photos, logos, clips, voice recordings)
27240
+ - \`index.html\` - root composition (timeline)
27241
+ - \`compositions/scene-*.html\` - per-scene HTML authored by you or the agent
27242
+ - \`assets/\` - generated/canonical build media (narration audio, images, video)
27243
+ - \`.agents/skills/hyperframes/\` - upstream composition rules, when installed here rather than globally
27244
+ - \`transcript.json\` - Whisper word-level transcript (if narration exists)
27245
+ - \`hyperframes.json\` - HF registry config (speak to both toolchains)
27246
+ - \`vibe.config.json\` - canonical VibeFrame config (providers, budget)
27247
+ - \`renders/\` - output MP4s
27231
27248
 
27232
27249
  ## Commands
27233
27250
 
@@ -27237,16 +27254,28 @@ vibe build # STORYBOARD.md \u219
27237
27254
  vibe scene lint # Validate scenes (in-process HF linter)
27238
27255
  vibe render # Render to MP4
27239
27256
 
27240
- # Hyperframes CLI (if installed \u2014 works in this project too)
27257
+ # Hyperframes CLI (if installed - works in this project too)
27241
27258
  npx hyperframes preview
27242
27259
  npx hyperframes render
27243
27260
  \`\`\`
27244
27261
 
27245
27262
  ## Key Rules (for hand-authored scene HTML)
27246
27263
 
27264
+ 0. A scene file is a \`<template id="scene-<id>-template">\` wrapping ONE
27265
+ composition div - not a standalone \`<!doctype html>\` document:
27266
+ \`\`\`html
27267
+ <template id="scene-hook-template">
27268
+ <div data-composition-id="scene-hook" data-start="0" data-duration="3.3"
27269
+ data-width="1920" data-height="1080">\u2026</div>
27270
+ </template>
27271
+ \`\`\`
27272
+ The composition div **MUST** carry \`data-width\` and \`data-height\`.
27247
27273
  1. Every timed element needs \`data-start\`, \`data-duration\`, and \`data-track-index\`.
27248
- 2. Elements with timing **MUST** have \`class="clip"\` \u2014 the framework uses this for visibility control.
27249
- 3. Timelines must be paused and registered on \`window.__timelines\`:
27274
+ 2. Elements with timing **MUST** have \`class="clip"\` - the framework uses this for visibility control.
27275
+ 3. Timelines must be paused and registered on \`window.__timelines\`, which is an
27276
+ OBJECT keyed by composition id - not an array, and \`.push()\` leaves the
27277
+ timeline undiscovered, which renders a black frame because \`gsap.from\` holds
27278
+ elements at their start state:
27250
27279
  \`\`\`js
27251
27280
  window.__timelines = window.__timelines || {};
27252
27281
  window.__timelines["composition-id"] = gsap.timeline({ paused: true });
@@ -27257,12 +27286,12 @@ npx hyperframes render
27257
27286
  \`filter\` tweens to \`.scene-content\` or any ancestor containing live text.
27258
27287
  Animate background/media layers instead; text/cards should enter briefly and
27259
27288
  then hold still at their final CSS positions.
27260
- 7. Only deterministic logic \u2014 no \`Date.now()\`, \`Math.random()\`, or network fetches.
27289
+ 7. Only deterministic logic - no \`Date.now()\`, \`Math.random()\`, or network fetches.
27261
27290
 
27262
- ## Linting \u2014 run after changes
27291
+ ## Linting - run after changes
27263
27292
 
27264
27293
  \`\`\`bash
27265
- vibe scene lint # preferred \u2014 in-process, no network
27294
+ vibe scene lint # preferred - in-process, no network
27266
27295
  vibe scene lint --fix # auto-fix mechanical issues
27267
27296
  vibe scene lint --json # structured output for agent loops
27268
27297
  \`\`\`
@@ -27271,7 +27300,7 @@ vibe scene lint --json # structured output for agent loops
27271
27300
  function buildProjectClaudeMd(name) {
27272
27301
  return `@AGENTS.md
27273
27302
 
27274
- # ${name} \u2014 Claude Code Overrides
27303
+ # ${name} - Claude Code Overrides
27275
27304
 
27276
27305
  This file imports \`AGENTS.md\`; keep cross-agent VibeFrame and
27277
27306
  Hyperframes instructions there so Codex, Cursor, Aider, Gemini CLI, and
@@ -27280,7 +27309,7 @@ only when this project needs them.
27280
27309
  `;
27281
27310
  }
27282
27311
  function buildSceneGitignore() {
27283
- return `# VibeFrame \u2014 caches, checkpoints, and project-scope config.yaml (may contain API keys)
27312
+ return `# VibeFrame - caches, checkpoints, and project-scope config.yaml (may contain API keys)
27284
27313
  .vibeframe/
27285
27314
 
27286
27315
  # Render outputs
@@ -28110,7 +28139,7 @@ function insertClipIntoRoot(rootHtml, clip) {
28110
28139
  const closeMatch = rootHtml.match(/\n(\s*)<\/div>(\s*\n\s*<script>)/);
28111
28140
  if (!closeMatch) {
28112
28141
  throw new Error(
28113
- "Could not find root composition closing </div>. Ensure index.html follows the layout from `vibe scene init`."
28142
+ "Could not find root composition closing </div>. Ensure index.html follows the layout from `vibe init`."
28114
28143
  );
28115
28144
  }
28116
28145
  const closeIdx = closeMatch.index;
@@ -29392,10 +29421,10 @@ async function getComposePrompts(opts) {
29392
29421
  error: msg
29393
29422
  });
29394
29423
  if (!existsSync6(designPath)) {
29395
- return baseError(`DESIGN.md not found at ${designPath}. Run \`vibe scene init <dir>\` first.`);
29424
+ return baseError(`DESIGN.md not found at ${designPath}. Run \`vibe init <dir>\` first.`);
29396
29425
  }
29397
29426
  if (!existsSync6(storyboardPath2)) {
29398
- return baseError(`STORYBOARD.md not found at ${storyboardPath2}. Run \`vibe scene init <dir>\` to create a starter, or add STORYBOARD.md with per-beat cues.`);
29427
+ return baseError(`STORYBOARD.md not found at ${storyboardPath2}. Run \`vibe init <dir>\` to create a starter, or add STORYBOARD.md with per-beat cues.`);
29399
29428
  }
29400
29429
  if (!hyperframesSkillAvailable(projectDir)) {
29401
29430
  warnings.push(
@@ -29475,7 +29504,9 @@ function buildInstructions(args) {
29475
29504
  if (args.skillRef) {
29476
29505
  lines.push(`1. Read \`${args.skillRef}\` for the Hyperframes framework rules + house style. This is the visual-identity hard-gate.`);
29477
29506
  } else {
29478
- lines.push(`1. Run \`vibe scene install-skill\` to install the Hyperframes composition rules, then read them.`);
29507
+ lines.push(
29508
+ `1. Read this project's \`AGENTS.md\` section "Key Rules (for hand-authored scene HTML)" - written by \`vibe init\`, and the authoritative local contract. \`vibe scene install-skill\` adds Hyperframes' house style on top, but note it installs a ROUTER whose full contract sits behind \`/hyperframes-core\`, which resolves only in a host that has upstream's Hyperframes skills.`
29509
+ );
29479
29510
  }
29480
29511
  lines.push(`2. Read \`DESIGN.md\` for project-specific palette, typography, motion signature.`);
29481
29512
  if (args.compositionRef) {
@@ -29485,6 +29516,7 @@ function buildInstructions(args) {
29485
29516
  lines.push(`3b. Use each beat's \`finalDurationSec\` (narration-synced) for \`data-duration\` and timeline anchors when present \u2014 NOT the storyboard \`duration\`, which is only the minimum. Scenes composed at the storyboard duration end early and render black tails.`);
29486
29517
  lines.push(`3c. Never give inner \`.clip\` elements a non-zero \`data-start\` \u2014 the renderer does not toggle internal clip visibility inside sub-compositions, so phased clips render all phases at once (overlapping text). Use full-window clips and GSAP autoAlpha phase transitions instead. Also keep beats 6-15s; split anything longer in the storyboard first.`);
29487
29518
  lines.push(`3d. If your environment cannot write files (e.g. Claude Desktop / MCP-only hosts), author each beat's HTML and submit it with the \`scene_submit\` tool (beat id + html). It validates with the same Hyperframes lint and writes the file for you; on lint errors it returns the findings without writing \u2014 fix and resubmit.`);
29519
+ lines.push(`3e. Hard requirements the linter fails on, so satisfy them even without the full contract. A scene file is a \`<template id="scene-<id>-template">\` wrapping ONE \`<div data-composition-id="scene-<id>" data-start="0" data-duration="<sec>" data-width="1920" data-height="1080">\` \u2014 not a standalone \`<!doctype html>\` document. Register the paused GSAP timeline on the registry OBJECT keyed by composition id: \`window.__timelines = window.__timelines || {}; window.__timelines["scene-<id>"] = tl;\` \u2014 it is not an array, and \`.push()\` leaves the timeline undiscovered, which renders a black frame because \`gsap.from\` holds elements at their start state. Also put \`class="clip"\` on every timed element and give timeline-visible elements a stable \`id\`. Generate a reference scene with \`vibe scene add <id> --style <preset> --no-audio --no-image\` and match its shape.`);
29488
29520
  if (args.beatCount > 1) {
29489
29521
  lines.push(`4. After authoring all ${args.beatCount} beat(s), run \`vibe build <project> --stage sync --json\` to assemble the root composition (index.html) from the fragments. Lint needs that root, so sync comes first.`);
29490
29522
  } else if (args.filtered) {
@@ -30770,7 +30802,9 @@ async function executeSceneAdd(opts) {
30770
30802
  error
30771
30803
  });
30772
30804
  if (!await pathExists2(rootPath)) {
30773
- return errResult(`Root composition not found: ${rootPath}. Run \`vibe scene init\` first.`);
30805
+ return errResult(
30806
+ `Root composition not found: ${rootPath}. Run \`vibe build\` once to create the render scaffold, or scaffold it up front with \`vibe init <dir> --profile full\`.`
30807
+ );
30774
30808
  }
30775
30809
  if (!opts.force && await pathExists2(scenePath)) {
30776
30810
  return errResult(`Scene already exists: ${sceneRel}. Re-run with --force to overwrite.`);
@@ -31312,7 +31346,7 @@ Run 'vibe schema scene.<command>' for structured parameter info.`
31312
31346
  console.log(source_default.dim("Show details: "), source_default.cyan('vibe scene list-styles "<name>"'));
31313
31347
  console.log(
31314
31348
  source_default.dim("Seed DESIGN.md:"),
31315
- source_default.cyan('vibe scene init <dir> --visual-style "<name>"')
31349
+ source_default.cyan('vibe init <dir> --visual-style "<name>"')
31316
31350
  );
31317
31351
  return;
31318
31352
  }
@@ -31347,7 +31381,7 @@ Run 'vibe schema scene.<command>' for structured parameter info.`
31347
31381
  console.log();
31348
31382
  console.log(
31349
31383
  source_default.dim("Seed DESIGN.md:"),
31350
- source_default.cyan(`vibe scene init <dir> --visual-style "${style.name}"`)
31384
+ source_default.cyan(`vibe init <dir> --visual-style "${style.name}"`)
31351
31385
  );
31352
31386
  });
31353
31387
  sceneCommand.command("add").description("Add a new scene to a project: AI narration + image + per-scene HTML").argument("<name>", "Scene name (slugified into the composition id)").option("--style <preset>", `Style preset: ${SCENE_PRESETS.join(", ")}`, "simple").option(
@@ -57541,13 +57575,15 @@ var init_walkthroughs = __esm({
57541
57575
  SCENE_WALKTHROUGH = `# Scene authoring with vibe
57542
57576
 
57543
57577
  A scene project is a directory that is **bilingual**: it works with both
57544
- \`vibe\` and \`npx hyperframes\`. Each scene is one HTML file with scoped CSS
57545
- and a paused GSAP timeline. Cheap to edit, cheap to lint, expensive only
57578
+ \`vibe\` and \`npx hyperframes\`. Scene composition is Hyperframes' job:
57579
+ each scene is one HTML file with scoped CSS and a paused GSAP timeline,
57580
+ authored to upstream's composition rules (install them with
57581
+ \`vibe scene install-skill\`). Cheap to edit, cheap to lint, expensive only
57546
57582
  at render.
57547
57583
 
57548
- \`vibe build\` (v0.60+) is the supported one-shot driver from a
57549
- written storyboard to an MP4. Plan H (v0.70) added \`--mode agent\` so the
57550
- host agent itself authors the per-beat HTML \u2014 no internal LLM call.
57584
+ \`vibe build\` is the supported one-shot driver from a written storyboard
57585
+ to an MP4. The host agent authors the per-beat HTML - the CLI makes no
57586
+ internal LLM call.
57551
57587
 
57552
57588
  ## Three authoring paths
57553
57589
 
@@ -57562,20 +57598,20 @@ narration / backdrop intent.
57562
57598
 
57563
57599
  ## High-craft path
57564
57600
 
57565
- 1. \`vibe init my-promo --visual-style "Swiss Pulse"\` \u2014 seeds
57601
+ 1. \`vibe init my-promo --visual-style "Swiss Pulse"\` - seeds
57566
57602
  \`DESIGN.md\` (palette, typography, motion, transitions) plus the
57567
57603
  \`vibe.config.json\` / \`hyperframes.json\` / \`index.html\` scaffold.
57568
57604
  It does **not** install the composition rules; if your agent does not
57569
57605
  already have the \`hyperframes\` skill, run
57570
57606
  \`vibe scene install-skill\` to fetch them from upstream into
57571
57607
  \`.agents/skills/hyperframes/\`.
57572
- 2. Read \`.agents/skills/hyperframes/SKILL.md\` (or your global copy) \u2014
57608
+ 2. Read \`.agents/skills/hyperframes/SKILL.md\` (or your global copy) -
57573
57609
  framework rules, motion principles, type system, transition recipes.
57574
- 3. Read \`DESIGN.md\` \u2014 project-specific palette / typography / motion
57610
+ 3. Read \`DESIGN.md\` - project-specific palette / typography / motion
57575
57611
  signature (visual identity hard-gate).
57576
57612
  4. Author each scene HTML directly under \`compositions/scene-<id>.html\`
57577
57613
  using the rules from steps 2 and 3. The skill enforces the visual
57578
- identity contract \u2014 scenes that contradict DESIGN.md fail lint.
57614
+ identity contract - scenes that contradict DESIGN.md fail lint.
57579
57615
  5. \`vibe scene lint --fix\` for mechanical issues, \`vibe render my-promo\`
57580
57616
  to MP4.
57581
57617
 
@@ -57589,16 +57625,16 @@ vibe scene lint
57589
57625
  vibe render my-promo
57590
57626
  \`\`\`
57591
57627
 
57592
- \`vibe init\` is **idempotent** \u2014 running it on an existing Hyperframes
57628
+ \`vibe init\` is **idempotent** - running it on an existing Hyperframes
57593
57629
  directory merges \`hyperframes.json\` instead of clobbering it. Safe to
57594
57630
  invoke on user-provided projects.
57595
57631
 
57596
57632
  ## Subcommands
57597
57633
 
57598
57634
  \`\`\`bash
57599
- # Project flow (top-level \u2014 preferred entry points)
57635
+ # Project flow (top-level - preferred entry points)
57600
57636
  vibe init <dir> [-r 16:9|9:16|1:1|4:5] [-d <sec>] [--visual-style "<name>"]
57601
- vibe build [<dir>] [--mode agent|batch|auto] # H3 dispatch
57637
+ vibe build [<dir>] [--composer template] # agent authors scenes by default
57602
57638
  vibe render [<dir>] [--fps 30] [--quality standard] [--format mp4]
57603
57639
 
57604
57640
  # Lower-level scene authoring
@@ -57611,11 +57647,11 @@ vibe scene lint [<root>] [--json] [--fix]
57611
57647
 
57612
57648
  ## Style presets (for \`vibe scene add --style\`)
57613
57649
 
57614
- - **simple** \u2014 backdrop + bottom caption (default)
57615
- - **announcement** \u2014 single huge headline, gradient text
57616
- - **explainer** \u2014 kicker + title + subtitle stack
57617
- - **kinetic-type** \u2014 words animate in word-by-word
57618
- - **product-shot** \u2014 corner label + bottom headline + slow zoom
57650
+ - **simple** - backdrop + bottom caption (default)
57651
+ - **announcement** - single huge headline, gradient text
57652
+ - **explainer** - kicker + title + subtitle stack
57653
+ - **kinetic-type** - words animate in word-by-word
57654
+ - **product-shot** - corner label + bottom headline + slow zoom
57619
57655
 
57620
57656
  All presets accept \`--narration <text|file>\`, \`--visuals <prompt>\`,
57621
57657
  \`--headline\`, \`--kicker\`. With \`--narration\`, scene duration auto-derives
@@ -57625,21 +57661,19 @@ from the generated TTS audio.
57625
57661
 
57626
57662
  \`\`\`bash
57627
57663
  vibe init my-promo --visual-style "Swiss Pulse" -d 12
57628
- # (edit STORYBOARD.md with per-beat YAML cues \u2014 narration, backdrop, duration)
57664
+ # (edit STORYBOARD.md with per-beat YAML cues - narration, backdrop, duration)
57629
57665
  vibe build my-promo
57630
57666
  \`\`\`
57631
57667
 
57632
57668
  \`vibe build\` reads the STORYBOARD frontmatter + per-beat cues,
57633
57669
  dispatches TTS + image-gen per beat, then either:
57634
57670
 
57635
- - **\`--mode agent\`** (default when an agent host is detected) \u2014 emits a
57636
- \`needs-author\` plan via \`vibe scene compose-prompts\`. The host agent
57637
- authors each \`compositions/scene-<id>.html\` itself, then re-invoking
57638
- \`vibe build\` proceeds to lint + render.
57639
- - **\`--mode batch\`** \u2014 VibeFrame runs an internal LLM (Claude / OpenAI /
57640
- Gemini) to compose the HTML, then renders.
57641
-
57642
- \`VIBE_BUILD_MODE\` env var overrides the auto-resolve.
57671
+ - **Agent authoring** (default) - emits a \`needs-author\` plan via
57672
+ \`vibe scene compose-prompts\`. The host agent authors each
57673
+ \`compositions/scene-<id>.html\` itself, then re-invoking \`vibe build\`
57674
+ proceeds to lint + render. The CLI makes no internal LLM call.
57675
+ - **\`--composer template\`** - the deterministic no-model composer
57676
+ (concat background + lower-thirds), for when no agent is available.
57643
57677
 
57644
57678
  ## Lint feedback loop
57645
57679
 
@@ -57649,7 +57683,7 @@ vibe scene lint --json --fix
57649
57683
 
57650
57684
  Returns structured findings. The recommended loop: 1) run lint with
57651
57685
  \`--fix\` (mechanical fixes applied), 2) if \`errorCount > 0\`, edit the
57652
- scene HTML, 3) re-lint. Cap retries at 3 \u2014 if errors persist, fall back
57686
+ scene HTML, 3) re-lint. Cap retries at 3 - if errors persist, fall back
57653
57687
  to a template preset (\`vibe scene add <id> --style simple --force\`)
57654
57688
  and surface the error to the user.
57655
57689
 
@@ -57725,9 +57759,9 @@ The full set lives in \`packages/cli/src/pipeline/executor.ts\`.
57725
57759
 
57726
57760
  ## Variable references
57727
57761
 
57728
- - \`$<step-id>.output\` \u2014 previous step's output path
57729
- - \`$<step-id>.result.<field>\` \u2014 structured field from JSON result
57730
- - \`\${ENV_VAR}\` \u2014 environment variable
57762
+ - \`$<step-id>.output\` - previous step's output path
57763
+ - \`$<step-id>.result.<field>\` - structured field from JSON result
57764
+ - \`\${ENV_VAR}\` - environment variable
57731
57765
  - Values can be templated: \`"\${SCRIPT_TITLE} - Episode \${EPISODE}"\`
57732
57766
 
57733
57767
  ## Running
@@ -57744,12 +57778,12 @@ Checkpoints land next to the YAML: \`pipeline.yaml.checkpoint.json\`.
57744
57778
 
57745
57779
  ## Authoring tips
57746
57780
 
57747
- 1. **Start from a tiny YAML** \u2014 keep it in your project directory and run
57781
+ 1. **Start from a tiny YAML** - keep it in your project directory and run
57748
57782
  \`vibe run pipeline.yaml --dry-run\` before spending provider budget.
57749
- 2. **Dry-run first** \u2014 you see estimated cost and resolved variable
57783
+ 2. **Dry-run first** - you see estimated cost and resolved variable
57750
57784
  graph before spending API credits.
57751
57785
  3. **Keep step ids short and descriptive** (\`intro\`, \`scene1\`, \`voice\`,
57752
- \`bgm\`) \u2014 they appear in logs and variable refs.
57786
+ \`bgm\`) - they appear in logs and variable refs.
57753
57787
  4. **Name outputs** with extensions matching the action (\`.mp4\`, \`.mp3\`,
57754
57788
  \`.png\`, \`.json\`).
57755
57789
  5. **Declare \`budget:\`** on expensive pipelines:
@@ -57773,9 +57807,9 @@ When the user has a working shell sequence, extract steps:
57773
57807
  - Wrap the entire chain in a \`name:\` + \`steps:\` skeleton
57774
57808
 
57775
57809
  The \`compose\` action is the catch-all assembly step (audio mux, video
57776
- overlay, etc.) \u2014 useful at the tail of a pipeline.
57810
+ overlay, etc.) - useful at the tail of a pipeline.
57777
57811
  `;
57778
- ARCHITECTURE_WALKTHROUGH = `# vibe agent / build / run \u2014 when to pick which
57812
+ ARCHITECTURE_WALKTHROUGH = `# vibe agent / build / run - when to pick which
57779
57813
 
57780
57814
  The CLI has three orchestrating commands that coordinate other primitives:
57781
57815
  \`vibe agent\`, \`vibe build\`, \`vibe run\`. New users routinely ask which one
@@ -57804,14 +57838,14 @@ built-in fallback when you do not already have an agent host.
57804
57838
  - "I have a finished script + visual identity" \u2192 \`vibe build\`
57805
57839
  - "I want this to run again next month" \u2192 \`vibe run\`
57806
57840
 
57807
- If two seem to fit, pick the rightmost one \u2014 more reproducible, less surprise.
57841
+ If two seem to fit, pick the rightmost one - more reproducible, less surprise.
57808
57842
 
57809
57843
  ## Cost-tier awareness (v0.83+)
57810
57844
 
57811
57845
  Every primitive subcommand carries a cost tier (\`free\` / \`low\` / \`high\` /
57812
57846
  \`very-high\`). \`vibe schema --list\` exposes the tier as JSON, and each
57813
57847
  \`vibe <group> <sub> --help\` page shows it as a colored footer. Use
57814
- \`vibe doctor --test-keys\` before kicking off any high-cost orchestrator \u2014
57848
+ \`vibe doctor --test-keys\` before kicking off any high-cost orchestrator -
57815
57849
  a single bad key wastes time and money.
57816
57850
 
57817
57851
  ## Cross-command primitives
@@ -57921,7 +57955,7 @@ vibe generate motion "animated product logo reveal" --render -o logo-reveal.mp4
57921
57955
  title: "YAML pipelines (Video as Code)",
57922
57956
  summary: "Author and run reproducible multi-step video workflows",
57923
57957
  steps: [
57924
- "Sketch the workflow as YAML \u2014 `name`, `description`, then `steps:` with `id` + `action` + inputs/outputs.",
57958
+ "Sketch the workflow as YAML - `name`, `description`, then `steps:` with `id` + `action` + inputs/outputs.",
57925
57959
  "Reference previous step outputs via `$<step-id>.output` (or `$<step-id>.result.<field>` for structured returns).",
57926
57960
  "Run `vibe run pipeline.yaml --dry-run` to see the resolved graph + cost estimate before spending API budget.",
57927
57961
  "Add a `budget:` block (tokens / cost_usd / max_tool_errors) to cap expensive runs.",
@@ -61217,7 +61251,7 @@ async function executeSceneRender(opts = {}) {
61217
61251
  kind: "render",
61218
61252
  beat: opts.beatId ?? null,
61219
61253
  root,
61220
- error: `Root composition not found: ${resolve66(projectDir, root)}. Run \`vibe scene init\` first.`
61254
+ error: `Root composition not found: ${resolve66(projectDir, root)}. Run \`vibe build ${projectDir}\` once to create the render scaffold, or scaffold it up front with \`vibe init <dir> --profile full\`.`
61221
61255
  };
61222
61256
  }
61223
61257
  const chrome = await preflightChrome();
@@ -61708,7 +61742,7 @@ async function executeSceneBuild(opts) {
61708
61742
  phase: "failed",
61709
61743
  mode,
61710
61744
  selectedStage,
61711
- error: `STORYBOARD.md not found at ${storyboardPath2}. Run \`vibe scene init <dir>\` to create a starter, or add STORYBOARD.md with per-beat cues.`,
61745
+ error: `STORYBOARD.md not found at ${storyboardPath2}. Run \`vibe init <dir>\` to create a starter, or add STORYBOARD.md with per-beat cues.`,
61712
61746
  beats: [],
61713
61747
  stageReports,
61714
61748
  warnings,
@@ -74248,8 +74282,8 @@ init_source();
74248
74282
  // package.json
74249
74283
  var package_default = {
74250
74284
  name: "@vibeframe/cli",
74251
- version: "0.113.28",
74252
- description: "VibeFrame CLI - agentic video workflow runtime",
74285
+ version: "0.113.30",
74286
+ description: "Frontier AI video generation for coding agents - Seedance, Runway, Veo, and Kling on your own keys, behind a hard cost cap",
74253
74287
  private: false,
74254
74288
  license: "MIT",
74255
74289
  repository: {
@@ -74260,13 +74294,21 @@ var package_default = {
74260
74294
  bugs: {
74261
74295
  url: "https://github.com/vericontext/vibeframe/issues"
74262
74296
  },
74297
+ homepage: "https://vibeframe.ai",
74263
74298
  keywords: [
74264
74299
  "vibeframe",
74265
74300
  "cli",
74266
- "video-editing",
74267
- "ai",
74268
- "ffmpeg",
74269
- "commander"
74301
+ "ai-video",
74302
+ "video-generation",
74303
+ "text-to-video",
74304
+ "image-to-video",
74305
+ "seedance",
74306
+ "runway",
74307
+ "veo",
74308
+ "kling",
74309
+ "ai-agent",
74310
+ "mcp",
74311
+ "ffmpeg"
74270
74312
  ],
74271
74313
  type: "module",
74272
74314
  bin: {
@@ -81597,7 +81639,7 @@ function parseScope(raw) {
81597
81639
  }
81598
81640
  return v;
81599
81641
  }
81600
- var setupCommand = new Command("setup").description("Configure VibeFrame (LLM provider, API keys)").option("--reset", "Reset configuration to defaults").option("--full", "Run full setup with all optional providers").option("--show", "Show current configuration (for debugging)").option(
81642
+ var setupCommand = new Command("setup").description("Configure VibeFrame (video/image provider keys, LLM provider)").option("--reset", "Reset configuration to defaults").option("--full", "Run full setup with all optional providers").option("--show", "Show current configuration (for debugging)").option(
81601
81643
  "-v, --verbose",
81602
81644
  "With --show: include unset providers + Resolution order + Defaults block"
81603
81645
  ).option("--claude-code", "Show Claude Code integration guide").option("-y, --yes", "Non-interactive: write config without prompting (CI / devcontainer)").option(
@@ -81617,8 +81659,8 @@ Non-interactive examples (no TTY required):
81617
81659
  vibe setup --scope project --yes --import-env Project-only setup (./.vibeframe/config.yaml)
81618
81660
 
81619
81661
  Scopes:
81620
- user (default) ~/.vibeframe/config.yaml \u2014 shared across every project
81621
- project ./.vibeframe/config.yaml \u2014 gitignored, isolates keys/defaults to this directory
81662
+ user (default) ~/.vibeframe/config.yaml - shared across every project
81663
+ project ./.vibeframe/config.yaml - gitignored, isolates keys/defaults to this directory
81622
81664
  When a project config exists at the cwd, it is used and the user file is ignored.
81623
81665
 
81624
81666
  Exit codes (non-interactive):
@@ -81825,7 +81867,7 @@ var AI_FEATURES = [
81825
81867
  {
81826
81868
  label: "Audio",
81827
81869
  desc: "TTS, SFX, music, voice clone",
81828
- defaultProvider: "ElevenLabs (paid, premium quality) \u2014 falls back to local Kokoro when no key (free, since v0.54)",
81870
+ defaultProvider: "ElevenLabs (paid, premium quality) - falls back to local Kokoro when no key (free, since v0.54)",
81829
81871
  alsoAvailable: "Replicate MusicGen (music only)",
81830
81872
  keyHint: "0-1 key",
81831
81873
  keys: [
@@ -82131,7 +82173,7 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
82131
82173
  const displayPath2 = scope === "user" ? userStatus?.source === "legacy" ? userStatus.configPath : USER_CONFIG_PATH : getConfigPath(scope);
82132
82174
  const cfgPath = displayPath2.replace(homedir6(), "~");
82133
82175
  const scopeNote = scope === "project" ? "applies to this project only \xB7 user config is ignored while this file exists \xB7 add .vibeframe/ to .gitignore" : "applies to every project for this user";
82134
- console.log(source_default.bold.magenta("VibeFrame Setup") + source_default.bold(` \u2014 ${scope} scope`));
82176
+ console.log(source_default.bold.magenta("VibeFrame Setup") + source_default.bold(` - ${scope} scope`));
82135
82177
  console.log(source_default.dim(`${cfgPath} \xB7 ${scopeNote}`));
82136
82178
  if (userStatus?.source === "legacy") {
82137
82179
  console.log(
@@ -82162,14 +82204,14 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
82162
82204
  console.log(source_default.bold("What would you like to do?"));
82163
82205
  console.log();
82164
82206
  const topLabels = [
82207
+ `Generate AI video ${source_default.dim("(build from a storyboard, remix highlights, auto-shorts)")}`,
82208
+ `AI features ${source_default.dim("(pick what you need - images, videos, audio, editing)")}`,
82165
82209
  `Edit videos offline ${source_default.dim("(silence-cut, fade, noise-reduce, detect)")} ${source_default.green("no API keys")}`,
82166
- `AI features ${source_default.dim("(pick what you need \u2014 images, videos, audio, editing)")}`,
82167
- `Full AI pipeline ${source_default.dim("(build, remix highlights, auto-shorts)")}`,
82168
- `Full provider list ${source_default.dim("(every supported provider, one by one \u2014 same as --full)")}`
82210
+ `Full provider list ${source_default.dim("(every supported provider, one by one - same as --full)")}`
82169
82211
  ];
82170
82212
  const topIndex = await promptSelect(source_default.cyan(" Select [1-4]: "), topLabels, 0);
82171
82213
  console.log();
82172
- if (topIndex === 0) {
82214
+ if (topIndex === 2) {
82173
82215
  await saveConfig(config2, { scope });
82174
82216
  await completeOrContinue(config2, "vibe edit silence-cut video.mp4 -o clean.mp4", [], scope);
82175
82217
  return;
@@ -82180,7 +82222,7 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
82180
82222
  await completeOrContinue(config2, "vibe doctor --test-keys", [], scope);
82181
82223
  return;
82182
82224
  }
82183
- if (topIndex === 2) {
82225
+ if (topIndex === 0) {
82184
82226
  config2.llm.provider = "claude";
82185
82227
  const pipelineKeys = [
82186
82228
  {
@@ -82188,7 +82230,7 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
82188
82230
  envVar: "ANTHROPIC_API_KEY",
82189
82231
  name: "Anthropic",
82190
82232
  url: "https://console.anthropic.com/settings/keys",
82191
- what: "Claude \u2014 storyboard generation + reasoning"
82233
+ what: "Claude - storyboard generation + reasoning"
82192
82234
  },
82193
82235
  {
82194
82236
  configKey: "openai",
@@ -82202,7 +82244,7 @@ async function runSetupWizard(fullSetup = false, scope = "user") {
82202
82244
  envVar: "FAL_API_KEY",
82203
82245
  name: "fal.ai",
82204
82246
  url: "https://fal.ai/dashboard/keys",
82205
- what: "Seedance 2.0 \u2014 video generation, default since v0.57"
82247
+ what: "Seedance 2.0 - video generation, default since v0.57"
82206
82248
  },
82207
82249
  {
82208
82250
  configKey: "elevenlabs",
@@ -82514,7 +82556,7 @@ async function runCustomSetup(config2, scope = "user", opts = {}) {
82514
82556
  xai: "Grok 4.1 Fast, 2M context, great for tool calling",
82515
82557
  openrouter: "300+ models via one API key (Claude, GPT, Gemini, Llama, etc.)",
82516
82558
  evolink: "GPT-5, Claude, Gemini, DeepSeek & more via one key",
82517
- ollama: "Free, local, no API key \u2014 offline capable (default: llama3.2)"
82559
+ ollama: "Free, local, no API key - offline capable (default: llama3.2)"
82518
82560
  };
82519
82561
  const providerLabels = providers.map((p) => {
82520
82562
  const rec = p === "claude" ? source_default.dim(" (recommended)") : "";
@@ -82635,19 +82677,19 @@ async function showComplete(config2, defaultTryCommand, features = [], scope = "
82635
82677
  console.log();
82636
82678
  console.log(
82637
82679
  source_default.dim(
82638
- ` Detected ${primary.label} \u2014 \`vibe init\` will scaffold ${primary.projectFiles.join(" + ")} in your project.`
82680
+ ` Detected ${primary.label} - \`vibe init\` will scaffold ${primary.projectFiles.join(" + ")} in your project.`
82639
82681
  )
82640
82682
  );
82641
82683
  console.log(
82642
82684
  source_default.dim(
82643
- ` Scene composer will auto-dispatch to ${primary.label} (${source_default.bold("--mode agent")}). Run \`vibe init my-promo\` to scaffold a video project + install local composition rules.`
82685
+ ` ${primary.label} authors each scene during \`vibe build\`. Run \`vibe init my-promo\` to scaffold a video project.`
82644
82686
  )
82645
82687
  );
82646
82688
  } else {
82647
82689
  console.log();
82648
82690
  console.log(
82649
82691
  source_default.dim(
82650
- ` No agent host detected \u2014 \`vibe build\` will use the internal LLM composer (${source_default.bold("--mode batch")}).`
82692
+ ` No agent host detected - scenes are authored by a coding agent during \`vibe build\`; pass ${source_default.bold("--composer template")} for the deterministic no-model fallback.`
82651
82693
  )
82652
82694
  );
82653
82695
  }
@@ -82658,7 +82700,7 @@ async function setupClaudeCode() {
82658
82700
  console.log(source_default.bold.cyan("Claude Code Integration"));
82659
82701
  console.log(source_default.dim("\u2500".repeat(40)));
82660
82702
  console.log();
82661
- console.log(" VibeFrame CLI is self-discoverable \u2014 no extra setup needed.");
82703
+ console.log(" VibeFrame CLI is self-discoverable - no extra setup needed.");
82662
82704
  console.log(" Claude Code can use these commands to understand the CLI:");
82663
82705
  console.log();
82664
82706
  console.log(` ${source_default.green("vibe --help")} All command groups`);
@@ -82763,7 +82805,7 @@ async function showConfig(opts = { verbose: false }) {
82763
82805
  if (!verbose && unsetCount > 0) {
82764
82806
  console.log(
82765
82807
  source_default.dim(
82766
- ` (${unsetCount} provider${unsetCount === 1 ? "" : "s"} unset \u2014 run with --verbose to list)`
82808
+ ` (${unsetCount} provider${unsetCount === 1 ? "" : "s"} unset - run with --verbose to list)`
82767
82809
  )
82768
82810
  );
82769
82811
  }
@@ -82834,7 +82876,7 @@ providers:
82834
82876
  # ${product} - Storyboard
82835
82877
 
82836
82878
  Pacing: keep beats 6-15 seconds. Longer beats render as static, overstuffed
82837
- scenes \u2014 split them instead.
82879
+ scenes - split them instead.
82838
82880
 
82839
82881
  Brief: ${brief}
82840
82882
 
@@ -83348,26 +83390,27 @@ function cmdQuote(value) {
83348
83390
  // src/commands/_shared/init-templates.ts
83349
83391
  var AGENTS_MD = `# AGENTS.md
83350
83392
 
83351
- This project uses [VibeFrame](https://github.com/vericontext/vibeframe) \u2014
83352
- a CLI for AI-powered video editing. The \`vibe\` command provides 80+
83353
- subcommands for video generation, editing, analysis, and pipeline
83354
- orchestration. Cost tiers below \u2014 **always confirm with the user before
83355
- running High / Very High tier commands**.
83393
+ This project uses [VibeFrame](https://github.com/vericontext/vibeframe) -
83394
+ a CLI for AI video generation on the user's own provider keys (Seedance,
83395
+ Runway, Veo, Kling), behind dry runs and a hard \`--max-cost\` ceiling.
83396
+ The \`vibe\` command provides 80+ subcommands for video generation,
83397
+ editing, and analysis. Cost tiers below - **always confirm with the user
83398
+ before running High / Very High tier commands**.
83356
83399
 
83357
83400
  ## Agent host coverage
83358
83401
 
83359
83402
  VibeFrame's CLI works with any bash-capable AI coding agent. Six host
83360
83403
  families have first-class auto-detection and scaffolds today:
83361
83404
 
83362
- - **Claude Code** \u2014 \`CLAUDE.md\` (this file's import wrapper) +
83405
+ - **Claude Code** - \`CLAUDE.md\` (this file's import wrapper) +
83363
83406
  \`AGENTS.md\` + \`/vibe-*\` slash commands.
83364
- - **OpenAI Codex** \u2014 reads \`AGENTS.md\` natively (agents.md spec).
83365
- - **Cursor** \u2014 reads \`AGENTS.md\` plus \`.cursor/rules/\` for project
83407
+ - **OpenAI Codex** - reads \`AGENTS.md\` natively (agents.md spec).
83408
+ - **Cursor** - reads \`AGENTS.md\` plus \`.cursor/rules/\` for project
83366
83409
  rules; supports MCP via \`.cursor/mcp.json\`.
83367
- - **Aider** \u2014 reads \`AGENTS.md\` (binary-only detection by VibeFrame).
83368
- - **Gemini CLI** \u2014 primary context file is \`GEMINI.md\`; also reads
83410
+ - **Aider** - reads \`AGENTS.md\` (binary-only detection by VibeFrame).
83411
+ - **Gemini CLI** - primary context file is \`GEMINI.md\`; also reads
83369
83412
  \`AGENTS.md\` if present.
83370
- - **OpenCode** \u2014 reads \`AGENTS.md\` (officially supported per
83413
+ - **OpenCode** - reads \`AGENTS.md\` (officially supported per
83371
83414
  \`opencode.ai/docs/rules\`); supports MCP via \`.opencode/mcp.json\`.
83372
83415
 
83373
83416
  Run \`vibe doctor\` to see which host(s) the CLI detects in your
@@ -83377,7 +83420,7 @@ fallback.
83377
83420
 
83378
83421
  ## Self-discovery
83379
83422
 
83380
- Don't memorise the command surface \u2014 read it from the CLI:
83423
+ Don't memorise the command surface - read it from the CLI:
83381
83424
 
83382
83425
  \`\`\`bash
83383
83426
  vibe --help # command groups overview
@@ -83397,10 +83440,10 @@ vibe guide pipeline # step-by-step authoring guide (pipeline)
83397
83440
  Routing the user's request correctly is the most important judgement call
83398
83441
  you'll make. Do not force everything into a scene project.
83399
83442
 
83400
- **ASSET \u2014 default for any single-asset request OR ambiguous prompt.**
83443
+ **ASSET - default for any single-asset request OR ambiguous prompt.**
83401
83444
  If the user asks for a single image, single video clip, sound effect, music
83402
- bed, or narration file \u2014 **OR pastes a visual/audio brief without explicit
83403
- storyboard / scene / multi-scene language** \u2014 treat it as ASSET. Use
83445
+ bed, or narration file - **OR pastes a visual/audio brief without explicit
83446
+ storyboard / scene / multi-scene language** - treat it as ASSET. Use
83404
83447
  \`vibe generate ...\` directly. Do **not** edit \`DESIGN.md\`,
83405
83448
  \`STORYBOARD.md\`, run \`vibe scene ...\`, or auto-load the hyperframes
83406
83449
  skill until BUILD intent is explicit. The visual-identity hard-gate
@@ -83417,13 +83460,13 @@ If genuinely uncertain, ask one short question: *"single asset or
83417
83460
  multi-scene project?"* before authoring DESIGN.md or loading the
83418
83461
  hyperframes skill.
83419
83462
 
83420
- **BUILD \u2014 create new video from text intent.**
83463
+ **BUILD - create new video from text intent.**
83421
83464
  Use \`vibe build\` with a STORYBOARD.md + DESIGN.md. The
83422
83465
  skills-driven pipeline (v0.60+) dispatches narration TTS + backdrop
83423
83466
  image-gen per beat, composes scene HTML via the bundled composition rules
83424
83467
  bundle, then renders to MP4. Idempotent re-runs reuse cached assets.
83425
83468
 
83426
- **REMIX \u2014 transform existing video / audio.**
83469
+ **REMIX - transform existing video / audio.**
83427
83470
  Use \`vibe remix\`, \`vibe edit\`, or \`vibe audio\`. One-shot,
83428
83471
  batch-oriented operations on a file the user already has on disk.
83429
83472
  \`vibe edit text-overlay\` is the free deterministic path for simple static
@@ -83483,7 +83526,7 @@ starting from a media file and wants it transformed, it's REMIX.
83483
83526
  When you run vibe commands programmatically:
83484
83527
 
83485
83528
  1. **Always \`--json\`** for structured output you can parse without regex
83486
- 2. **Always \`--dry-run\` first** for any High/Very-High tier command \u2014 it returns
83529
+ 2. **Always \`--dry-run\` first** for any High/Very-High tier command - it returns
83487
83530
  the cost estimate without spending API budget
83488
83531
  3. **Use \`vibe schema <command>\`** to discover parameters; do not guess flags
83489
83532
  4. **Pass complex options via \`--stdin\`**:
@@ -83525,7 +83568,7 @@ vibe host doctor all --json # verify readiness
83525
83568
 
83526
83569
  Default setup is snippet-only; use \`--write\` when you want VibeFrame to merge
83527
83570
  the generated config. Keep provider keys in \`.vibeframe/config.yaml\`, user
83528
- config, or env files \u2014 not in app host config.
83571
+ config, or env files - not in app host config.
83529
83572
 
83530
83573
  ## Host agent loop
83531
83574
 
@@ -83536,7 +83579,7 @@ budget caps, \`build-report.json\`, \`review-report.json\`, \`nextActions\`,
83536
83579
  \`safeToAutoRun\`, \`requiresConfirmation\`, \`fixOwner\`, deterministic repair,
83537
83580
  and render inspection for the host agent to decide what to do next.
83538
83581
 
83539
- Copy-paste agent prompt (Codex) \u2014 a plain prompt, not a built-in command:
83582
+ Copy-paste agent prompt (Codex) - a plain prompt, not a built-in command:
83540
83583
 
83541
83584
  \`\`\`text
83542
83585
  Build this VibeFrame project into renders/final.mp4. Use --json for every
@@ -83553,7 +83596,7 @@ remaining host-agent issue is fixed, accepted with rationale, or reported as
83553
83596
  blocked.
83554
83597
  \`\`\`
83555
83598
 
83556
- Copy-paste agent prompt (Claude Code) \u2014 a plain prompt, not a built-in command:
83599
+ Copy-paste agent prompt (Claude Code) - a plain prompt, not a built-in command:
83557
83600
 
83558
83601
  \`\`\`text
83559
83602
  Finish this VibeFrame render using your host's agent loop as the outer
@@ -83568,7 +83611,7 @@ no unresolved unacknowledged host-agent issues.
83568
83611
 
83569
83612
  ### Composition rules (scene HTML)
83570
83613
 
83571
- Composition rules live in the **Hyperframes skill** \u2014 framework rules, motion
83614
+ Composition rules live in the **Hyperframes skill** - framework rules, motion
83572
83615
  principles, type system, and visual-identity hard-gate. **Load that skill
83573
83616
  before authoring any scene composition HTML under \`compositions/\`.** The same
83574
83617
  rules govern \`vibe scene lint\`, so your authored HTML and the linter stay in
@@ -83592,22 +83635,12 @@ containing live text/cards. Put ambient zoom/parallax on background or media
83592
83635
  layers only; text should enter briefly and then hold still at its final CSS
83593
83636
  position.
83594
83637
 
83595
- ### Scene composer (batch / non-agent fallback)
83596
-
83597
- When you don't want to author HTML yourself, \`vibe build --mode batch\` runs an
83598
- LLM internally with the same skill bundle. It auto-picks a provider based
83599
- on available keys (\`claude > gemini > openai\`) \u2014 pass \`--composer <name>\`
83600
- to force one:
83601
-
83602
- | Provider | Env var | Spike notes (v0.70) |
83603
- |---|---|---|
83604
- | Claude (default) | \`ANTHROPIC_API_KEY\` | ~9 s/beat. Fastest, validated baseline. |
83605
- | Gemini | \`GOOGLE_API_KEY\` | ~20 s/beat. ~2.6\xD7 cheaper than Claude. |
83606
- | OpenAI | \`OPENAI_API_KEY\` | ~70 s/beat. gpt-5 reasoning latency \u2014 opt-in only. |
83638
+ ### Scene composer (non-agent fallback)
83607
83639
 
83608
- All three pass first-shot lint at every effort tier on the \`vibeframe-promo\`
83609
- fixture. Quality on more complex storyboards may differ \u2014 fall back to
83610
- \`--composer claude\` if a non-default provider repeatedly fails lint.
83640
+ Scene HTML is authored by you, the host agent - the CLI makes no LLM call
83641
+ during \`vibe build\`. When no agent is available to author scenes, pass
83642
+ \`--composer template\` for the deterministic no-model composer
83643
+ (concat background + lower-thirds).
83611
83644
 
83612
83645
  ## Project conventions
83613
83646
 
@@ -83622,7 +83655,7 @@ var CLAUDE_MD = `@AGENTS.md
83622
83655
 
83623
83656
  # Claude Code overrides
83624
83657
 
83625
- This file imports \`AGENTS.md\` (above) \u2014 that's the canonical source.
83658
+ This file imports \`AGENTS.md\` (above) - that's the canonical source.
83626
83659
  Add anything Claude-Code-specific *below*; everything generic should
83627
83660
  stay in AGENTS.md so other agent hosts (Codex, Cursor, Aider, Gemini CLI, OpenCode) see it
83628
83661
  too.
@@ -83630,11 +83663,11 @@ too.
83630
83663
  ## Skills
83631
83664
 
83632
83665
  If you ran \`vibe init\` with Claude Code detected, the VibeFrame skill
83633
- pack is available as slash commands (consolidated to 2 in v0.62 \u2014 the
83666
+ pack is available as slash commands (consolidated to 2 in v0.62 - the
83634
83667
  overview content moved into AGENTS.md above):
83635
83668
 
83636
- - \`/vibe-pipeline\` \u2014 YAML pipeline authoring helper (Video as Code)
83637
- - \`/vibe-scene\` \u2014 per-scene HTML authoring + \`vibe build\`
83669
+ - \`/vibe-pipeline\` - YAML pipeline authoring helper (Video as Code)
83670
+ - \`/vibe-scene\` - per-scene HTML authoring + \`vibe build\`
83638
83671
 
83639
83672
  Claude-specific routing note: follow the ASSET / BUILD / REMIX decision
83640
83673
  rules in \`AGENTS.md\`. In particular, a request for one generated image or
@@ -83661,7 +83694,7 @@ var GEMINI_MD = `@AGENTS.md
83661
83694
 
83662
83695
  # Gemini CLI overrides
83663
83696
 
83664
- This project's canonical agent guidance lives in \`AGENTS.md\` \u2014 read
83697
+ This project's canonical agent guidance lives in \`AGENTS.md\` - read
83665
83698
  it first. The \`@AGENTS.md\` line above is the import marker; if
83666
83699
  Gemini CLI doesn't inline imported files in your version, open
83667
83700
  \`AGENTS.md\` directly. Both files are kept in sync by \`vibe init\`.
@@ -83678,11 +83711,11 @@ function renderEnvExample(opts = {}) {
83678
83711
  # Run \`vibe doctor\` to see what's currently detected.
83679
83712
 
83680
83713
  `;
83681
- return `# VibeFrame API keys \u2014 copy this file to \`.env\` and fill in what you need.
83714
+ return `# VibeFrame API keys - copy this file to \`.env\` and fill in what you need.
83682
83715
  # Free local fallbacks work without any keys. See README for the full list.
83683
83716
 
83684
83717
  ${fallback2}# \u2500\u2500 LLM provider / optional \`vibe agent\` fallback (pick one) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
83685
- ANTHROPIC_API_KEY= # Claude \u2014 recommended default
83718
+ ANTHROPIC_API_KEY= # Claude - recommended default
83686
83719
  OPENAI_API_KEY= # GPT-5-mini \xB7 Whisper \xB7 gpt-image-2
83687
83720
  GOOGLE_API_KEY= # Gemini \xB7 Veo
83688
83721
  XAI_API_KEY= # Grok image+video
@@ -83691,7 +83724,7 @@ OPENROUTER_API_KEY= # multiplexes any provider above
83691
83724
 
83692
83725
  # \u2500\u2500 Media providers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
83693
83726
  ELEVENLABS_API_KEY= # paid TTS / SFX / music (Kokoro is the free fallback)
83694
- FAL_API_KEY= # Seedance 2.0 \u2014 default video provider since v0.57
83727
+ FAL_API_KEY= # Seedance 2.0 - default video provider since v0.57
83695
83728
  IMGBB_API_KEY= # image hosting for Seedance/Kling image-to-video
83696
83729
  RUNWAY_API_SECRET= # Runway Gen-4.5 video
83697
83730
  KLING_API_KEY= # Kling video
@@ -84605,35 +84638,17 @@ var planCommand = new Command("plan").description("Read STORYBOARD.md and show b
84605
84638
  return;
84606
84639
  }
84607
84640
  if (maxCost !== void 0 && plan.estimatedCostUsd > maxCost) {
84608
- const warning = `Estimated cost $${plan.estimatedCostUsd.toFixed(2)} exceeds --max-cost $${maxCost.toFixed(2)}.`;
84609
- const data = {
84610
- ...plan,
84611
- costCapUsd: maxCost,
84612
- code: "COST_CAP_EXCEEDED",
84613
- message: warning,
84614
- suggestion: "Raise --max-cost or reduce the stage/provider scope.",
84615
- recoverable: true,
84616
- retryWith: [
84617
- ...plan.retryWith,
84618
- `vibe plan ${projectDirArg} --stage ${stage} --skip-backdrop --json`,
84619
- `vibe build ${projectDirArg} --stage ${stage} --max-cost ${plan.estimatedCostUsd} --json`
84620
- ].filter((value, index, all) => value.length > 0 && all.indexOf(value) === index)
84621
- };
84622
- if (isJsonMode()) {
84623
- outputSuccess({
84624
- command: "plan",
84625
- startedAt,
84626
- data,
84627
- warnings: [warning]
84628
- });
84629
- process.exitCode = 1;
84630
- return;
84631
- }
84632
84641
  exitWithError(
84633
- usageError(
84634
- `Estimated cost $${plan.estimatedCostUsd.toFixed(2)} exceeds --max-cost $${maxCost.toFixed(2)}.`,
84635
- `Raise --max-cost or reduce the stage/provider scope.`
84636
- )
84642
+ costCapError({
84643
+ estimatedCostUsd: plan.estimatedCostUsd,
84644
+ maxCostUsd: maxCost,
84645
+ retryWith: [
84646
+ ...plan.retryWith,
84647
+ `vibe plan ${projectDirArg} --stage ${stage} --skip-backdrop --json`,
84648
+ `vibe build ${projectDirArg} --stage ${stage} --max-cost ${plan.estimatedCostUsd} --json`
84649
+ ].filter((value, index, all) => value.length > 0 && all.indexOf(value) === index),
84650
+ data: { ...plan, costCapUsd: maxCost }
84651
+ })
84637
84652
  );
84638
84653
  }
84639
84654
  if (isJsonMode()) {
@@ -84844,38 +84859,18 @@ Advanced equivalent: \`vibe scene build\`.`
84844
84859
  return;
84845
84860
  }
84846
84861
  if (maxCostUsd !== void 0 && plan.estimatedCostUsd > maxCostUsd) {
84847
- const warning = `Estimated cost $${plan.estimatedCostUsd.toFixed(2)} exceeds --max-cost $${maxCostUsd.toFixed(2)}.`;
84848
- const retryWith = unique6([
84849
- ...plan.retryWith,
84850
- `vibe build ${projectDirArg} --stage ${stage} --skip-backdrop --json`,
84851
- `vibe build ${projectDirArg} --stage ${stage} --max-cost ${plan.estimatedCostUsd} --json`
84852
- ]);
84853
- if (isJsonMode() || isQuietMode()) {
84854
- outputSuccess({
84855
- command: "build",
84856
- startedAt,
84857
- dryRun: true,
84858
- warnings: [warning],
84859
- data: {
84860
- params,
84861
- plan,
84862
- costCapUsd: maxCostUsd,
84863
- code: "COST_CAP_EXCEEDED",
84864
- message: warning,
84865
- suggestion: "Raise --max-cost or reduce the stage/provider scope.",
84866
- retryWith,
84867
- recoverable: true
84868
- }
84869
- });
84870
- process.exitCode = 1;
84871
- return;
84872
- }
84873
- console.log(source_default.red(warning));
84874
- if (retryWith.length > 0) {
84875
- console.log(source_default.dim(`Retry: ${retryWith[0]}`));
84876
- }
84877
- process.exitCode = 1;
84878
- return;
84862
+ exitWithError(
84863
+ costCapError({
84864
+ estimatedCostUsd: plan.estimatedCostUsd,
84865
+ maxCostUsd,
84866
+ retryWith: unique6([
84867
+ ...plan.retryWith,
84868
+ `vibe build ${projectDirArg} --stage ${stage} --skip-backdrop --json`,
84869
+ `vibe build ${projectDirArg} --stage ${stage} --max-cost ${plan.estimatedCostUsd} --json`
84870
+ ]),
84871
+ data: { params, plan, costCapUsd: maxCostUsd }
84872
+ })
84873
+ );
84879
84874
  }
84880
84875
  if (!isJsonMode() && !isQuietMode()) {
84881
84876
  printBuildDryRun(projectDirArg, params, plan);
@@ -85143,7 +85138,7 @@ function printNeedsAuthor(result) {
85143
85138
  console.log(" Then run: vibe build");
85144
85139
  console.log(
85145
85140
  source_default.dim(
85146
- " Use `vibe build --mode batch` when you want the CLI to call an LLM composer instead."
85141
+ " Use `vibe build --composer template` for the deterministic no-model composer instead."
85147
85142
  )
85148
85143
  );
85149
85144
  }
@@ -85798,7 +85793,7 @@ var doctorCommand = new Command("doctor").description("Check system health and a
85798
85793
  `
85799
85794
  Examples:
85800
85795
  $ vibe doctor Compact health summary (issues + Ready %)
85801
- $ vibe doctor --verbose Full report \u2014 all providers, composer, free commands
85796
+ $ vibe doctor --verbose Full report - all providers, composer, free commands
85802
85797
  $ vibe doctor --test-keys Validate each configured key against its provider
85803
85798
  $ vibe doctor --json Machine-readable output
85804
85799
  `
@@ -86140,11 +86135,11 @@ function printReport(results, opts = { verbose: false }) {
86140
86135
  );
86141
86136
  if (sc.composer) {
86142
86137
  console.log(
86143
- ` Revise LLM ${source_default.green("OK")} ${source_default.dim(`${composerLabel(sc.composer)} (${sc.composerEnvVar}) \u2014 powers 'vibe storyboard revise'`)}`
86138
+ ` Revise LLM ${source_default.green("OK")} ${source_default.dim(`${composerLabel(sc.composer)} (${sc.composerEnvVar}) - powers 'vibe storyboard revise'`)}`
86144
86139
  );
86145
86140
  } else {
86146
86141
  console.log(
86147
- ` Revise LLM ${source_default.yellow("--")} ${source_default.dim("no ANTHROPIC_API_KEY / GOOGLE_API_KEY / OPENAI_API_KEY \u2014 'vibe storyboard revise' unavailable")}`
86142
+ ` Revise LLM ${source_default.yellow("--")} ${source_default.dim("no ANTHROPIC_API_KEY / GOOGLE_API_KEY / OPENAI_API_KEY - 'vibe storyboard revise' unavailable")}`
86148
86143
  );
86149
86144
  }
86150
86145
  if (sc.sceneProjectInCwd) {
@@ -86158,7 +86153,7 @@ function printReport(results, opts = { verbose: false }) {
86158
86153
  }
86159
86154
  } else {
86160
86155
  console.log(
86161
- ` HF rules ${source_default.dim("(no STORYBOARD.md in cwd \u2014 rules are per-scene-project)")}`
86156
+ ` HF rules ${source_default.dim("(no STORYBOARD.md in cwd - rules are per-scene-project)")}`
86162
86157
  );
86163
86158
  }
86164
86159
  }
@@ -86282,7 +86277,7 @@ async function runLiveKeyTests(results) {
86282
86277
  );
86283
86278
  const configured = Object.entries(results.providers).filter(([, info]) => info.configured);
86284
86279
  if (configured.length === 0) {
86285
- console.log(source_default.dim(" No keys configured \u2014 nothing to test."));
86280
+ console.log(source_default.dim(" No keys configured - nothing to test."));
86286
86281
  return;
86287
86282
  }
86288
86283
  const { testKey: testKey2 } = await Promise.resolve().then(() => (init_key_live_test(), key_live_test_exports));
@@ -87236,7 +87231,7 @@ async function registerAllTools(registry) {
87236
87231
  // src/agent/prompts/system.ts
87237
87232
  function getSystemPrompt(context) {
87238
87233
  const projectInfo = context.projectPath ? `Current project: ${context.projectPath}` : "No timeline loaded. Use timeline_create or project_create to start.";
87239
- return `You are VibeFrame, an AI video editing assistant. You help users edit videos through natural language commands.
87234
+ return `You are VibeFrame, an AI video generation and editing assistant. You help users generate video from frontier models on their own provider keys - behind dry runs and cost caps - and edit the results, through natural language commands.
87240
87235
 
87241
87236
  ## Current Context
87242
87237
  - Working directory: ${context.workingDirectory}
@@ -87244,10 +87239,10 @@ function getSystemPrompt(context) {
87244
87239
 
87245
87240
  ## Your Capabilities
87246
87241
  You have access to tools for:
87247
- 1. **Timeline Management**: Create, open, save, and modify low-level timeline JSON state
87248
- 2. **Timeline Editing**: Add sources, create clips, add tracks, apply effects, trim, split, move, and delete clips
87249
- 3. **Media Analysis**: Detect scenes, silence, and beats in media files
87250
- 4. **AI Generation**: Generate images, videos, TTS, sound effects, music, and more
87242
+ 1. **AI Generation**: Generate images, videos, TTS, sound effects, music, and more on the user's provider keys
87243
+ 2. **Media Analysis**: Detect scenes, silence, and beats in media files
87244
+ 3. **Timeline Management**: Create, open, save, and modify low-level timeline JSON state
87245
+ 4. **Timeline Editing**: Add sources, create clips, add tracks, apply effects, trim, split, move, and delete clips
87251
87246
  5. **Export**: Export projects to video files
87252
87247
 
87253
87248
  ## Guidelines
@@ -88203,20 +88198,24 @@ async function markBannerShown() {
88203
88198
  function showFirstRunBanner() {
88204
88199
  console.log();
88205
88200
  console.log(source_default.cyan.bold(" Welcome to VibeFrame!"));
88206
- console.log(source_default.dim(" AI-native video editing from your terminal."));
88201
+ console.log(source_default.dim(" Frontier video generation for your coding agent. Your keys, your ceiling."));
88207
88202
  console.log();
88208
88203
  console.log(
88209
- ` ${source_default.white("1.")} ${source_default.green("vibe setup")} Configure API keys ${source_default.dim("(1 min)")}`
88204
+ ` ${source_default.white("1.")} ${source_default.green('vibe init demo --from "30s video"')} Scaffold a project ${source_default.dim("(no key needed)")}`
88205
+ );
88206
+ console.log(
88207
+ ` ${source_default.white("2.")} ${source_default.green("vibe build demo --dry-run")} Price it before any spend`
88208
+ );
88209
+ console.log(
88210
+ ` ${source_default.white("3.")} ${source_default.green("vibe setup")} Add provider keys when a step generates`
88210
88211
  );
88211
- console.log(` ${source_default.white("2.")} ${source_default.green("vibe doctor")} Check system health`);
88212
- console.log(` ${source_default.white("3.")} ${source_default.green("vibe --help")} See all commands`);
88213
88212
  console.log();
88214
88213
  console.log(source_default.dim(" Try without keys:"));
88215
88214
  console.log(
88216
- ` ${source_default.green("vibe demo")} Run sample edits on a test video`
88215
+ ` ${source_default.green("vibe build demo --dry-run --max-cost 5")} See the cost gate refuse an over-budget build`
88217
88216
  );
88217
+ console.log(source_default.dim(" vibe demo Run sample edits on a test video"));
88218
88218
  console.log(source_default.dim(" vibe edit silence-cut video.mp4 -o clean.mp4"));
88219
- console.log(source_default.dim(" vibe detect scenes video.mp4"));
88220
88219
  console.log();
88221
88220
  }
88222
88221
 
@@ -88280,7 +88279,7 @@ async function readStdin() {
88280
88279
  return Buffer.concat(chunks).toString("utf-8").trim();
88281
88280
  }
88282
88281
  var program2 = new Command();
88283
- program2.name("vibe").showSuggestionAfterError(true).description("VibeFrame CLI - video projects, AI media generation, and workflow automation").version(package_default.version).option("--json", "Output in JSON format").option("-q, --quiet", "Output only the primary result value (path, URL, or ID)").option("--fields <fields>", "Limit JSON output to specific fields (comma-separated)").option("--stdin", "Read options from stdin as JSON (for agent/script use)").option("--describe", "Show JSON schema for the command and exit (no execution)").exitOverride().configureOutput({
88282
+ program2.name("vibe").showSuggestionAfterError(true).description("VibeFrame CLI - AI video generation on your own provider keys, behind dry runs and a hard cost cap").version(package_default.version).option("--json", "Output in JSON format").option("-q, --quiet", "Output only the primary result value (path, URL, or ID)").option("--fields <fields>", "Limit JSON output to specific fields (comma-separated)").option("--stdin", "Read options from stdin as JSON (for agent/script use)").option("--describe", "Show JSON schema for the command and exit (no execution)").exitOverride().configureOutput({
88284
88283
  outputError: (str, write2) => {
88285
88284
  if (process.env.VIBE_JSON_OUTPUT === "1" || process.argv.includes("--json")) {
88286
88285
  const err = {