@amg555/frameforge-mcp 2.3.0 → 2.3.1

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.
@@ -1,17 +1,45 @@
1
1
  {
2
2
  "name": "frameforge",
3
- "owner": { "name": "AMG555" },
4
- "metadata": {
5
- "description": "FrameForge — Enterprise AI video production engine. Localhost-first, any agentic IDE (IBM Bob, Cursor, Windsurf, Kiro, Claude Code). Cloudflare Remote MCP for ~80% token savings.",
6
- "version": "1.2.0"
7
- },
3
+ "displayName": "FrameForge — AI Video Production",
4
+ "description": "Full AI video production engine. Produce short-form reels (1080×1920), YouTube videos (1920×1080), or code-driven animated explainers — directly from your IDE. Playwright + FFmpeg renders every frame. 17 MCP tools.",
5
+ "version": "2.3.1",
6
+ "homepage": "https://github.com/AMG555/FrameForge",
8
7
  "plugins": [
9
8
  {
10
9
  "name": "video-pipeline",
11
- "source": "./plugins/video-pipeline",
12
- "description": "End-to-end overnight video production: topic research with real fact-checking (Tavily/Brave/SearXNG), script writing, voice synthesis (ElevenLabs/edge-tts/Azure/OpenAI), FFmpeg animation, quality gates, file and webhook delivery.",
13
- "version": "2.3.0",
14
- "keywords": ["frameforge", "video", "automation", "mcp", "tts", "ffmpeg", "ibm-bob", "enterprise", "cloudflare"]
10
+ "path": "plugins/video-pipeline/.claude-plugin/plugin.json",
11
+ "skills": [
12
+ {
13
+ "name": "video-pipeline",
14
+ "displayName": "FrameForge Video Pipeline",
15
+ "description": "End-to-end video production: research → script → TTS → images → render → publish. Three paths: (1) IDE writes scenes (most common, no API key), (2) code-driven Playwright animation, (3) auto-research pipeline. 17 MCP tools.",
16
+ "triggerPhrases": [
17
+ "make a video about",
18
+ "produce a reel on",
19
+ "create a short",
20
+ "edit this into a reel",
21
+ "make an explainer",
22
+ "animated video",
23
+ "code-driven video",
24
+ "generate video",
25
+ "run the pipeline",
26
+ "publish video",
27
+ "overnight batch",
28
+ "queue videos"
29
+ ]
30
+ }
31
+ ]
15
32
  }
16
- ]
33
+ ],
34
+ "mcpServer": {
35
+ "command": "npx",
36
+ "args": ["--yes", "--package=@amg555/frameforge-mcp", "frameforge-mcp"],
37
+ "description": "Runs the FrameForge MCP server via npx (no install needed). Requires ffmpeg and edge-tts on PATH."
38
+ },
39
+ "requirements": {
40
+ "node": ">=18.0.0",
41
+ "binaries": ["ffmpeg", "ffprobe"],
42
+ "optional": ["edge-tts", "python3"],
43
+ "notes": "edge-tts: pip install edge-tts. Playwright (for code-driven animation): npm install playwright && npx playwright install chromium (run once in project dir)."
44
+ }
17
45
  }
package/CHANGELOG.md CHANGED
@@ -4,6 +4,22 @@ All notable changes to FrameForge are documented here.
4
4
 
5
5
  ---
6
6
 
7
+ ## [2.3.1] — 2026-11-04
8
+
9
+ ### Added
10
+
11
+ - **`.claude-plugin/marketplace.json`** — Claude Code plugin marketplace registration. FrameForge is now discoverable via `claude plugin marketplace add AMG555/FrameForge`.
12
+ - **`plugins/video-pipeline/.claude-plugin/plugin.json`** — per-plugin manifest for the video-pipeline skill.
13
+
14
+ ### Changed
15
+
16
+ - **`src/cli/setup-keys.js`** — `skip` is now the **default** option in the LLM provider menu. Users who write their own scenes (the most common path) are no longer forced through an API key section.
17
+ - **`CLAUDE.md`** — Path 2 expanded: transcript/`cuePhrase()` word-sync workflow, `video_job.py` spend-capped batch, golden stills regression test, hook variants (A/B testing opening shots), mobile crop check, still-review budget.
18
+ - **`START_HERE.md`** — restructured into three named paths (A: IDE-scenes, B: code-driven animation, C: auto-research). Reel vs. YouTube format choice surfaced in opening questions. Path B includes transcription, hook variants, and storyboard gate.
19
+ - Version bump: `2.3.0` → `2.3.1` across all version strings.
20
+
21
+ ---
22
+
7
23
  ## [2.3.0] — 2026-11-02
8
24
 
9
25
  ### Added
package/CLAUDE.md CHANGED
@@ -94,10 +94,14 @@ Output files appear in `.frameforge-files/`:
94
94
 
95
95
  ### Path 2 — Code-driven animated video (Playwright + FFmpeg, no AI images)
96
96
 
97
- Use this when: the user wants motion graphics, Pollinations is unavailable, or they ask for "animated" or "code-rendered" video. Every frame is a pure function of time `t`.
97
+ Use this when: the user wants motion graphics, Pollinations is unavailable, or they ask for "animated", "code-rendered", "explainer", "reel", or "YouTube-style" video. Every frame is a pure function of time `t`.
98
98
 
99
99
  > **Iron rule:** Never use `Math.random()`, `Date.now()`, `setTimeout`, or module-level mutable state in scene code. Use `hash(i)` from `reel/engine.js` for deterministic randomness.
100
100
 
101
+ **Pick a format first:**
102
+ - **Reel / Short / TikTok** → `width: 1080, height: 1920` (portrait 9:16)
103
+ - **YouTube / Explainer** → `width: 1920, height: 1080` (landscape 16:9)
104
+
101
105
  **Step 0 — Beat sheet first. Always. No exceptions.**
102
106
 
103
107
  Before writing any scene code, reply to the user with:
@@ -106,17 +110,22 @@ Before writing any scene code, reply to the user with:
106
110
 
107
111
  **Stop and wait for approval before Step 1.** Fixing a beat sheet costs one message. Rewriting a finished scene costs everything.
108
112
 
109
- **Step 1 — Generate TTS first (exact timing is ground truth):**
113
+ **Step 1 — Generate TTS and transcription (exact timing is ground truth):**
110
114
  ```
111
115
  multi_voice_tts({ text: "Full narration text.", outputPath: ".frameforge-files/voice_0.m4a" })
112
116
  ```
117
+ Then transcribe for word-level timestamps (required for `cuePhrase()` sync):
118
+ ```
119
+ // run in projectDir after scaffold: python scripts/transcribe.py .frameforge-files/voice_0.m4a
120
+ // → produces voice_0.captions.json with per-word start/end times
121
+ ```
113
122
 
114
123
  **Step 2 — Scaffold the project:**
115
124
  ```
116
125
  scaffold_animation_project({
117
126
  outDir: ".frameforge-files/my-animation/",
118
127
  title: "My Video",
119
- width: 1920, height: 1080,
128
+ width: 1920, height: 1080, // or 1080×1920 for portrait reel
120
129
  scenes: [{ narration: "...", caption: "...", visual_description: "..." }],
121
130
  audioPath: ".frameforge-files/voice_0.m4a"
122
131
  })
@@ -138,16 +147,49 @@ validate_storyboard({ storyboardPath: ".frameforge-files/my-animation/STORYBOARD
138
147
  - Read `ANIMATION_GUIDE.md` in the project folder first
139
148
  - Every style must be a **pure function of `t`**
140
149
  - Use `layer('name').on(t => ({ ...styles }))` for each scene
150
+ - Sync animation to narration using `cuePhrase('the exact words spoken')` — this reads `voice_0.captions.json` and returns the frame when those words start. **The build fails if the phrase isn't found**, so re-recording VO can never silently desync the animation.
141
151
 
142
152
  **Step 5 — Pre-flight, then stills, then full render:**
143
153
  ```
144
154
  render_animation({ projectDir: ".frameforge-files/my-animation/", mode: "look" }) // fonts, assets, NaN checks
145
155
  render_animation({ projectDir: ".frameforge-files/my-animation/", mode: "sheet" }) // contact sheet — inspect this
146
156
  render_animation({ projectDir: ".frameforge-files/my-animation/", mode: "strip", timestamps: [2.1, 2.6] }) // motion check
157
+ render_animation({ projectDir: ".frameforge-files/my-animation/", mode: "crop", timestamps: ["9:16", 3.0] }) // mobile check
147
158
  render_animation({ projectDir: ".frameforge-files/my-animation/", mode: "full",
148
159
  audioPath: ".frameforge-files/voice_0.m4a" }) // only after stills pass
149
160
  ```
150
161
 
162
+ **Still review budget (minimum, before full render):**
163
+ - At least one `sheet` per shot
164
+ - One `strip` per key motion or transition
165
+ - One `crop` per story-carrying face or detail
166
+
167
+ **Step 6 — Optional: hook variants**
168
+
169
+ For reels and Shorts, make 2–3 versions with different opening hooks:
170
+ - Change only the first shot (0s–3s) in `edit.js`
171
+ - `render_animation({ mode: "stills", timestamps: [0.0, 1.5, 3.0] })` to compare openings
172
+ - Full render each variant, deliver as `hook_a.mp4`, `hook_b.mp4`, etc.
173
+
174
+ **Step 7 — Optional: unattended / spend-capped batch**
175
+ ```
176
+ // run from projectDir
177
+ python scripts/video_job.py submit --spec spec.json --max-usd 2.00
178
+ // → { jobId } — detached process, survives your session closing
179
+ python scripts/video_job.py status --id <jobId>
180
+ python scripts/video_job.py result --id <jobId>
181
+ ```
182
+ Each step only starts if the running cost won't exceed `--max-usd`. Receipts go to `jobs/receipts.jsonl`.
183
+
184
+ **Step 8 — Golden stills regression test (before any refactor)**
185
+
186
+ After the video passes QC, save the test stills:
187
+ ```
188
+ render_animation({ projectDir, mode: "storyboard" }) // 4 keyframes, file to out/storyboard.jpg
189
+ // → copy out/storyboard.jpg to test/golden/storyboard.jpg
190
+ ```
191
+ Before future refactors, re-run and compare. If pixels shift, the refactor broke determinism.
192
+
151
193
  > Requires one-time setup in the project directory: `npm install playwright && npx playwright install chromium`
152
194
 
153
195
  ---
package/README.md CHANGED
@@ -6,9 +6,10 @@
6
6
 
7
7
  **Any IDE. Any topic. Any style. 1080p videos from a single prompt.**
8
8
 
9
+ [![npm](https://img.shields.io/npm/v/@amg555/frameforge-mcp.svg?label=npm)](https://www.npmjs.com/package/@amg555/frameforge-mcp)
9
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
10
11
  [![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)
11
- [![Version](https://img.shields.io/badge/version-2.3.0-blue.svg)](CHANGELOG.md)
12
+ [![Version](https://img.shields.io/badge/version-2.3.1-blue.svg)](CHANGELOG.md)
12
13
  [![MCP Spec](https://img.shields.io/badge/MCP-2024--11--05-blue.svg)](https://modelcontextprotocol.io/)
13
14
  [![Tests](https://img.shields.io/badge/tests-512%20passing-brightgreen.svg)](#testing)
14
15
 
@@ -272,6 +273,16 @@ Every video passes 7 checks before delivery. Any failure blocks the output.
272
273
 
273
274
  ## CLI commands
274
275
 
276
+ **Via npx (no clone needed):**
277
+
278
+ | Command | What it does |
279
+ |---------|-------------|
280
+ | `npx --package=@amg555/frameforge-mcp frameforge-setup` | Interactive key wizard — saves to `~/.frameforge/config.json` |
281
+ | `npx --package=@amg555/frameforge-mcp frameforge-doctor` | Check Node, FFmpeg, edge-tts, and env vars |
282
+ | `npx --package=@amg555/frameforge-mcp frameforge --topic "..."` | Full pipeline: research → render → deliver |
283
+
284
+ **Via cloned repo:**
285
+
275
286
  | Command | What it does |
276
287
  |---------|-------------|
277
288
  | `npm run doctor` | Check Node, FFmpeg, edge-tts, and env vars |
@@ -323,7 +334,14 @@ Report vulnerabilities: [SECURITY.md](SECURITY.md)
323
334
 
324
335
  ## Deployment
325
336
 
326
- **VPS / Pi / local machine:**
337
+ **npx (no install — recommended for users):**
338
+
339
+ ```bash
340
+ npx --package=@amg555/frameforge-mcp frameforge-setup
341
+ # then add the IDE config from the quickstart above
342
+ ```
343
+
344
+ **VPS / Pi / self-hosted (cloned repo):**
327
345
 
328
346
  ```bash
329
347
  git clone https://github.com/AMG555/FrameForge.git && cd FrameForge
package/START_HERE.md CHANGED
@@ -17,18 +17,20 @@ produce it — from research through render to final MP4.
17
17
 
18
18
  ## Opening Message (say this verbatim to the user)
19
19
 
20
- > 👋 I'm your FrameForge video studio. I can make short-form reels, YouTube explainers,
21
- > documentary clips, tutorials, or any video you describe — using AI research, voiceover,
22
- > animated scenes, and a full render pipeline.
20
+ > 👋 I'm your FrameForge video studio. I can make:
23
21
  >
24
- > Let's start with a few quick questions so I know exactly what to build:
22
+ > - **Short-form reels** (Instagram, TikTok, YouTube Shorts — 15–60s, 9:16 portrait)
23
+ > - **YouTube videos** (explainers, tutorials, long-form — 3–15 min, 16:9 landscape)
24
+ > - **Code-driven animated explainers** (motion graphics, no stock images needed — any length)
25
+ >
26
+ > Let's start with a few quick questions:
25
27
  >
26
28
  > 1. **What's the topic or idea?** (e.g. "How black holes form", "5 tips for sourdough bread", "A travel reel about Tokyo")
27
- > 2. **What style?** Pick one: `educational` · `comedic` · `documentary` · `vlog` · `cinematic` · `tutorial` · or describe your own
28
- > 3. **How long?** `Short (15–60s)` · `Medium (1–3 min)` · `Long (5–10 min)`
29
- > 4. **Orientation?** `Landscape 16:9 (YouTube/desktop)` · `Portrait 9:16 (Reels/TikTok/Shorts)`
29
+ > 2. **Format?** `Reel / Short / TikTok (9:16)` · `YouTube video (16:9)` · `Animated explainer (any)`
30
+ > 3. **Style?** `educational` · `comedic` · `documentary` · `cinematic` · `tutorial` · or describe your own
31
+ > 4. **How long?** `Short (15–60s)` · `Medium (1–3 min)` · `Long (5–10 min)`
30
32
  > 5. **Voice?** `Auto-select` · or name a style: `professional narrator`, `friendly teacher`, `energetic host`
31
- > 6. **Any images or clips you want included?** (paste file paths, or say "no — generate everything")
33
+ > 6. **Any footage, images, or audio to include?** (paste file paths, or say "generate everything")
32
34
  >
33
35
  > Answer as many or as few as you like. I'll fill in the rest.
34
36
 
@@ -36,16 +38,24 @@ produce it — from research through render to final MP4.
36
38
 
37
39
  ## After the User Answers — Agent Instructions
38
40
 
39
- Once you have the user's answers, proceed as follows. Never skip the beat-sheet gate.
41
+ Once you have the user's answers, choose the right render path and follow it precisely.
42
+
43
+ ---
44
+
45
+ ## Render Paths
40
46
 
41
- ### Step 1 — Beat Sheet Gate (MANDATORY, no exceptions)
47
+ ### PATH A — IDE-written scenes (fastest, most common)
42
48
 
43
- Before calling any render tool, produce a **beat sheet** in this exact format and
44
- **stop** — wait for the user to approve it before continuing:
49
+ Use for: any video where you (the IDE agent) write the narration and visual descriptions.
50
+ No LLM key needed — FrameForge generates TTS + AI images and renders with FFmpeg.
51
+
52
+ **Step A1 — Beat Sheet Gate (MANDATORY)**
53
+
54
+ Before calling any render tool, produce a beat sheet and **stop** — wait for approval:
45
55
 
46
56
  ```
47
57
  BEAT SHEET — "<title>"
48
- Duration: Xs | Style: <style> | Format: <orientation>
58
+ Duration: Xs | Style: <style> | Format: <landscape/portrait>
49
59
 
50
60
  Scene 1 [0:00–0:08] <what happens + what the viewer learns> → TRANSITION
51
61
  Scene 2 [0:08–0:18] <what happens + what the viewer learns> → TRANSITION
@@ -56,43 +66,89 @@ Voice: <voice description>
56
66
  Visual style: <1-sentence description>
57
67
  ```
58
68
 
59
- Gate rules — reject and revise the beat sheet if ANY of these are true:
69
+ Gate rules — revise if ANY are true:
60
70
  - A scene has no event (action that changes something)
61
71
  - Two scenes share the same timestamp range
62
72
  - Any seam is missing a transition label
63
- - The total duration doesn't match the user's requested length ±10%
73
+ - Total duration doesn't match requested length ±10%
64
74
 
65
- Only proceed to Step 2 after the user says **"looks good"**, **"go ahead"**, or equivalent.
75
+ **Step A2 — Render**
66
76
 
67
- ### Step 2 — Research (if the topic needs facts)
77
+ ```
78
+ create_video_from_script({
79
+ scenes: [ { narration: "...", caption: "...", visual_description: "...", camera_hint: "zoom_in" } ],
80
+ title: "My Video",
81
+ orientation: "landscape", // "portrait" for Reels/Shorts/TikTok
82
+ voice: "en-US-BrianNeural", // or use language: "en"
83
+ withMusic: true
84
+ })
85
+ ```
68
86
 
69
- Use `research_topic` to gather verified claims. Skip this for pure creative/style videos.
87
+ **Step A3 — Publish**
70
88
 
71
- ### Step 3 — Script
89
+ Ask: "Save locally, or deliver somewhere?" Then call `publish_video`.
72
90
 
73
- Use `write_script` with the beat sheet as the outline. Pass `style`, `format`, and
74
- `voice` from the user's answers. The script must match the beat sheet scene-for-scene.
91
+ ---
75
92
 
76
- ### Step 4 — Assets
93
+ ### PATH B — Code-driven animated video (motion graphics, explainers, reels)
77
94
 
78
- For each scene, call `generate_scene_image` with a prompt that matches the scene's
79
- visual description. If the user supplied their own files, use `ingest_media` instead.
95
+ Use for: motion graphics, animated explainers, reels that must look high-quality without stock images.
96
+ Requires one-time: `npm install playwright && npx playwright install chromium` (run in the project dir).
80
97
 
81
- Call `render_tts` for each scene's narration line.
98
+ **Step B1 — Beat sheet first (same gate as Path A — MANDATORY)**
82
99
 
83
- ### Step 5 — Render
100
+ **Step B2 — TTS and transcription**
84
101
 
85
- Call `create_video_from_script` (IDE-driven path) or `assemble_video` (pipeline path)
86
- to produce the final MP4.
102
+ ```
103
+ multi_voice_tts({ text: "Full narration.", outputPath: ".frameforge-files/voice_0.m4a" })
104
+ // After scaffolding: python scripts/transcribe.py .frameforge-files/voice_0.m4a
105
+ // → voice_0.captions.json — word timestamps for cuePhrase() sync
106
+ ```
87
107
 
88
- After render, call `render_animation` with `mode: "sheet"` to produce a contact-sheet
89
- preview. Show the user the sheet path and ask if they want any changes.
108
+ **Step B3 — Scaffold**
90
109
 
91
- ### Step 6 — Publish (optional)
110
+ ```
111
+ scaffold_animation_project({
112
+ outDir: ".frameforge-files/my-animation/",
113
+ title: "My Video",
114
+ width: 1920, height: 1080, // 1080×1920 for portrait reels
115
+ scenes: [...],
116
+ audioPath: ".frameforge-files/voice_0.m4a"
117
+ })
118
+ ```
92
119
 
93
- Ask the user: "Do you want to publish this anywhere, or just save the file locally?"
120
+ **Step B4 — Validate STORYBOARD.md**
94
121
 
95
- If they want to publish, call `publish_video` with their chosen channel.
122
+ ```
123
+ validate_storyboard({ storyboardPath: ".frameforge-files/my-animation/STORYBOARD.md" })
124
+ ```
125
+
126
+ **Step B5 — Write `edit.js`, then stills, then full render**
127
+
128
+ ```
129
+ render_animation({ projectDir: "...", mode: "look" }) // pre-flight
130
+ render_animation({ projectDir: "...", mode: "sheet" }) // one sheet per shot
131
+ render_animation({ projectDir: "...", mode: "strip", timestamps: [2.1, 2.6] }) // motion check
132
+ render_animation({ projectDir: "...", mode: "full", audioPath: ".frameforge-files/voice_0.m4a" })
133
+ ```
134
+
135
+ **For reels: make 2–3 hook variants** (change only the first 3s of `edit.js`, full-render each):
136
+ ```
137
+ render_animation({ projectDir: "...", mode: "stills", timestamps: [0.0, 1.5, 3.0] })
138
+ // deliver hook_a.mp4, hook_b.mp4 so the user can A/B test
139
+ ```
140
+
141
+ ---
142
+
143
+ ### PATH C — Auto-research (needs `PROVIDER_LLM` + key in `.env`)
144
+
145
+ Use for: overnight batch, topics where you want FrameForge to research and script everything.
146
+
147
+ ```
148
+ queue_full_pipeline({ topic: "How GPS works", style: "educational" })
149
+ → { jobId }
150
+ get_job_status({ jobId }) // poll every 30s
151
+ ```
96
152
 
97
153
  ---
98
154
 
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@amg555/frameforge-mcp",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "description": "FrameForge — AI video production engine for agentic IDEs. npx @amg555/frameforge-mcp. FFmpeg + TTS run on your machine. 17 MCP tools.",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
8
8
  "main": "src/mcp-server/server.js",
9
9
  "bin": {
10
- "frameforge": "src/cli/make.js",
11
- "frameforge-mcp": "src/mcp-server/stdio.js",
12
- "frameforge-setup": "src/cli/setup-keys.js",
10
+ "frameforge": "src/cli/make.js",
11
+ "frameforge-mcp": "src/mcp-server/stdio.js",
12
+ "frameforge-setup": "src/cli/setup-keys.js",
13
13
  "frameforge-doctor": "src/cli/doctor.js"
14
14
  },
15
15
  "scripts": {
@@ -55,6 +55,6 @@
55
55
  "license": "MIT",
56
56
  "repository": {
57
57
  "type": "git",
58
- "url": "https://github.com/AMG555/FrameForge"
58
+ "url": "git+https://github.com/AMG555/FrameForge.git"
59
59
  }
60
60
  }
@@ -171,6 +171,15 @@ async function main() {
171
171
  This wizard writes your provider API keys to: ${path.resolve(outFile)}
172
172
  Keys are never sent anywhere — they stay on your machine.
173
173
  Press Enter to accept a default. Ctrl+C to cancel.
174
+
175
+ ✅ No keys are required to make videos.
176
+ Your IDE writes the scenes — FrameForge uses free providers by default:
177
+ • edge-tts — free voice (no account)
178
+ • pollinations — free images (no account)
179
+ • FFmpeg — free local render (already on your machine)
180
+
181
+ You only need keys for the auto-research pipeline (FrameForge writes the
182
+ script itself). Skip those sections if you plan to write scenes yourself.
174
183
  `);
175
184
 
176
185
  const cfg = {};
@@ -178,22 +187,27 @@ Press Enter to accept a default. Ctrl+C to cancel.
178
187
  // ── LLM ──────────────────────────────────────────────────────────────────
179
188
  section('1 / 5 — LLM Provider (research + script generation)');
180
189
  console.log(' Used for: researching topics, writing scripts, fact-checking.');
190
+ console.log(' ⚡ SKIP THIS if your IDE agent writes the scenes (most common path).');
181
191
  console.log(' Free option: Groq (no credit card needed for free tier).\n');
182
192
 
183
193
  cfg.PROVIDER_LLM = await menu('Choose LLM provider', [
194
+ ['skip', '⏭ Skip — I write my own scenes (most common, no key needed)'],
184
195
  ['groq', 'Groq — free, fast (llama-3.3-70b). Get key: console.groq.com'],
185
196
  ['cerebras', 'Cerebras — fastest inference (2000+ tok/s). Get key: cloud.cerebras.ai'],
197
+ ['gemini', 'Google Gemini 2.0 Flash — free tier. Get key: aistudio.google.com'],
186
198
  ['openrouter', 'OpenRouter — all models with one key. Get key: openrouter.ai'],
187
199
  ['anthropic', 'Anthropic Claude Sonnet 4.5. Get key: console.anthropic.com'],
188
- ['gemini', 'Google Gemini 2.0 Flash. Get key: aistudio.google.com'],
189
200
  ['mistral', 'Mistral Large. Get key: console.mistral.ai'],
190
201
  ['together', 'Together AI Llama-3.3-70B-Turbo. Get key: api.together.ai'],
191
202
  ['openai', 'OpenAI GPT-4o. Get key: platform.openai.com'],
192
203
  ['ollama', 'Ollama — fully local, no key needed. Install: ollama.com'],
193
204
  ['webhook', 'Custom/VoxForge/any OpenAI-compatible endpoint'],
194
- ], 'groq');
205
+ ], 'skip');
195
206
 
196
- if (cfg.PROVIDER_LLM === 'groq') {
207
+ if (cfg.PROVIDER_LLM === 'skip') {
208
+ console.log(' ✅ LLM skipped — your IDE will write scenes via create_video_from_script.\n');
209
+ cfg.PROVIDER_LLM = undefined; // don't write to config
210
+ } else if (cfg.PROVIDER_LLM === 'groq') {
197
211
  cfg.GROQ_API_KEY = await askSecret(' Groq API key (starts with gsk_)');
198
212
  } else if (cfg.PROVIDER_LLM === 'cerebras') {
199
213
  cfg.CEREBRAS_API_KEY = await askSecret(' Cerebras API key');
@@ -1120,7 +1120,7 @@ Requires: npm install playwright && npx playwright install chromium (one-time se
1120
1120
 
1121
1121
  const SERVER_INFO = {
1122
1122
  name: 'video-pipeline',
1123
- version: '2.3.0',
1123
+ version: '2.3.1',
1124
1124
  };
1125
1125
 
1126
1126
  const CAPABILITIES = {