@vibeframe/cli 0.75.0 → 0.77.0

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 (2) hide show
  1. package/dist/index.js +64 -61
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -18722,8 +18722,8 @@ var init_elevenlabs = __esm({
18722
18722
  "generate speech",
18723
18723
  "generate sound-effect",
18724
18724
  "generate music",
18725
- "audio voices",
18726
- "audio voice-clone",
18725
+ "audio list-voices",
18726
+ "audio clone-voice",
18727
18727
  "audio dub"
18728
18728
  ]
18729
18729
  });
@@ -25999,7 +25999,7 @@ function buildEmptyRootHtml(opts) {
25999
25999
  }
26000
26000
  function buildDesignMd(opts) {
26001
26001
  const { name, style } = opts;
26002
- 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 styles\` if you want a credible starting point.`;
26002
+ 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.`;
26003
26003
  const moodLine = style ? `**Mood:** ${style.mood} \xB7 **Best for:** ${style.bestFor}` : `**Mood:** _(one line \u2014 what should the viewer FEEL?)_`;
26004
26004
  const palette = style ? `${style.palette.map((c) => `- \`${c}\``).join("\n")}
26005
26005
 
@@ -26057,7 +26057,7 @@ ${avoid}
26057
26057
 
26058
26058
  ---
26059
26059
 
26060
- _Browse other named styles: \`vibe scene styles\`_
26060
+ _Browse other named styles: \`vibe scene list-styles\`_
26061
26061
  ${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>"\`._`}
26062
26062
  `;
26063
26063
  }
@@ -26123,7 +26123,7 @@ typography, motion, and transition rules. Both the agent-driven path and
26123
26123
  the fallback emit reference it; scenes that contradict DESIGN.md are
26124
26124
  rejected by the Hyperframes \`hyperframes\` skill.
26125
26125
 
26126
- Browse named styles: \`vibe scene styles\`. Re-seed from one with
26126
+ Browse named styles: \`vibe scene list-styles\`. Re-seed from one with
26127
26127
  \`vibe scene init . --visual-style "Swiss Pulse"\` (idempotent).
26128
26128
 
26129
26129
  ## Skills \u2014 USE THESE FIRST
@@ -29405,7 +29405,7 @@ Examples:
29405
29405
  $ vibe scene lint # Validate every scene against composition rules
29406
29406
  $ vibe scene lint --fix # Auto-fix mechanical issues (e.g. missing class="clip")
29407
29407
  $ vibe scene lint --json # Structured output for agent loops
29408
- $ vibe scene styles # Browse seed visual styles for DESIGN.md
29408
+ $ vibe scene list-styles # Browse seed visual styles for DESIGN.md
29409
29409
 
29410
29410
  For the project flow (init / build / render), use the top-level commands.
29411
29411
  The \`scene init\`, \`scene build\`, and \`scene render\` legacy aliases
@@ -29520,13 +29520,13 @@ Run 'vibe schema scene.<command>' for structured parameter info.`);
29520
29520
  console.log();
29521
29521
  console.log(source_default.dim("Re-run with --json to get the full per-beat userPrompt + cues for direct consumption."));
29522
29522
  });
29523
- sceneCommand.command("styles").description("List vendored visual styles (or show one) for DESIGN.md seeding").argument("[name]", "Style name to inspect (omit to list all)").action((name) => {
29523
+ sceneCommand.command("list-styles").description("List vendored visual styles (or show one) for DESIGN.md seeding").argument("[name]", "Style name to inspect (omit to list all)").action((name) => {
29524
29524
  const startedAt = Date.now();
29525
29525
  if (!name) {
29526
29526
  const all = listVisualStyles();
29527
29527
  if (isJsonMode()) {
29528
29528
  outputSuccess({
29529
- command: "scene styles",
29529
+ command: "scene list-styles",
29530
29530
  startedAt,
29531
29531
  data: {
29532
29532
  count: all.length,
@@ -29550,7 +29550,7 @@ Run 'vibe schema scene.<command>' for structured parameter info.`);
29550
29550
  );
29551
29551
  }
29552
29552
  console.log();
29553
- console.log(source_default.dim("Show details: "), source_default.cyan('vibe scene styles "<name>"'));
29553
+ console.log(source_default.dim("Show details: "), source_default.cyan('vibe scene list-styles "<name>"'));
29554
29554
  console.log(source_default.dim("Seed DESIGN.md:"), source_default.cyan('vibe scene init <dir> --visual-style "<name>"'));
29555
29555
  return;
29556
29556
  }
@@ -29566,7 +29566,7 @@ Run 'vibe schema scene.<command>' for structured parameter info.`);
29566
29566
  }
29567
29567
  if (isJsonMode()) {
29568
29568
  outputSuccess({
29569
- command: "scene styles",
29569
+ command: "scene list-styles",
29570
29570
  startedAt,
29571
29571
  data: { style }
29572
29572
  });
@@ -38839,7 +38839,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
38839
38839
  exitWithError(generalError(`Frame interpolation failed: ${msg}`));
38840
38840
  }
38841
38841
  });
38842
- editCommand.command("upscale-video").description("Upscale video resolution using AI or FFmpeg").argument("<video>", "Video file path").option("-o, --output <path>", "Output file path").option("-s, --scale <factor>", "Scale factor: 2 or 4", "2").option("-m, --model <model>", "Model: real-esrgan, topaz", "real-esrgan").option("--ffmpeg", "Use FFmpeg lanczos (free, no API)").option("-k, --api-key <key>", "Replicate API token (or set REPLICATE_API_TOKEN env)").option("--no-wait", "Start processing and return task ID without waiting").option("--dry-run", "Preview parameters without executing").action(async (videoPath, options) => {
38842
+ editCommand.command("upscale").description("Upscale video resolution using AI or FFmpeg").argument("<video>", "Video file path").option("-o, --output <path>", "Output file path").option("-s, --scale <factor>", "Scale factor: 2 or 4", "2").option("-m, --model <model>", "Model: real-esrgan, topaz", "real-esrgan").option("--ffmpeg", "Use FFmpeg lanczos (free, no API)").option("-k, --api-key <key>", "Replicate API token (or set REPLICATE_API_TOKEN env)").option("--no-wait", "Start processing and return task ID without waiting").option("--dry-run", "Preview parameters without executing").action(async (videoPath, options) => {
38843
38843
  const startedAt = Date.now();
38844
38844
  try {
38845
38845
  if (options.output) {
@@ -38852,7 +38852,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
38852
38852
  }
38853
38853
  if (options.dryRun) {
38854
38854
  outputSuccess({
38855
- command: "edit upscale-video",
38855
+ command: "edit upscale",
38856
38856
  startedAt,
38857
38857
  dryRun: true,
38858
38858
  data: {
@@ -38888,7 +38888,7 @@ Run 'vibe schema edit.<command>' for structured parameter info.
38888
38888
  spinner3.succeed(source_default.green(`Upscaled to ${newWidth}x${newHeight}`));
38889
38889
  if (isJsonMode()) {
38890
38890
  outputSuccess({
38891
- command: "edit upscale-video",
38891
+ command: "edit upscale",
38892
38892
  startedAt,
38893
38893
  data: {
38894
38894
  dimensions: `${newWidth}x${newHeight}`,
@@ -57372,10 +57372,10 @@ var init_scene2 = __esm({
57372
57372
  )
57373
57373
  });
57374
57374
  sceneStylesTool = defineTool({
57375
- name: "scene_styles",
57375
+ name: "scene_list_styles",
57376
57376
  category: "scene",
57377
57377
  cost: "free",
57378
- description: "List the 8 vendored visual identities available for `scene_init --visual-style` (Swiss Pulse, Data Drift, \u2026) or, when `name` is provided, return the full DESIGN.md hard-gate body for one style. The DESIGN.md content is what the LLM uses as a non-negotiable visual rulebook during compose-scenes-with-skills.",
57378
+ description: "List the 8 vendored visual identities available for `init --visual-style` (Swiss Pulse, Data Drift, \u2026) or, when `name` is provided, return the full DESIGN.md hard-gate body for one style. The DESIGN.md content is what the LLM uses as a non-negotiable visual rulebook during compose-scenes-with-skills.",
57379
57379
  schema: sceneStylesSchema,
57380
57380
  async execute(args) {
57381
57381
  if (args.name) {
@@ -57383,7 +57383,7 @@ var init_scene2 = __esm({
57383
57383
  if (!style) {
57384
57384
  return {
57385
57385
  success: false,
57386
- error: `Unknown visual style "${args.name}". Run scene_styles with no name to list all 8.`
57386
+ error: `Unknown visual style "${args.name}". Run scene_list_styles with no name to list all 8.`
57387
57387
  };
57388
57388
  }
57389
57389
  return {
@@ -57423,7 +57423,7 @@ var init_scene2 = __esm({
57423
57423
  (s) => ` \u2022 ${s.name} (${s.slug}) \u2014 ${s.mood}; best for ${s.bestFor}`
57424
57424
  ),
57425
57425
  ``,
57426
- `Run scene_styles { name: "<slug>" } to fetch the full DESIGN.md hard-gate body for one style.`
57426
+ `Run scene_list_styles { name: "<slug>" } to fetch the full DESIGN.md hard-gate body for one style.`
57427
57427
  ]
57428
57428
  };
57429
57429
  }
@@ -57435,7 +57435,7 @@ var init_scene2 = __esm({
57435
57435
  duration: external_exports.number().optional().describe("Default root composition duration in seconds. Default 10.")
57436
57436
  });
57437
57437
  sceneInitTool = defineTool({
57438
- name: "scene_init",
57438
+ name: "init",
57439
57439
  category: "scene",
57440
57440
  cost: "free",
57441
57441
  description: "Scaffold a new VibeFrame video scene project. Supports minimal, agent, and full profiles; full includes the current HTML render backend metadata. Idempotent: re-running keeps user-authored files and merges backend config instead of overwriting. No API keys required.",
@@ -57581,7 +57581,7 @@ var init_scene2 = __esm({
57581
57581
  workers: external_exports.number().optional().describe("Capture worker count (1-16). Default 1.")
57582
57582
  });
57583
57583
  sceneRenderTool = defineTool({
57584
- name: "scene_render",
57584
+ name: "render",
57585
57585
  category: "scene",
57586
57586
  cost: "free",
57587
57587
  description: "Render a scene project to MP4/WebM/MOV via the Hyperframes producer. Requires Chrome installed locally. Output defaults to renders/<projectName>-<isoStamp>.<format>.",
@@ -57598,7 +57598,7 @@ var init_scene2 = __esm({
57598
57598
  workers: args.workers
57599
57599
  });
57600
57600
  if (!result.success) {
57601
- return { success: false, error: result.error ?? "scene_render failed" };
57601
+ return { success: false, error: result.error ?? "render failed" };
57602
57602
  }
57603
57603
  return {
57604
57604
  success: true,
@@ -57636,10 +57636,10 @@ var init_scene2 = __esm({
57636
57636
  force: external_exports.boolean().optional().describe("Re-dispatch primitives even when cached assets exist.")
57637
57637
  });
57638
57638
  sceneBuildTool = defineTool({
57639
- name: "scene_build",
57639
+ name: "build",
57640
57640
  category: "scene",
57641
57641
  cost: "high",
57642
- description: "v0.60 one-shot orchestrator: read STORYBOARD.md per-beat YAML cues (narration / backdrop / duration), dispatch TTS + image generation per beat, compose scene HTML via the compose-scenes-with-skills pipeline, then render to MP4. Use this instead of chaining scene_init + scene_add + scene_render manually. Caches by SHA256 of (DESIGN.md + cue body) so re-runs are idempotent and cheap.",
57642
+ description: "v0.60 one-shot orchestrator: read STORYBOARD.md per-beat YAML cues (narration / backdrop / duration), dispatch TTS + image generation per beat, compose scene HTML via the compose-scenes-with-skills pipeline, then render to MP4. Use this instead of chaining init + scene_add + render manually. Caches by SHA256 of (DESIGN.md + cue body) so re-runs are idempotent and cheap.",
57643
57643
  schema: sceneBuildSchema,
57644
57644
  async execute(args, ctx) {
57645
57645
  const projectDir = args.projectDir ? resolve55(ctx.workingDirectory, args.projectDir) : ctx.workingDirectory;
@@ -57659,7 +57659,7 @@ var init_scene2 = __esm({
57659
57659
  force: args.force
57660
57660
  });
57661
57661
  if (!result.success) {
57662
- return { success: false, error: result.error ?? "scene_build failed" };
57662
+ return { success: false, error: result.error ?? "build failed" };
57663
57663
  }
57664
57664
  return {
57665
57665
  success: true,
@@ -57742,7 +57742,7 @@ var init_scene2 = __esm({
57742
57742
  name: "scene_compose_prompts",
57743
57743
  category: "scene",
57744
57744
  cost: "free",
57745
- description: "Emit the per-beat compose plan for the host agent to author scene HTML itself. Reads STORYBOARD.md + DESIGN.md and returns each beat's outputPath + userPrompt + cues + body, plus references to the project's SKILL.md (Hyperframes rules) and DESIGN.md (visual identity). The host agent writes each compositions/scene-<id>.html file directly \u2014 VibeFrame makes NO LLM call here. Pairs with scene_install_skill (Phase H1). Phase H2 of the agentic-native composer plan; the internal-LLM batch path (scene_build) remains as a fallback for non-agent contexts.",
57745
+ description: "Emit the per-beat compose plan for the host agent to author scene HTML itself. Reads STORYBOARD.md + DESIGN.md and returns each beat's outputPath + userPrompt + cues + body, plus references to the project's SKILL.md (Hyperframes rules) and DESIGN.md (visual identity). The host agent writes each compositions/scene-<id>.html file directly \u2014 VibeFrame makes NO LLM call here. Pairs with scene_install_skill (Phase H1). Phase H2 of the agentic-native composer plan; the internal-LLM batch path (build) remains as a fallback for non-agent contexts.",
57746
57746
  schema: sceneComposePromptsSchema,
57747
57747
  async execute(args, ctx) {
57748
57748
  const projectDir = resolve55(ctx.workingDirectory, args.projectDir);
@@ -57842,7 +57842,7 @@ var init_audio2 = __esm({
57842
57842
  }
57843
57843
  });
57844
57844
  audioVoiceCloneTool = defineTool({
57845
- name: "audio_voice_clone",
57845
+ name: "audio_clone_voice",
57846
57846
  category: "audio",
57847
57847
  cost: "low",
57848
57848
  description: "Clone a voice from audio samples using ElevenLabs. Requires ELEVENLABS_API_KEY.",
@@ -58388,7 +58388,7 @@ var init_analyze = __esm({
58388
58388
  init_ai_review();
58389
58389
  init_ai_suggest_edit();
58390
58390
  analyzeMediaTool = defineTool({
58391
- name: "analyze_media",
58391
+ name: "inspect_media",
58392
58392
  category: "analyze",
58393
58393
  cost: "low",
58394
58394
  description: "Analyze media (image, video, or YouTube URL) using Gemini AI. Requires GOOGLE_API_KEY.",
@@ -58416,7 +58416,7 @@ var init_analyze = __esm({
58416
58416
  }
58417
58417
  });
58418
58418
  analyzeVideoTool = defineTool({
58419
- name: "analyze_video",
58419
+ name: "inspect_video",
58420
58420
  category: "analyze",
58421
58421
  cost: "low",
58422
58422
  description: "Analyze video content using Gemini AI with temporal understanding. Requires GOOGLE_API_KEY.",
@@ -58444,7 +58444,7 @@ var init_analyze = __esm({
58444
58444
  }
58445
58445
  });
58446
58446
  analyzeReviewTool = defineTool({
58447
- name: "analyze_review",
58447
+ name: "inspect_review",
58448
58448
  category: "analyze",
58449
58449
  cost: "low",
58450
58450
  description: "AI video review: analyzes quality, suggests fixes, and optionally auto-applies them. Requires GOOGLE_API_KEY.",
@@ -58472,7 +58472,7 @@ var init_analyze = __esm({
58472
58472
  }
58473
58473
  });
58474
58474
  analyzeSuggestTool = defineTool({
58475
- name: "analyze_suggest",
58475
+ name: "inspect_suggest",
58476
58476
  category: "analyze",
58477
58477
  cost: "low",
58478
58478
  description: "Get natural-language edit suggestions for a project from Gemini. Returns suggestions array with type/confidence/clipIds. With `apply: true`, applies the first suggestion in place. Requires GOOGLE_API_KEY.",
@@ -58853,7 +58853,7 @@ var init_pipeline2 = __esm({
58853
58853
  init_ai_highlights();
58854
58854
  init_pipeline();
58855
58855
  pipelineHighlightsTool = defineTool({
58856
- name: "pipeline_highlights",
58856
+ name: "remix_highlights",
58857
58857
  category: "pipeline",
58858
58858
  cost: "low",
58859
58859
  description: "Extract highlight clips from a longer video using AI analysis. Requires OPENAI_API_KEY+ANTHROPIC_API_KEY or GOOGLE_API_KEY (with --use-gemini).",
@@ -58886,10 +58886,10 @@ var init_pipeline2 = __esm({
58886
58886
  }
58887
58887
  });
58888
58888
  pipelineAutoShortsTool = defineTool({
58889
- name: "pipeline_auto_shorts",
58889
+ name: "remix_auto_shorts",
58890
58890
  category: "pipeline",
58891
58891
  cost: "medium",
58892
- description: "Automatically generate short-form content (Reels/TikTok/Shorts) from a longer video. Same API key requirements as pipeline_highlights.",
58892
+ description: "Automatically generate short-form content (Reels/TikTok/Shorts) from a longer video. Same API key requirements as remix_highlights.",
58893
58893
  schema: external_exports.object({
58894
58894
  video: external_exports.string().describe("Path to the input video file"),
58895
58895
  outputDir: external_exports.string().optional().describe("Output directory for shorts"),
@@ -58923,7 +58923,7 @@ var init_pipeline2 = __esm({
58923
58923
  }
58924
58924
  });
58925
58925
  pipelineRunTool = defineTool({
58926
- name: "pipeline_run",
58926
+ name: "run",
58927
58927
  category: "pipeline",
58928
58928
  cost: "very-high",
58929
58929
  surfaces: ["mcp"],
@@ -59002,7 +59002,7 @@ var init_pipeline2 = __esm({
59002
59002
  }
59003
59003
  });
59004
59004
  pipelineRegenerateSceneTool = defineTool({
59005
- name: "pipeline_regenerate_scene",
59005
+ name: "remix_regenerate_scene",
59006
59006
  category: "pipeline",
59007
59007
  cost: "high",
59008
59008
  description: "Regenerate specific scenes against an existing storyboard.{yaml,json} on disk. Can regenerate video, image, or narration independently.",
@@ -61650,7 +61650,7 @@ Safe to invoke on user-provided projects.
61650
61650
 
61651
61651
  \`\`\`bash
61652
61652
  vibe scene init <dir> [-r 16:9|9:16|1:1|4:5] [-d <sec>] [--visual-style "<name>"]
61653
- vibe scene styles [<name>] # list / show vendored visual identities
61653
+ vibe scene list-styles [<name>] # list / show vendored visual identities
61654
61654
  vibe scene install-skill [<dir>] [--host all] # retroactive composition-rules install
61655
61655
  vibe scene add <name> --style <preset> [...]
61656
61656
  vibe scene compose-prompts [<dir>] [--beat <id>] # H2: emit plan, no LLM call
@@ -61838,7 +61838,7 @@ overlay, etc.) \u2014 useful at the tail of a pipeline.
61838
61838
  ],
61839
61839
  relatedCommands: [
61840
61840
  "vibe init",
61841
- "vibe scene styles",
61841
+ "vibe scene list-styles",
61842
61842
  "vibe scene install-skill",
61843
61843
  "vibe scene compose-prompts",
61844
61844
  "vibe build",
@@ -62167,7 +62167,7 @@ init_source();
62167
62167
  // package.json
62168
62168
  var package_default = {
62169
62169
  name: "@vibeframe/cli",
62170
- version: "0.75.0",
62170
+ version: "0.77.0",
62171
62171
  description: "VibeFrame CLI - natural language video editing from the terminal",
62172
62172
  private: false,
62173
62173
  license: "MIT",
@@ -62584,12 +62584,12 @@ var timelineCommand = new Command("timeline").description("Timeline editing comm
62584
62584
  Examples:
62585
62585
  $ vibe timeline add-source project.vibe.json video.mp4 # Returns source ID
62586
62586
  $ vibe timeline add-clip project.vibe.json <source-id> # Add clip from source
62587
- $ vibe timeline trim project.vibe.json <clip-id> --start 5 --end 30
62588
- $ vibe timeline split project.vibe.json <clip-id> --time 10
62587
+ $ vibe timeline trim-clip project.vibe.json <clip-id> --start 5 --end 30
62588
+ $ vibe timeline split-clip project.vibe.json <clip-id> --time 10
62589
62589
  $ vibe timeline list project.vibe.json --json
62590
- $ vibe timeline delete project.vibe.json <clip-id>
62590
+ $ vibe timeline delete-clip project.vibe.json <clip-id>
62591
62591
 
62592
- Typical workflow: create project \u2192 add-source \u2192 add-clip \u2192 trim/split \u2192 export
62592
+ Typical workflow: create project \u2192 add-source \u2192 add-clip \u2192 trim-clip/split-clip \u2192 export
62593
62593
  Cost: Free (no API keys needed).
62594
62594
  Run 'vibe schema timeline.<command>' for structured parameter info.`);
62595
62595
  timelineCommand.command("add-source").description("Add a media source to the project").argument("<project>", "Project file path").argument("<media>", "Media file path").option("-n, --name <name>", "Source name (defaults to filename)").option("-t, --type <type>", "Media type (video, audio, image, lottie)").option("-d, --duration <seconds>", "Duration in seconds (required for images)").option("--dry-run", "Preview parameters without executing").action(async (projectPath, mediaPath, options) => {
@@ -62865,14 +62865,14 @@ timelineCommand.command("add-effect").description("Add an effect to a clip").arg
62865
62865
  exitWithError(generalError(`Failed to add effect: ${msg}`));
62866
62866
  }
62867
62867
  });
62868
- timelineCommand.command("trim").description("Trim a clip").argument("<project>", "Project file path").argument("<clip-id>", "Clip ID").option("--start <seconds>", "New start time").option("--duration <seconds>", "New duration").option("--dry-run", "Preview parameters without executing").action(async (projectPath, clipId, options) => {
62868
+ timelineCommand.command("trim-clip").description("Trim a clip").argument("<project>", "Project file path").argument("<clip-id>", "Clip ID").option("--start <seconds>", "New start time").option("--duration <seconds>", "New duration").option("--dry-run", "Preview parameters without executing").action(async (projectPath, clipId, options) => {
62869
62869
  const startedAt = Date.now();
62870
62870
  const spinner2 = ora("Trimming clip...").start();
62871
62871
  try {
62872
62872
  validateResourceId(clipId);
62873
62873
  if (options.dryRun) {
62874
62874
  outputSuccess({
62875
- command: "timeline trim",
62875
+ command: "timeline trim-clip",
62876
62876
  startedAt,
62877
62877
  dryRun: true,
62878
62878
  data: {
@@ -62906,7 +62906,7 @@ timelineCommand.command("trim").description("Trim a clip").argument("<project>",
62906
62906
  spinner2.succeed(source_default.green("Clip trimmed"));
62907
62907
  if (isJsonMode()) {
62908
62908
  outputSuccess({
62909
- command: "timeline trim",
62909
+ command: "timeline trim-clip",
62910
62910
  startedAt,
62911
62911
  data: {
62912
62912
  id: updatedClip.id,
@@ -63027,14 +63027,14 @@ timelineCommand.command("list").description("List timeline contents").argument("
63027
63027
  exitWithError(generalError(`Failed to list timeline: ${msg}`));
63028
63028
  }
63029
63029
  });
63030
- timelineCommand.command("split").description("Split a clip at a specific time").argument("<project>", "Project file path").argument("<clip-id>", "Clip ID to split").option("-t, --time <seconds>", "Split time relative to clip start", "0").option("--dry-run", "Preview parameters without executing").action(async (projectPath, clipId, options) => {
63030
+ timelineCommand.command("split-clip").description("Split a clip at a specific time").argument("<project>", "Project file path").argument("<clip-id>", "Clip ID to split").option("-t, --time <seconds>", "Split time relative to clip start", "0").option("--dry-run", "Preview parameters without executing").action(async (projectPath, clipId, options) => {
63031
63031
  const startedAt = Date.now();
63032
63032
  const spinner2 = ora("Splitting clip...").start();
63033
63033
  try {
63034
63034
  validateResourceId(clipId);
63035
63035
  if (options.dryRun) {
63036
63036
  outputSuccess({
63037
- command: "timeline split",
63037
+ command: "timeline split-clip",
63038
63038
  startedAt,
63039
63039
  dryRun: true,
63040
63040
  data: {
@@ -63071,7 +63071,7 @@ timelineCommand.command("split").description("Split a clip at a specific time").
63071
63071
  spinner2.succeed(source_default.green("Clip split successfully"));
63072
63072
  if (isJsonMode()) {
63073
63073
  outputSuccess({
63074
- command: "timeline split",
63074
+ command: "timeline split-clip",
63075
63075
  startedAt,
63076
63076
  data: {
63077
63077
  first: { id: first.id, duration: first.duration },
@@ -63089,14 +63089,14 @@ timelineCommand.command("split").description("Split a clip at a specific time").
63089
63089
  exitWithError(generalError(`Failed to split clip: ${msg}`));
63090
63090
  }
63091
63091
  });
63092
- timelineCommand.command("duplicate").description("Duplicate a clip").argument("<project>", "Project file path").argument("<clip-id>", "Clip ID to duplicate").option("-t, --time <seconds>", "Start time for duplicate (default: after original)").option("--dry-run", "Preview parameters without executing").action(async (projectPath, clipId, options) => {
63092
+ timelineCommand.command("duplicate-clip").description("Duplicate a clip").argument("<project>", "Project file path").argument("<clip-id>", "Clip ID to duplicate").option("-t, --time <seconds>", "Start time for duplicate (default: after original)").option("--dry-run", "Preview parameters without executing").action(async (projectPath, clipId, options) => {
63093
63093
  const startedAt = Date.now();
63094
63094
  const spinner2 = ora("Duplicating clip...").start();
63095
63095
  try {
63096
63096
  validateResourceId(clipId);
63097
63097
  if (options.dryRun) {
63098
63098
  outputSuccess({
63099
- command: "timeline duplicate",
63099
+ command: "timeline duplicate-clip",
63100
63100
  startedAt,
63101
63101
  dryRun: true,
63102
63102
  data: {
@@ -63128,7 +63128,7 @@ timelineCommand.command("duplicate").description("Duplicate a clip").argument("<
63128
63128
  spinner2.succeed(source_default.green(`Clip duplicated: ${duplicated.id}`));
63129
63129
  if (isJsonMode()) {
63130
63130
  outputSuccess({
63131
- command: "timeline duplicate",
63131
+ command: "timeline duplicate-clip",
63132
63132
  startedAt,
63133
63133
  data: {
63134
63134
  id: duplicated.id,
@@ -63148,14 +63148,14 @@ timelineCommand.command("duplicate").description("Duplicate a clip").argument("<
63148
63148
  exitWithError(generalError(`Failed to duplicate clip: ${msg}`));
63149
63149
  }
63150
63150
  });
63151
- timelineCommand.command("delete").description("Delete a clip from the timeline").argument("<project>", "Project file path").argument("<clip-id>", "Clip ID to delete").option("--dry-run", "Preview parameters without executing").action(async (projectPath, clipId, options) => {
63151
+ timelineCommand.command("delete-clip").description("Delete a clip from the timeline").argument("<project>", "Project file path").argument("<clip-id>", "Clip ID to delete").option("--dry-run", "Preview parameters without executing").action(async (projectPath, clipId, options) => {
63152
63152
  const startedAt = Date.now();
63153
63153
  const spinner2 = ora("Deleting clip...").start();
63154
63154
  try {
63155
63155
  validateResourceId(clipId);
63156
63156
  if (options.dryRun) {
63157
63157
  outputSuccess({
63158
- command: "timeline delete",
63158
+ command: "timeline delete-clip",
63159
63159
  startedAt,
63160
63160
  dryRun: true,
63161
63161
  data: {
@@ -63185,7 +63185,7 @@ timelineCommand.command("delete").description("Delete a clip from the timeline")
63185
63185
  spinner2.succeed(source_default.green("Clip deleted"));
63186
63186
  if (isJsonMode()) {
63187
63187
  outputSuccess({
63188
- command: "timeline delete",
63188
+ command: "timeline delete-clip",
63189
63189
  startedAt,
63190
63190
  data: {
63191
63191
  id: clipId,
@@ -63200,7 +63200,7 @@ timelineCommand.command("delete").description("Delete a clip from the timeline")
63200
63200
  exitWithError(generalError(`Failed to delete clip: ${msg}`));
63201
63201
  }
63202
63202
  });
63203
- timelineCommand.command("move").description("Move a clip to a new position").argument("<project>", "Project file path").argument("<clip-id>", "Clip ID to move").option("-t, --time <seconds>", "New start time").option("--track <track-id>", "Move to different track").option("--dry-run", "Preview parameters without executing").action(async (projectPath, clipId, options) => {
63203
+ timelineCommand.command("move-clip").description("Move a clip to a new position").argument("<project>", "Project file path").argument("<clip-id>", "Clip ID to move").option("-t, --time <seconds>", "New start time").option("--track <track-id>", "Move to different track").option("--dry-run", "Preview parameters without executing").action(async (projectPath, clipId, options) => {
63204
63204
  const startedAt = Date.now();
63205
63205
  const spinner2 = ora("Moving clip...").start();
63206
63206
  try {
@@ -63208,7 +63208,7 @@ timelineCommand.command("move").description("Move a clip to a new position").arg
63208
63208
  if (options.track) validateResourceId(options.track);
63209
63209
  if (options.dryRun) {
63210
63210
  outputSuccess({
63211
- command: "timeline move",
63211
+ command: "timeline move-clip",
63212
63212
  startedAt,
63213
63213
  dryRun: true,
63214
63214
  data: {
@@ -63243,7 +63243,7 @@ timelineCommand.command("move").description("Move a clip to a new position").arg
63243
63243
  spinner2.succeed(source_default.green("Clip moved"));
63244
63244
  if (isJsonMode()) {
63245
63245
  outputSuccess({
63246
- command: "timeline move",
63246
+ command: "timeline move-clip",
63247
63247
  startedAt,
63248
63248
  data: {
63249
63249
  id: updated.id,
@@ -64189,7 +64189,7 @@ init_ai_highlights();
64189
64189
  init_ai_animated_caption();
64190
64190
  init_output();
64191
64191
  var pipelineCommand = new Command("remix").description(
64192
- "AI media transformations on existing video / audio (highlights, auto-shorts, animated captions). For BUILD-from-text flows see `vibe build`."
64192
+ "Transform existing media (highlights, auto-shorts, animated captions, regenerate-scene)"
64193
64193
  ).addHelpText(
64194
64194
  "after",
64195
64195
  `
@@ -69745,7 +69745,7 @@ async function runSceneInit(projectDirArg, options, startedAt) {
69745
69745
  }
69746
69746
  const visualStyle = options.visualStyle ? getVisualStyle(String(options.visualStyle)) : void 0;
69747
69747
  if (options.visualStyle && !visualStyle) {
69748
- exitWithError(usageError(`Unknown visual style: ${String(options.visualStyle)}`, `Valid: ${visualStyleNames()}. Browse with \`vibe scene styles\`.`));
69748
+ exitWithError(usageError(`Unknown visual style: ${String(options.visualStyle)}`, `Valid: ${visualStyleNames()}. Browse with \`vibe scene list-styles\`.`));
69749
69749
  }
69750
69750
  const projectDir = resolve42(projectDirArg);
69751
69751
  const projectName = basename14(projectDir);
@@ -71169,7 +71169,7 @@ You have access to tools for:
71169
71169
  - For generate_image: Ask what kind of image (subject, style, mood) if not specified
71170
71170
  - For generate_video: Ask about the video prompt/motion if not specified
71171
71171
  - For generate_speech: Ask what text to convert if not provided
71172
- - For scene_build (text \u2192 MP4): Ask for the storyboard / script content
71172
+ - For build (text \u2192 MP4): Ask for the storyboard / script content
71173
71173
  - Example: "generate an image" \u2192 Ask "What kind of image would you like? (e.g., space landscape, cute robot, product photo)"
71174
71174
  - DON'T make up random content - the user knows what they want
71175
71175
 
@@ -71212,7 +71212,7 @@ When working with script-to-video / scene-build output directories:
71212
71212
  - **narration-N.mp3**: Generated narration audio for each scene
71213
71213
 
71214
71214
  USE fs_read to examine these files when the user asks about scenes or wants to regenerate content. For example:
71215
- - "regenerate scene 3" \u2192 First fs_read storyboard.json, tell user what scene 3 contains, then use pipeline_regenerate_scene
71215
+ - "regenerate scene 3" \u2192 First fs_read storyboard.json, tell user what scene 3 contains, then use remix_regenerate_scene
71216
71216
  - "what's in scene 2?" \u2192 fs_read storyboard.json and explain scene 2 details
71217
71217
 
71218
71218
  ### Error Recovery
@@ -71923,10 +71923,13 @@ program2.name("vibe").showSuggestionAfterError(true).description("VibeFrame CLI
71923
71923
  "after",
71924
71924
  `
71925
71925
  Global flags (work with any command):
71926
+ -V, --version Print version and exit
71927
+ -h, --help Print help for the command and exit
71926
71928
  --json Output JSON (auto-enabled when piped)
71927
71929
  --fields Limit output fields (e.g., --fields "path,duration")
71928
- --quiet Output only the result value (path, URL, or ID)
71930
+ -q, --quiet Output only the result value (path, URL, or ID)
71929
71931
  --stdin Read options from stdin as JSON (for agent/script use)
71932
+ --describe Print the command's JSON schema and exit (no execution)
71930
71933
  --dry-run Preview without executing (most commands)
71931
71934
 
71932
71935
  Get started (90% of users start here):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibeframe/cli",
3
- "version": "0.75.0",
3
+ "version": "0.77.0",
4
4
  "description": "VibeFrame CLI - natural language video editing from the terminal",
5
5
  "private": false,
6
6
  "license": "MIT",
@@ -182,8 +182,8 @@
182
182
  "tsx": "^4.21.0",
183
183
  "typescript": "^5.3.3",
184
184
  "vitest": "^1.2.2",
185
- "@vibeframe/ai-providers": "0.75.0",
186
- "@vibeframe/core": "0.75.0"
185
+ "@vibeframe/ai-providers": "0.77.0",
186
+ "@vibeframe/core": "0.77.0"
187
187
  },
188
188
  "engines": {
189
189
  "node": ">=20"