videodraft 0.3.2 → 0.3.4

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 VideoDraft
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -107,7 +107,13 @@ npx videodraft skills install # zero-install: npx fetches the C
107
107
  videodraft skills install # if the CLI is on PATH — auto-detects your installed agents
108
108
  videodraft skills install --agent claude,codex # target specific agents (repeatable/comma; --all for every agent)
109
109
  videodraft skills install --project # into ./.claude/skills for just this repo (else global)
110
- npx skills add videodraft-ai/cli # via the vercel-labs skills tool (discovery / 69-agent multiselect)
110
+ videodraft skills show # print the skill (also: skills show models|examples|pipeline|--all)
111
+
112
+ # Or install straight from the repo — no CLI on PATH needed first:
113
+ npx -y skills add videodraft-ai/cli -g # vercel-labs skills tool; npx -y skips npx's install prompt; -g = user scope
114
+ gh skill install videodraft-ai/cli videodraft --scope user # GitHub CLI; name the skill + user scope (else it lists / installs project-scoped)
115
+ # Claude Code: /plugin marketplace add videodraft-ai/cli then /plugin install videodraft@videodraft
116
+ # Codex: codex plugin marketplace add videodraft-ai/cli then codex plugin add videodraft@videodraft
111
117
  ```
112
118
 
113
119
  ## Environment variables
package/dist/index.js CHANGED
@@ -24,8 +24,8 @@ function readVersionFromDisk() {
24
24
  }
25
25
  }
26
26
  function resolveVersion() {
27
- if ("0.3.2") {
28
- return "0.3.2";
27
+ if ("0.3.4") {
28
+ return "0.3.4";
29
29
  }
30
30
  return readVersionFromDisk();
31
31
  }
@@ -3017,13 +3017,28 @@ function bundledSkillDir() {
3017
3017
  }
3018
3018
  throw new CliError("Bundled skill not found (package is missing skills/videodraft).");
3019
3019
  }
3020
- function copyDir(src, dest) {
3021
- fs7.mkdirSync(dest, { recursive: true });
3022
- for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
3023
- const from = path4.join(src, entry.name);
3024
- const to = path4.join(dest, entry.name);
3025
- if (entry.isDirectory()) copyDir(from, to);
3026
- else fs7.copyFileSync(from, to);
3020
+ function bundledSkillFiles() {
3021
+ if ('{"SKILL.md":"---\\nname: videodraft\\ndescription: Create AI videos, images, voiceovers, music, sound effects, dialogue, dubbing, storyboards, avatar videos and product/ad videos with VideoDraft. Use when the user mentions VideoDraft, or asks to generate/make a video, video ad, explainer, storyboard, talking-head/avatar video, AI image, voiceover/TTS, background music, sound effects, dialogue audio, voice changing, or dubbing \u2014 including batch/programmatic video generation in scripts or CI. Works via the `videodraft` CLI (preferred in terminals) or the VideoDraft MCP connector.\\nargument-hint: \\"[what to make, e.g. \\\\\\"a 6s cinematic video of a red fox\\\\\\"]\\"\\nallowed-tools: Bash(videodraft *) Bash(npx -y videodraft@latest *)\\n---\\n\\n# VideoDraft\\n\\nVideoDraft is an AI video creation platform where asset generation is the priority lane:\\n\\n- **Asset generation**: standalone images, video clips, voiceovers, music, sound effects, dialogue, voice-changed audio, dubbed media, upscales, and image descriptions. This is the fastest and most important lane. Treat these as complete deliverables when the user asks for assets.\\n- **Asset I/O**: upload local files, download outputs, auto-upload local references, and save generated media where the user can see it.\\n- **Project production**: idea \u2192 script \u2192 storyboard (scenes + shot images) \u2192 project data \u2192 production timeline \u2192 exported MP4. Use this only when the user asks for a story, storyboard, editable project, timeline, or final video.\\n\\n## How to connect\\n\\nTwo equivalent surfaces (same backend, same credits, same projects):\\n\\n1. **CLI** (preferred when you have a shell): run `videodraft` if it\'s on PATH; otherwise `npx -y videodraft@latest` runs it with no install (needs Node \u226520; the `-y` skips npx\'s install prompt so it runs non-interactively; the package is fetched on first use and cached). For heavy use, `npm install -g videodraft`. If there\'s no Node/shell here but the MCP connector below is available, use that instead; if neither works, tell the user how to install (https://videodraft.ai/cli).\\n - Auth \u2014 pick by context, don\'t guess:\\n \u2022 INTERACTIVE (a human is in the session, e.g. Claude Code / Codex): on exit code 3 (\\"not authenticated\\"), tell the user to run `videodraft login` in their terminal \u2014 it opens their browser for a one-click VideoDraft sign-in (OAuth), no key to copy. Wait for them to confirm it succeeded, then retry the command. This is the preferred path when the user is present.\\n \u2022 HEADLESS / CI (no browser): set `VIDEODRAFT_API_KEY=vd_mcp_...` (a token the user mints at https://app.videodraft.ai/mcp-keys).\\n \u2022 SECURITY: never ask the user to paste a `vd_mcp_...` token into the chat \u2014 use browser `login` or the env var so the token never lands in the transcript.\\n - Every command accepts `--json` (parse this, don\'t scrape text). Exit codes: 0 ok, 1 error, 2 usage, 3 auth (see Auth above), 4 insufficient credits (\u2192 tell the user, don\'t retry).\\n - Tool discovery: start with `videodraft tools list` for the grouped catalog, then narrow with `videodraft tools list --lane assets`, `--lane asset_io`, `--lane project_data`, or `--lane production`.\\n - Asset lane: `videodraft generate image|video|voiceover|music|sound-effect|dialogue|voice-changer|dub`, `videodraft upload`, and `videodraft download`.\\n - Full API access: `videodraft tools schema <name>`, `videodraft call <tool> --args \'<json>\'`.\\n2. **MCP connector**: if VideoDraft MCP tools (e.g. `generate_storyboard_from_idea`) are available, call them directly \u2014 the CLI\'s curated commands map 1:1 onto these tools.\\n\\n## First decision: asset or project?\\n\\n- **One standalone asset** (image, clip, voiceover, music track, sound effect, dialogue track, voice-changed file, dubbed media file, upscale, or description): generate it directly. Do NOT create a project.\\n - `videodraft generate image \\"a red fox in snow, cinematic\\" --ar 16:9 --download ./out/`\\n - `videodraft generate video \\"slow dolly over a misty lake\\" --model google-veo3.1 --duration 6 --download ./out/`\\n- **A small set of related assets**: still stay in the asset lane. Use an AI Studio session if you need to group related generations, but do not make a storyboard/project unless the user asks for one.\\n- **A multi-scene video / ad / explainer, storyboard, timeline, or final exported video**: create a project so the work stays organized, editable in the web app, and exportable.\\n - `videodraft create \\"30s launch video for our espresso machine\\" --ar 9:16`\\n- **Just a script** (no video asked for): `videodraft create \\"...\\" --script-only`. Stop at the script \u2014 do not build a storyboard the user didn\'t ask for.\\n- **Iterating on existing work**: find it first (`videodraft projects list`) and reuse that project. Never create a new project to change an existing one.\\n\\n## Credits: confirm before spending\\n\\nGeneration costs credits (video is per-second; shot-image batches are the largest single spend). Before anything expensive:\\n\\n1. `videodraft credits` \u2014 check the balance.\\n2. `videodraft generate video \\"...\\" --estimate` or `videodraft costs <model> --duration 8 --resolution 1080p` \u2014 get the quote. For ElevenLabs audio, use `--type audio` plus `--duration`, `--length`, or `--chars`.\\n3. Tell the user the model + settings + rough cost and get a go-ahead. Ask rather than assume aspect ratio, duration, and model when they matter.\\n4. Honor the user\'s stated preference on confirmation. If they tell you to stop asking (e.g. \\"don\'t ask me\\", \\"just go\\", \\"stop confirming cost\\"), proceed without a go-ahead for the rest of the session. If they say to always confirm, confirm every spend. Default when unspecified: confirm the first spend of a session and any unusually large one (a shot-image batch, a long or 1080p video).\\n\\n`videodraft models image|video|audio` lists every model with its supported inputs (aspect ratios, resolutions, reference limits, audio billing inputs) \u2014 consult it instead of guessing capabilities.\\n\\n## Async jobs\\n\\nImage/video generation is asynchronous: commands submit a job and **wait by default**, printing output URLs (and saving files with `--download`). In scripts/CI prefer explicit control:\\n\\n```bash\\nJOB=$(videodraft generate image \\"...\\" --no-wait --json | jq -r .job_id)\\nvideodraft wait \\"$JOB\\" --download \\"./outputs/{job_id}_{index}.{ext}\\" --json\\n```\\n\\nFor MANY jobs: submit each with `--no-wait`, collect ALL with one command \u2014 `videodraft wait <id1> <id2> ...` polls every job from one process with one batched request per tick. Do NOT spawn parallel `wait`/`generate --wait` processes for a batch.\\n\\nIf a wait times out, the job is still running server-side \u2014 `videodraft status <job_id>` later. Never re-submit just because a wait timed out (that double-spends credits).\\n\\n## Local files and reference images\\n\\nReference inputs must be public URLs. The CLI uploads local files automatically wherever a URL is expected (`--ref photo.jpg`, `--start-image frame.png`), or explicitly:\\n\\n```bash\\nURL=$(videodraft upload ./product.png --json | jq -r .url)\\n```\\n\\nNever silently drop a reference you couldn\'t upload \u2014 stop and tell the user. Never upload a user\'s file to a third-party host.\\n\\nWhen the user attaches media, classify each item before acting: a recurring **visual asset** (character/product/location/style), actual **footage to place as shots**, or **inspiration only**. See [references/pipeline.md](references/pipeline.md) for how each role flows into a project.\\n\\n## Showing media to the user\\n\\nGenerated media is **not** displayed in the chat automatically \u2014 you decide what to show. To preview an asset inline, save it locally (use `--download` so it lands under `media/`) and reference its **local path** as a Markdown link with a **leading `./`**:\\n\\n```\\n[ferrari shot](./media/ferrari_01.png) \u2190 image card\\n[the clip](./media/clip.mp4) \u2190 video player\\n[voiceover](./media/vo.mp3) \u2190 audio player\\n```\\n\\nPut the Markdown link **in your message text** \u2014 video and audio embed exactly like images. Do **not** use `SendUserFile` (or other file-send tools) to display media: that renders inside a collapsible tool card and gets buried in the tool list. The Markdown link in your prose is what produces the inline card.\\n\\nUse the path you saved to: a **workspace-relative** path (`./media/clip.mp4`, or `./<any-folder>/clip.mp4` \u2014 any folder in the workspace works), or the **absolute** path for a file outside the workspace (e.g. `/Users/you/Desktop/clip.mp4` or another workspace\'s path). Both render. Show the finished results worth showing (and only those \u2014 not every intermediate job). A bare CDN URL or a JSON dump of output URLs does **not** render; the local-path Markdown link is what produces an inline card.\\n\\n## The full pipeline (idea \u2192 MP4)\\n\\n```bash\\nvideodraft credits\\nvideodraft create \\"<idea>\\" --ar 9:16 # project: script \u2192 visual assets \u2192 storyboard\\nvideodraft shots <project_id> --grid --estimate # cost preview, confirm with user\\nvideodraft shots <project_id> --grid # batch shot images (waits, writes onto shot cards)\\nvideodraft produce <project_id> # voiceovers + captions + production timeline\\nvideodraft export <project_id> --download final.mp4\\n```\\n\\nOptional between produce and export: per-shot motion clips (`videodraft generate video ... --project <id>` then place it with `videodraft attach <project> --scene N --shot M --media <url|file> --type video --duration <s>`), music (`videodraft generate music \\"...\\" --attach <project_id>`), and standalone audio assets (`generate sound-effect`, `generate dialogue`, `generate voice-changer`, `generate dub`). Details, per-step tools and editing rules: [references/pipeline.md](references/pipeline.md).\\n\\nAvatar/talking-head videos are their own short flow: `videodraft avatar script` \u2192 `avatar create` \u2192 `avatar render` (paid step).\\n\\n## Working with project data\\n\\nA project is one JSON blob (script, storyboard scenes, shot cards, visual assets, production timeline). To inspect: `videodraft projects get <id>`. To edit: fetch `--raw`, modify, then `videodraft call update_project` \u2014 objects deep-merge, **arrays replace wholesale** (send the complete `storyboard.scenes` array to change one scene). Snapshot first with `videodraft checkpoint create <id>` before risky edits. Schema reference: `videodraft call get_project_schema`.\\n\\n## More\\n\\n- [references/pipeline.md](references/pipeline.md) \u2014 project data model, step-by-step tools, attaching media, editing safely\\n- [references/models.md](references/models.md) \u2014 choosing image/video models, pricing patterns, voices and styles\\n- [references/examples.md](references/examples.md) \u2014 recipes: batch product videos from a CSV, talking-head from a script, changelog video in CI\\n","references/examples.md":"# Recipes\\n\\nWorking patterns for common asks. All assume auth (`videodraft login` once, or `VIDEODRAFT_API_KEY` in the environment) and use `--json` for parsing.\\n\\n## 1. Batch product videos from a CSV\\n\\nOne 9:16 product clip per row of `products.csv` (`name,image_url,tagline`):\\n\\n```bash\\n#!/usr/bin/env bash\\nset -euo pipefail\\nmkdir -p outputs\\n\\nwhile IFS=, read -r name image tagline; do\\n job=$(videodraft generate video \\\\\\n \\"Premium product shot of ${name}: ${tagline}. Slow orbit, studio lighting.\\" \\\\\\n --model google-veo3.1 --ar 9:16 --duration 6 \\\\\\n --start-image \\"$image\\" \\\\\\n --no-wait --json | jq -r .job_id)\\n echo \\"$name,$job\\" >> outputs/jobs.csv\\ndone < <(tail -n +2 products.csv)\\n\\n# Collect ALL results with ONE process (batched polling \u2014 one request per tick)\\nvideodraft wait $(cut -d, -f2 outputs/jobs.csv) \\\\\\n --download \\"outputs/{job_id}_{index}.{ext}\\" --json > outputs/results.json\\n# map job ids back to product names via outputs/jobs.csv\\n```\\n\\nSubmit-then-collect parallelizes server-side generation; the single multi-id `wait` keeps it to one local process and one batched poll request per tick no matter how many jobs. Estimate first: `videodraft costs google-veo3.1 --type video --duration 6` \xD7 rows, and confirm with the user.\\n\\n## 2. Full marketing video from one idea\\n\\n```bash\\nvideodraft credits --json\\nvideodraft create \\"30-second launch video for Solace, a sleep-tracking ring. Calm, premium, dark palette.\\" \\\\\\n --ar 9:16 --style cinematic --json > project.json\\nPROJECT=$(jq -r .project_id project.json)\\n\\nvideodraft shots \\"$PROJECT\\" --grid --estimate # show the user the cost; get a go-ahead\\nvideodraft shots \\"$PROJECT\\" --grid\\nvideodraft produce \\"$PROJECT\\"\\nvideodraft generate music \\"minimal ambient, warm pads, 60 BPM\\" --attach \\"$PROJECT\\"\\nvideodraft export \\"$PROJECT\\" --download solace-launch.mp4\\n```\\n\\nThe project stays editable at the URL in `project.json` (`.urls`) \u2014 hand it to the user for tweaks.\\n\\n## 3. Talking-head (avatar) video\\n\\n```bash\\nSCRIPT=$(videodraft avatar script \\"why our espresso subscription saves you money\\" --style ad-style --json | jq -r .script)\\nAVATAR=$(videodraft avatar create ./founder.jpg --script \\"$SCRIPT\\" --ar 9:16 --json | jq -r .avatar_video_id)\\nvideodraft avatar render \\"$AVATAR\\" --resolution 720p # paid step \u2014 confirm cost first (~20 credits/sec)\\n```\\n\\n## 4. Changelog video in CI\\n\\nIn a GitHub Action with `VIDEODRAFT_API_KEY` set as a secret:\\n\\n```bash\\nNOTES=$(git log --oneline v1.2.0..HEAD | head -20)\\nvideodraft create \\"Weekly product update video. Energetic, 20 seconds. Changes: ${NOTES}\\" --ar 16:9 --json > p.json\\nPROJECT=$(jq -r .project_id p.json)\\nvideodraft shots \\"$PROJECT\\" && videodraft produce \\"$PROJECT\\"\\nvideodraft export \\"$PROJECT\\" --download changelog.mp4 --wait-timeout 30m\\n```\\n\\n## 5. Variations and picking a winner\\n\\n```bash\\nvideodraft generate image \\"logo concept: minimalist fox, geometric\\" --num 4 --download \\"./concepts/{job_id}_{index}.{ext}\\" --json\\n# Show all 4 to the user; regenerate the chosen one at higher res:\\nvideodraft generate image \\"<same prompt>\\" --model nano-banana-pro --resolution 4K\\n```\\n\\n## 6. Reaching tools without a curated command\\n\\n```bash\\nvideodraft tools list --json | jq -r \'.[].name\'\\nvideodraft tools schema attach_media_to_shot --json\\nvideodraft call attach_media_to_shot --args \'{\\"project_id\\":\\"...\\",\\"scene_index\\":0,\\"shot_index\\":1,\\"media_url\\":\\"https://...\\",\\"media_type\\":\\"video\\",\\"duration_seconds\\":6}\'\\n```\\n\\nAnything the VideoDraft MCP exposes \u2014 character studio, product studio, timeline editing \u2014 is reachable this way even before it gets a curated command.\\n","references/models.md":"# Choosing models (and predicting cost)\\n\\nAlways consult the live catalog instead of memorizing this page \u2014 models change weekly:\\n\\n```bash\\nvideodraft models image --json # every image model + inputs (aspect ratios, resolutions, max refs)\\nvideodraft models video --json # every video model + inputs + per-second pricing metadata\\nvideodraft models audio --json # standalone audio/media models + pricing inputs\\nvideodraft models voices --json # TTS voices\\nvideodraft models styles --json # visual style presets\\n```\\n\\n## Defaults (safe starting points)\\n\\n- **Image**: `nano-banana-2` (the platform default, 1K, up to 14 reference images). Use `--num 1..4` for variations of one prompt in a single call \u2014 never loop for variations. `nano-banana-2-lite` is the fastest/cheapest Google direct image model (1K only, up to 14 reference images).\\n- **Video**: `google-veo3.1` at fast quality (6s / 720p) \u2014 the platform default. `gemini-omni-flash` is Google\'s any-to-any multimodal video model (text/image/video \u2192 video, auto or 3-10s, 720p, audio always on).\\n- **Voiceover**: ElevenLabs Brittney (default voice).\\n- **Music**: `lyria-3-clip-preview` (30s, cheap); `lyria-3-pro-preview` for 180s/quality; `elevenlabs-music` for music that can include vocals/lyrics.\\n- **ElevenLabs audio**: `generate sound-effect`, `generate dialogue`, `generate voice-changer`, and `generate dub` are synchronous audio/media calls. Voice changer and dubbing require the source media duration in seconds for billing and currently accept source media up to 300s.\\n\\n## Capability gotchas\\n\\n- Each model\'s `inputs` block is authoritative: supported `aspect_ratios`, `resolutions`, `quality_options`, `start_frame`/`end_frame`, `max_reference_images/videos/audio`, `multi_prompt`, `audio_toggle`. Passing an unsupported input fails with a clear error \u2014 check first, don\'t trial-and-error paid calls.\\n- Most video models support only 16:9 / 9:16 / 1:1. A 3:4 request hard-fails on most.\\n- `--seed` reproduces a specific output on models that support it (e.g. Flux, Ideogram V4); everything else ignores it. You do not need a seed for variation \u2014 `--num` already varies.\\n- `--rendering-speed` applies to Ideogram (V3: `Default`/`Turbo`/`Quality`; V4: `Turbo`/`Balanced`/`Quality`) and affects image cost \u2014 pass it to `videodraft costs ... --rendering-speed <tier>` for an accurate estimate. Always trust `videodraft models image --json` over this list; new models and tiers appear there the moment the platform ships them, with no CLI update.\\n- Reference inputs: `--ref <img>` (images), `--ref-video <v>` (Gemini Omni Flash, Seedance 2, Kling O3, Wan 2.7), `--ref-audio <a>` (Seedance 2). The CLI uploads local files for all of these, so you can pass a path or a URL. `--segment \\"<prompt>:<seconds>\\"` (repeatable) drives multi-prompt models (Kling 3.0 / 3.0 Turbo / O3); total 3-15s. `generate image --video-ref` is the nano-banana-2 video reference.\\n- The top-level prompt is OPTIONAL for `generate video` with multi-prompt models and for Kling 3.0 Turbo (`--model kling-v3-turbo`) image-to-video \u2014 a `--segment`-only or `--start-image`-only call is valid. Every other model still needs a prompt; the server enforces per-model rules.\\n- AI Production: `videodraft produce <project> --mode full_video` generates one Seedance 2 video per scene; poll with `videodraft generations`, then `videodraft finalize <project>` swaps them into the timeline before `export`.\\n\\n## Cost model\\n\\n- Images: per image (\xD7 `--num`). Matrix-priced models (GPT-Image, Nano Banana Pro) vary by resolution/quality.\\n- Video: usually credits/second \xD7 duration; rate depends on model + resolution + quality + native audio on/off.\\n- Shot-image batches: one image per shot (+1 grid image per scene in `--grid` mode) \u2014 the largest single spend in the pipeline.\\n- Avatar renders: ~10 credits/sec at 480p, ~20/sec at 720p.\\n- ElevenLabs audio: sound effects are per second, dialogue is per character, music/voice-changer/dubbing are per started minute. Voice changer and dubbing reject source media above 300s in the current synchronous flow.\\n- Upscales: priced by scale and source size.\\n\\nQuote before spending:\\n\\n```bash\\nvideodraft costs google-veo3.1 --type video --duration 8 --resolution 1080p --audio\\nvideodraft costs elevenlabs-dubbing --type audio --duration 60\\nvideodraft costs elevenlabs-dialogue --type audio --chars 350\\nvideodraft generate video \\"...\\" --estimate # same quote, inline\\nvideodraft credits # current balance\\n```\\n","references/pipeline.md":"# VideoDraft pipeline reference\\n\\nEverything here works through the CLI (`videodraft <command>` / `videodraft call <tool>`) or the MCP connector (tool names in backticks). One backend; pick the surface you have.\\n\\n## Stages and their tools\\n\\n| Stage | CLI | Underlying tool |\\n|---|---|---|\\n| Idea \u2192 full storyboard project | `videodraft create \\"<idea>\\"` | `generate_storyboard_from_idea` |\\n| Idea \u2192 script only (stop there) | `videodraft create \\"<idea>\\" --script-only` | `generate_script_from_idea` |\\n| Footage IS the video | `videodraft call generate_storyboard_from_media` | `generate_storyboard_from_media` |\\n| Batch shot images | `videodraft shots <project>` | `generate_shot_images` |\\n| One shot image | `videodraft generate image --project <id> --scene N --shot M` | `generate_image` |\\n| Produce (voiceover, captions, timeline) | `videodraft produce <project>` | `produce_project` |\\n| Per-shot motion prompts | `videodraft video-prompts <project>` | `generate_video_prompts` |\\n| Motion clip for a shot | `videodraft generate video --project <id>` | `generate_video` |\\n| Attach a finished clip to the timeline | `videodraft attach <project> --scene N --shot M --media <url> --type video` | `attach_media_to_shot` |\\n| Background music | `videodraft generate music --attach <project>` | `generate_music` / `set_background_music` |\\n| Sound effect | `videodraft generate sound-effect \\"...\\"` | `generate_sound_effect` |\\n| Dialogue audio | `videodraft generate dialogue --line \\"voice:text\\"` | `generate_dialogue` |\\n| Voice changer | `videodraft generate voice-changer <audio>` | `change_voice` |\\n| Dubbing | `videodraft generate dub <audio_or_video>` | `dub_media` |\\n| Scene voiceover | `videodraft generate voiceover --project <id> --scene N` | `generate_voiceover` |\\n| Final MP4 | `videodraft export <project>` | `export_video` + `check_export_status` |\\n\\n## Rules that prevent broken results\\n\\n- **The storyboard is generated FROM the script**, never from the raw idea. `videodraft create` runs the whole chain correctly. Don\'t call `generate_storyboard_scenes` with a raw idea as the \\"script\\".\\n- **Visual consistency**: never generate a storyboard shot in isolation. Shot prompts carry `[[asset:Name]]` / `[[shot:X-Y]]` tags that `generate_shot_images` resolves against the project\'s visual assets and prior shots. When generating a single shot whose prompt has no tags, pass `--ref` images yourself (the project\'s visual assets and/or the previous shot\'s image \u2014 `projects get` exposes both). Grid mode (`--grid`) gives the strongest cross-shot consistency.\\n- **Hold off generating shot images while the user is still iterating** on storyboard structure.\\n- **produce \u2192 export ordering**: `export` requires a produced project where every production scene has timeline media. If `produce` returns `generating_shot_images`, poll the job ids it returns, then re-run produce.\\n- **Generated motion clips do not auto-attach**: after `generate video` completes, attach the clip with `attach_media_to_shot` (`media_type:\\"video\\"`, include `duration_seconds`) \u2014 it replaces the production timeline clip while keeping the storyboard still.\\n- **Timeouts on the one-shot create**: if `create` times out at the transport layer, the project was still created server-side \u2014 `videodraft projects list`, take the most recent, and resume with its id. Don\'t start a duplicate.\\n\\n## User-attached media: classify roles first\\n\\nFor EACH attached file decide:\\n\\n- **visual_asset** \u2014 recurring reference (character / product / location / style). Upload, then pass in `visual_assets` of `generate_storyboard_from_idea` (via `videodraft call`), or add to an existing project with `add_visual_assets`. Type must be one of `character | object | location | style | custom` with a short name + concrete description.\\n- **shot** \u2014 the media IS footage for the video. Whole video = footage \u2192 `generate_storyboard_from_media`. Idea + footage \u2192 `generate_storyboard_from_idea` with `shot_media`. Existing storyboard \u2192 `attach_media_to_shots`.\\n- **reference** \u2014 inspiration only \u2192 fold a description into the idea/instructions; don\'t place it as a shot or asset.\\n\\nAmbiguous (e.g. a person holding a product)? Ask the user.\\n\\nUploads persist in the media library \u2014 recall later with `videodraft media list`.\\n\\n## Editing project data safely\\n\\n1. `videodraft call get_project_schema` \u2014 read the structure once per session.\\n2. `videodraft projects get <id> --raw` \u2014 the exact editable blob.\\n3. Modify; then `videodraft call update_project --stdin` with `{\\"project_id\\": \\"...\\", \\"data\\": {...}}`.\\n - Objects deep-merge key-by-key; **arrays replace wholesale** \u2014 send the complete array you\'re changing (e.g. all of `storyboard.scenes`).\\n - Scene shot arrays (`image_prompt` / `shot_types` / `shot_actions` / `search_prompt` / `preview_media`) are auto-aligned; fix-ups come back as warnings.\\n4. Snapshot before risky edits: `videodraft checkpoint create <id> --name \\"before re-script\\"`. Restore with `videodraft checkpoint restore <id> <version>`.\\n\\n## AI Studio sessions (standalone generations)\\n\\nProject generations group automatically. For standalone work in a long conversation, create one session up front and reuse it:\\n\\n```bash\\nSESSION=$(videodraft call create_ai_studio_session --arg name=\\"Fox brand explorations\\" --json | jq -r .session_id)\\nvideodraft generate image \\"...\\" --session \\"$SESSION\\"\\n```\\n"}') {
3022
+ return JSON.parse('{"SKILL.md":"---\\nname: videodraft\\ndescription: Create AI videos, images, voiceovers, music, sound effects, dialogue, dubbing, storyboards, avatar videos and product/ad videos with VideoDraft. Use when the user mentions VideoDraft, or asks to generate/make a video, video ad, explainer, storyboard, talking-head/avatar video, AI image, voiceover/TTS, background music, sound effects, dialogue audio, voice changing, or dubbing \u2014 including batch/programmatic video generation in scripts or CI. Works via the `videodraft` CLI (preferred in terminals) or the VideoDraft MCP connector.\\nargument-hint: \\"[what to make, e.g. \\\\\\"a 6s cinematic video of a red fox\\\\\\"]\\"\\nallowed-tools: Bash(videodraft *) Bash(npx -y videodraft@latest *)\\n---\\n\\n# VideoDraft\\n\\nVideoDraft is an AI video creation platform where asset generation is the priority lane:\\n\\n- **Asset generation**: standalone images, video clips, voiceovers, music, sound effects, dialogue, voice-changed audio, dubbed media, upscales, and image descriptions. This is the fastest and most important lane. Treat these as complete deliverables when the user asks for assets.\\n- **Asset I/O**: upload local files, download outputs, auto-upload local references, and save generated media where the user can see it.\\n- **Project production**: idea \u2192 script \u2192 storyboard (scenes + shot images) \u2192 project data \u2192 production timeline \u2192 exported MP4. Use this only when the user asks for a story, storyboard, editable project, timeline, or final video.\\n\\n## How to connect\\n\\nTwo equivalent surfaces (same backend, same credits, same projects):\\n\\n1. **CLI** (preferred when you have a shell): run `videodraft` if it\'s on PATH; otherwise `npx -y videodraft@latest` runs it with no install (needs Node \u226520; the `-y` skips npx\'s install prompt so it runs non-interactively; the package is fetched on first use and cached). For heavy use, `npm install -g videodraft`. If there\'s no Node/shell here but the MCP connector below is available, use that instead; if neither works, tell the user how to install (https://videodraft.ai/cli).\\n - Auth \u2014 pick by context, don\'t guess:\\n \u2022 INTERACTIVE (a human is in the session, e.g. Claude Code / Codex): on exit code 3 (\\"not authenticated\\"), tell the user to run `videodraft login` in their terminal \u2014 it opens their browser for a one-click VideoDraft sign-in (OAuth), no key to copy. Wait for them to confirm it succeeded, then retry the command. This is the preferred path when the user is present.\\n \u2022 HEADLESS / CI (no browser): set `VIDEODRAFT_API_KEY=vd_mcp_...` (a token the user mints at https://app.videodraft.ai/mcp-keys).\\n \u2022 SECURITY: never ask the user to paste a `vd_mcp_...` token into the chat \u2014 use browser `login` or the env var so the token never lands in the transcript.\\n - Every command accepts `--json` (parse this, don\'t scrape text). Exit codes: 0 ok, 1 error, 2 usage, 3 auth (see Auth above), 4 insufficient credits (\u2192 tell the user, don\'t retry).\\n - Tool discovery: start with `videodraft tools list` for the grouped catalog, then narrow with `videodraft tools list --lane assets`, `--lane asset_io`, `--lane project_data`, or `--lane production`.\\n - Asset lane: `videodraft generate image|video|voiceover|music|sound-effect|dialogue|voice-changer|dub`, `videodraft upload`, and `videodraft download`.\\n - Full API access: `videodraft tools schema <name>`, `videodraft call <tool> --args \'<json>\'`.\\n2. **MCP connector**: if VideoDraft MCP tools (e.g. `generate_storyboard_from_idea`) are available, call them directly \u2014 the CLI\'s curated commands map 1:1 onto these tools.\\n\\n## First decision: asset or project?\\n\\n- **One standalone asset** (image, clip, voiceover, music track, sound effect, dialogue track, voice-changed file, dubbed media file, upscale, or description): generate it directly. Do NOT create a project.\\n - `videodraft generate image \\"a red fox in snow, cinematic\\" --ar 16:9 --download ./out/`\\n - `videodraft generate video \\"slow dolly over a misty lake\\" --model google-veo3.1 --duration 6 --download ./out/`\\n- **A small set of related assets**: still stay in the asset lane. Use an AI Studio session if you need to group related generations, but do not make a storyboard/project unless the user asks for one.\\n- **A multi-scene video / ad / explainer, storyboard, timeline, or final exported video**: create a project so the work stays organized, editable in the web app, and exportable.\\n - `videodraft create \\"30s launch video for our espresso machine\\" --ar 9:16`\\n- **Just a script** (no video asked for): `videodraft create \\"...\\" --script-only`. Stop at the script \u2014 do not build a storyboard the user didn\'t ask for.\\n- **Iterating on existing work**: find it first (`videodraft projects list`) and reuse that project. Never create a new project to change an existing one.\\n\\n## Credits: confirm before spending\\n\\nGeneration costs credits (video is per-second; shot-image batches are the largest single spend). Before anything expensive:\\n\\n1. `videodraft credits` \u2014 check the balance.\\n2. `videodraft generate video \\"...\\" --estimate` or `videodraft costs <model> --duration 8 --resolution 1080p` \u2014 get the quote. For ElevenLabs audio, use `--type audio` plus `--duration`, `--length`, or `--chars`.\\n3. Tell the user the model + settings + rough cost and get a go-ahead. Ask rather than assume aspect ratio, duration, and model when they matter.\\n4. Honor the user\'s stated preference on confirmation. If they tell you to stop asking (e.g. \\"don\'t ask me\\", \\"just go\\", \\"stop confirming cost\\"), proceed without a go-ahead for the rest of the session. If they say to always confirm, confirm every spend. Default when unspecified: confirm the first spend of a session and any unusually large one (a shot-image batch, a long or 1080p video).\\n\\n`videodraft models image|video|audio` lists every model with its supported inputs (aspect ratios, resolutions, reference limits, audio billing inputs) \u2014 consult it instead of guessing capabilities.\\n\\n## Async jobs\\n\\nImage/video generation is asynchronous: commands submit a job and **wait by default**, printing output URLs (and saving files with `--download`). In scripts/CI prefer explicit control:\\n\\n```bash\\nJOB=$(videodraft generate image \\"...\\" --no-wait --json | jq -r .job_id)\\nvideodraft wait \\"$JOB\\" --download \\"./outputs/{job_id}_{index}.{ext}\\" --json\\n```\\n\\nFor MANY jobs: submit each with `--no-wait`, collect ALL with one command \u2014 `videodraft wait <id1> <id2> ...` polls every job from one process with one batched request per tick. Do NOT spawn parallel `wait`/`generate --wait` processes for a batch.\\n\\nIf a wait times out, the job is still running server-side \u2014 `videodraft status <job_id>` later. Never re-submit just because a wait timed out (that double-spends credits).\\n\\n## Local files and reference images\\n\\nReference inputs must be public URLs. The CLI uploads local files automatically wherever a URL is expected (`--ref photo.jpg`, `--start-image frame.png`), or explicitly:\\n\\n```bash\\nURL=$(videodraft upload ./product.png --json | jq -r .url)\\n```\\n\\nNever silently drop a reference you couldn\'t upload \u2014 stop and tell the user. Never upload a user\'s file to a third-party host.\\n\\nWhen the user attaches media, classify each item before acting: a recurring **visual asset** (character/product/location/style), actual **footage to place as shots**, or **inspiration only**. See [references/pipeline.md](references/pipeline.md) for how each role flows into a project.\\n\\n## Showing media to the user\\n\\nGenerated media is **not** displayed in the chat automatically \u2014 you decide what to show. To preview an asset inline, save it locally (use `--download` so it lands under `media/`) and reference its **local path** as a Markdown link with a **leading `./`**:\\n\\n```\\n[ferrari shot](./media/ferrari_01.png) \u2190 image card\\n[the clip](./media/clip.mp4) \u2190 video player\\n[voiceover](./media/vo.mp3) \u2190 audio player\\n```\\n\\nPut the Markdown link **in your message text** \u2014 video and audio embed exactly like images. Do **not** use `SendUserFile` (or other file-send tools) to display media: that renders inside a collapsible tool card and gets buried in the tool list. The Markdown link in your prose is what produces the inline card.\\n\\nUse the path you saved to: a **workspace-relative** path (`./media/clip.mp4`, or `./<any-folder>/clip.mp4` \u2014 any folder in the workspace works), or the **absolute** path for a file outside the workspace (e.g. `/Users/you/Desktop/clip.mp4` or another workspace\'s path). Both render. Show the finished results worth showing (and only those \u2014 not every intermediate job). A bare CDN URL or a JSON dump of output URLs does **not** render; the local-path Markdown link is what produces an inline card.\\n\\n## The full pipeline (idea \u2192 MP4)\\n\\n```bash\\nvideodraft credits\\nvideodraft create \\"<idea>\\" --ar 9:16 # project: script \u2192 visual assets \u2192 storyboard\\nvideodraft shots <project_id> --grid --estimate # cost preview, confirm with user\\nvideodraft shots <project_id> --grid # batch shot images (waits, writes onto shot cards)\\nvideodraft produce <project_id> # voiceovers + captions + production timeline\\nvideodraft export <project_id> --download final.mp4\\n```\\n\\nOptional between produce and export: per-shot motion clips (`videodraft generate video ... --project <id>` then place it with `videodraft attach <project> --scene N --shot M --media <url|file> --type video --duration <s>`), music (`videodraft generate music \\"...\\" --attach <project_id>`), and standalone audio assets (`generate sound-effect`, `generate dialogue`, `generate voice-changer`, `generate dub`). Details, per-step tools and editing rules: [references/pipeline.md](references/pipeline.md).\\n\\nAvatar/talking-head videos are their own short flow: `videodraft avatar script` \u2192 `avatar create` \u2192 `avatar render` (paid step).\\n\\n## Working with project data\\n\\nA project is one JSON blob (script, storyboard scenes, shot cards, visual assets, production timeline). To inspect: `videodraft projects get <id>`. To edit: fetch `--raw`, modify, then `videodraft call update_project` \u2014 objects deep-merge, **arrays replace wholesale** (send the complete `storyboard.scenes` array to change one scene). Snapshot first with `videodraft checkpoint create <id>` before risky edits. Schema reference: `videodraft call get_project_schema`.\\n\\n## More\\n\\n- [references/pipeline.md](references/pipeline.md) \u2014 project data model, step-by-step tools, attaching media, editing safely\\n- [references/models.md](references/models.md) \u2014 choosing image/video models, pricing patterns, voices and styles\\n- [references/examples.md](references/examples.md) \u2014 recipes: batch product videos from a CSV, talking-head from a script, changelog video in CI\\n","references/examples.md":"# Recipes\\n\\nWorking patterns for common asks. All assume auth (`videodraft login` once, or `VIDEODRAFT_API_KEY` in the environment) and use `--json` for parsing.\\n\\n## 1. Batch product videos from a CSV\\n\\nOne 9:16 product clip per row of `products.csv` (`name,image_url,tagline`):\\n\\n```bash\\n#!/usr/bin/env bash\\nset -euo pipefail\\nmkdir -p outputs\\n\\nwhile IFS=, read -r name image tagline; do\\n job=$(videodraft generate video \\\\\\n \\"Premium product shot of ${name}: ${tagline}. Slow orbit, studio lighting.\\" \\\\\\n --model google-veo3.1 --ar 9:16 --duration 6 \\\\\\n --start-image \\"$image\\" \\\\\\n --no-wait --json | jq -r .job_id)\\n echo \\"$name,$job\\" >> outputs/jobs.csv\\ndone < <(tail -n +2 products.csv)\\n\\n# Collect ALL results with ONE process (batched polling \u2014 one request per tick)\\nvideodraft wait $(cut -d, -f2 outputs/jobs.csv) \\\\\\n --download \\"outputs/{job_id}_{index}.{ext}\\" --json > outputs/results.json\\n# map job ids back to product names via outputs/jobs.csv\\n```\\n\\nSubmit-then-collect parallelizes server-side generation; the single multi-id `wait` keeps it to one local process and one batched poll request per tick no matter how many jobs. Estimate first: `videodraft costs google-veo3.1 --type video --duration 6` \xD7 rows, and confirm with the user.\\n\\n## 2. Full marketing video from one idea\\n\\n```bash\\nvideodraft credits --json\\nvideodraft create \\"30-second launch video for Solace, a sleep-tracking ring. Calm, premium, dark palette.\\" \\\\\\n --ar 9:16 --style cinematic --json > project.json\\nPROJECT=$(jq -r .project_id project.json)\\n\\nvideodraft shots \\"$PROJECT\\" --grid --estimate # show the user the cost; get a go-ahead\\nvideodraft shots \\"$PROJECT\\" --grid\\nvideodraft produce \\"$PROJECT\\"\\nvideodraft generate music \\"minimal ambient, warm pads, 60 BPM\\" --attach \\"$PROJECT\\"\\nvideodraft export \\"$PROJECT\\" --download solace-launch.mp4\\n```\\n\\nThe project stays editable at the URL in `project.json` (`.urls`) \u2014 hand it to the user for tweaks.\\n\\n## 3. Talking-head (avatar) video\\n\\n```bash\\nSCRIPT=$(videodraft avatar script \\"why our espresso subscription saves you money\\" --style ad-style --json | jq -r .script)\\nAVATAR=$(videodraft avatar create ./founder.jpg --script \\"$SCRIPT\\" --ar 9:16 --json | jq -r .avatar_video_id)\\nvideodraft avatar render \\"$AVATAR\\" --resolution 720p # paid step \u2014 confirm cost first (~20 credits/sec)\\n```\\n\\n## 4. Changelog video in CI\\n\\nIn a GitHub Action with `VIDEODRAFT_API_KEY` set as a secret:\\n\\n```bash\\nNOTES=$(git log --oneline v1.2.0..HEAD | head -20)\\nvideodraft create \\"Weekly product update video. Energetic, 20 seconds. Changes: ${NOTES}\\" --ar 16:9 --json > p.json\\nPROJECT=$(jq -r .project_id p.json)\\nvideodraft shots \\"$PROJECT\\" && videodraft produce \\"$PROJECT\\"\\nvideodraft export \\"$PROJECT\\" --download changelog.mp4 --wait-timeout 30m\\n```\\n\\n## 5. Variations and picking a winner\\n\\n```bash\\nvideodraft generate image \\"logo concept: minimalist fox, geometric\\" --num 4 --download \\"./concepts/{job_id}_{index}.{ext}\\" --json\\n# Show all 4 to the user; regenerate the chosen one at higher res:\\nvideodraft generate image \\"<same prompt>\\" --model nano-banana-pro --resolution 4K\\n```\\n\\n## 6. Reaching tools without a curated command\\n\\n```bash\\nvideodraft tools list --json | jq -r \'.[].name\'\\nvideodraft tools schema attach_media_to_shot --json\\nvideodraft call attach_media_to_shot --args \'{\\"project_id\\":\\"...\\",\\"scene_index\\":0,\\"shot_index\\":1,\\"media_url\\":\\"https://...\\",\\"media_type\\":\\"video\\",\\"duration_seconds\\":6}\'\\n```\\n\\nAnything the VideoDraft MCP exposes \u2014 character studio, product studio, timeline editing \u2014 is reachable this way even before it gets a curated command.\\n","references/models.md":"# Choosing models (and predicting cost)\\n\\nAlways consult the live catalog instead of memorizing this page \u2014 models change weekly:\\n\\n```bash\\nvideodraft models image --json # every image model + inputs (aspect ratios, resolutions, max refs)\\nvideodraft models video --json # every video model + inputs + per-second pricing metadata\\nvideodraft models audio --json # standalone audio/media models + pricing inputs\\nvideodraft models voices --json # TTS voices\\nvideodraft models styles --json # visual style presets\\n```\\n\\n## Defaults (safe starting points)\\n\\n- **Image**: `nano-banana-2` (the platform default, 1K, up to 14 reference images). Use `--num 1..4` for variations of one prompt in a single call \u2014 never loop for variations. `nano-banana-2-lite` is the fastest/cheapest Google direct image model (1K only, up to 14 reference images).\\n- **Video**: `google-veo3.1` at fast quality (6s / 720p) \u2014 the platform default. `gemini-omni-flash` is Google\'s any-to-any multimodal video model (text/image/video \u2192 video, auto or 3-10s, 720p, audio always on).\\n- **Voiceover**: ElevenLabs Brittney (default voice).\\n- **Music**: `lyria-3-clip-preview` (30s, cheap); `lyria-3-pro-preview` for 180s/quality; `elevenlabs-music` for music that can include vocals/lyrics.\\n- **ElevenLabs audio**: `generate sound-effect`, `generate dialogue`, `generate voice-changer`, and `generate dub` are synchronous audio/media calls. Voice changer and dubbing require the source media duration in seconds for billing and currently accept source media up to 300s.\\n\\n## Capability gotchas\\n\\n- Each model\'s `inputs` block is authoritative: supported `aspect_ratios`, `resolutions`, `quality_options`, `start_frame`/`end_frame`, `max_reference_images/videos/audio`, `multi_prompt`, `audio_toggle`. Passing an unsupported input fails with a clear error \u2014 check first, don\'t trial-and-error paid calls.\\n- Most video models support only 16:9 / 9:16 / 1:1. A 3:4 request hard-fails on most.\\n- `--seed` reproduces a specific output on models that support it (e.g. Flux, Ideogram V4); everything else ignores it. You do not need a seed for variation \u2014 `--num` already varies.\\n- `--rendering-speed` applies to Ideogram (V3: `Default`/`Turbo`/`Quality`; V4: `Turbo`/`Balanced`/`Quality`) and affects image cost \u2014 pass it to `videodraft costs ... --rendering-speed <tier>` for an accurate estimate. Always trust `videodraft models image --json` over this list; new models and tiers appear there the moment the platform ships them, with no CLI update.\\n- Reference inputs: `--ref <img>` (images), `--ref-video <v>` (Gemini Omni Flash, Seedance 2, Kling O3, Wan 2.7), `--ref-audio <a>` (Seedance 2). The CLI uploads local files for all of these, so you can pass a path or a URL. `--segment \\"<prompt>:<seconds>\\"` (repeatable) drives multi-prompt models (Kling 3.0 / 3.0 Turbo / O3); total 3-15s. `generate image --video-ref` is the nano-banana-2 video reference.\\n- The top-level prompt is OPTIONAL for `generate video` with multi-prompt models and for Kling 3.0 Turbo (`--model kling-v3-turbo`) image-to-video \u2014 a `--segment`-only or `--start-image`-only call is valid. Every other model still needs a prompt; the server enforces per-model rules.\\n- AI Production: `videodraft produce <project> --mode full_video` generates one Seedance 2 video per scene; poll with `videodraft generations`, then `videodraft finalize <project>` swaps them into the timeline before `export`.\\n\\n## Cost model\\n\\n- Images: per image (\xD7 `--num`). Matrix-priced models (GPT-Image, Nano Banana Pro) vary by resolution/quality.\\n- Video: usually credits/second \xD7 duration; rate depends on model + resolution + quality + native audio on/off.\\n- Shot-image batches: one image per shot (+1 grid image per scene in `--grid` mode) \u2014 the largest single spend in the pipeline.\\n- Avatar renders: ~10 credits/sec at 480p, ~20/sec at 720p.\\n- ElevenLabs audio: sound effects are per second, dialogue is per character, music/voice-changer/dubbing are per started minute. Voice changer and dubbing reject source media above 300s in the current synchronous flow.\\n- Upscales: priced by scale and source size.\\n\\nQuote before spending:\\n\\n```bash\\nvideodraft costs google-veo3.1 --type video --duration 8 --resolution 1080p --audio\\nvideodraft costs elevenlabs-dubbing --type audio --duration 60\\nvideodraft costs elevenlabs-dialogue --type audio --chars 350\\nvideodraft generate video \\"...\\" --estimate # same quote, inline\\nvideodraft credits # current balance\\n```\\n","references/pipeline.md":"# VideoDraft pipeline reference\\n\\nEverything here works through the CLI (`videodraft <command>` / `videodraft call <tool>`) or the MCP connector (tool names in backticks). One backend; pick the surface you have.\\n\\n## Stages and their tools\\n\\n| Stage | CLI | Underlying tool |\\n|---|---|---|\\n| Idea \u2192 full storyboard project | `videodraft create \\"<idea>\\"` | `generate_storyboard_from_idea` |\\n| Idea \u2192 script only (stop there) | `videodraft create \\"<idea>\\" --script-only` | `generate_script_from_idea` |\\n| Footage IS the video | `videodraft call generate_storyboard_from_media` | `generate_storyboard_from_media` |\\n| Batch shot images | `videodraft shots <project>` | `generate_shot_images` |\\n| One shot image | `videodraft generate image --project <id> --scene N --shot M` | `generate_image` |\\n| Produce (voiceover, captions, timeline) | `videodraft produce <project>` | `produce_project` |\\n| Per-shot motion prompts | `videodraft video-prompts <project>` | `generate_video_prompts` |\\n| Motion clip for a shot | `videodraft generate video --project <id>` | `generate_video` |\\n| Attach a finished clip to the timeline | `videodraft attach <project> --scene N --shot M --media <url> --type video` | `attach_media_to_shot` |\\n| Background music | `videodraft generate music --attach <project>` | `generate_music` / `set_background_music` |\\n| Sound effect | `videodraft generate sound-effect \\"...\\"` | `generate_sound_effect` |\\n| Dialogue audio | `videodraft generate dialogue --line \\"voice:text\\"` | `generate_dialogue` |\\n| Voice changer | `videodraft generate voice-changer <audio>` | `change_voice` |\\n| Dubbing | `videodraft generate dub <audio_or_video>` | `dub_media` |\\n| Scene voiceover | `videodraft generate voiceover --project <id> --scene N` | `generate_voiceover` |\\n| Final MP4 | `videodraft export <project>` | `export_video` + `check_export_status` |\\n\\n## Rules that prevent broken results\\n\\n- **The storyboard is generated FROM the script**, never from the raw idea. `videodraft create` runs the whole chain correctly. Don\'t call `generate_storyboard_scenes` with a raw idea as the \\"script\\".\\n- **Visual consistency**: never generate a storyboard shot in isolation. Shot prompts carry `[[asset:Name]]` / `[[shot:X-Y]]` tags that `generate_shot_images` resolves against the project\'s visual assets and prior shots. When generating a single shot whose prompt has no tags, pass `--ref` images yourself (the project\'s visual assets and/or the previous shot\'s image \u2014 `projects get` exposes both). Grid mode (`--grid`) gives the strongest cross-shot consistency.\\n- **Hold off generating shot images while the user is still iterating** on storyboard structure.\\n- **produce \u2192 export ordering**: `export` requires a produced project where every production scene has timeline media. If `produce` returns `generating_shot_images`, poll the job ids it returns, then re-run produce.\\n- **Generated motion clips do not auto-attach**: after `generate video` completes, attach the clip with `attach_media_to_shot` (`media_type:\\"video\\"`, include `duration_seconds`) \u2014 it replaces the production timeline clip while keeping the storyboard still.\\n- **Timeouts on the one-shot create**: if `create` times out at the transport layer, the project was still created server-side \u2014 `videodraft projects list`, take the most recent, and resume with its id. Don\'t start a duplicate.\\n\\n## User-attached media: classify roles first\\n\\nFor EACH attached file decide:\\n\\n- **visual_asset** \u2014 recurring reference (character / product / location / style). Upload, then pass in `visual_assets` of `generate_storyboard_from_idea` (via `videodraft call`), or add to an existing project with `add_visual_assets`. Type must be one of `character | object | location | style | custom` with a short name + concrete description.\\n- **shot** \u2014 the media IS footage for the video. Whole video = footage \u2192 `generate_storyboard_from_media`. Idea + footage \u2192 `generate_storyboard_from_idea` with `shot_media`. Existing storyboard \u2192 `attach_media_to_shots`.\\n- **reference** \u2014 inspiration only \u2192 fold a description into the idea/instructions; don\'t place it as a shot or asset.\\n\\nAmbiguous (e.g. a person holding a product)? Ask the user.\\n\\nUploads persist in the media library \u2014 recall later with `videodraft media list`.\\n\\n## Editing project data safely\\n\\n1. `videodraft call get_project_schema` \u2014 read the structure once per session.\\n2. `videodraft projects get <id> --raw` \u2014 the exact editable blob.\\n3. Modify; then `videodraft call update_project --stdin` with `{\\"project_id\\": \\"...\\", \\"data\\": {...}}`.\\n - Objects deep-merge key-by-key; **arrays replace wholesale** \u2014 send the complete array you\'re changing (e.g. all of `storyboard.scenes`).\\n - Scene shot arrays (`image_prompt` / `shot_types` / `shot_actions` / `search_prompt` / `preview_media`) are auto-aligned; fix-ups come back as warnings.\\n4. Snapshot before risky edits: `videodraft checkpoint create <id> --name \\"before re-script\\"`. Restore with `videodraft checkpoint restore <id> <version>`.\\n\\n## AI Studio sessions (standalone generations)\\n\\nProject generations group automatically. For standalone work in a long conversation, create one session up front and reuse it:\\n\\n```bash\\nSESSION=$(videodraft call create_ai_studio_session --arg name=\\"Fox brand explorations\\" --json | jq -r .session_id)\\nvideodraft generate image \\"...\\" --session \\"$SESSION\\"\\n```\\n"}');
3023
+ }
3024
+ const root = bundledSkillDir();
3025
+ const files = {};
3026
+ const walk = (dir) => {
3027
+ for (const entry of fs7.readdirSync(dir, { withFileTypes: true })) {
3028
+ if (entry.name.startsWith(".")) continue;
3029
+ const full = path4.join(dir, entry.name);
3030
+ if (entry.isDirectory()) walk(full);
3031
+ else files[path4.relative(root, full).split(path4.sep).join("/")] = fs7.readFileSync(full, "utf8");
3032
+ }
3033
+ };
3034
+ walk(root);
3035
+ return files;
3036
+ }
3037
+ function writeSkillFiles(files, destRoot) {
3038
+ for (const [rel, content] of Object.entries(files)) {
3039
+ const dest = path4.join(destRoot, rel);
3040
+ fs7.mkdirSync(path4.dirname(dest), { recursive: true });
3041
+ fs7.writeFileSync(dest, content);
3027
3042
  }
3028
3043
  }
3029
3044
  var KNOWN_AGENTS = ["claude", "codex", "cursor"];
@@ -3067,6 +3082,13 @@ function resolveAgents(rawValues, all) {
3067
3082
  if (detected.length > 0) return { agents: detected, source: "detected" };
3068
3083
  return { agents: ["claude"], source: "default" };
3069
3084
  }
3085
+ var SECTION_ALIASES = {
3086
+ "": "SKILL.md",
3087
+ skill: "SKILL.md",
3088
+ examples: "references/examples.md",
3089
+ models: "references/models.md",
3090
+ pipeline: "references/pipeline.md"
3091
+ };
3070
3092
  function registerSkillCommands(program) {
3071
3093
  const skills = program.command("skills").description("The VideoDraft agent skill");
3072
3094
  skills.command("install").description("Install the VideoDraft skill (auto-detects your installed agents by default)").option(
@@ -3077,7 +3099,7 @@ function registerSkillCommands(program) {
3077
3099
  ).option("--all", "install for every supported agent (claude, codex, cursor)").option("--project", "install into the current project (./.claude/skills) instead of globally").option("--force", "overwrite existing installation(s)").action(async function() {
3078
3100
  const ctx = buildContext(this);
3079
3101
  const opts = this.opts();
3080
- const src = bundledSkillDir();
3102
+ const files = bundledSkillFiles();
3081
3103
  const { agents, source } = resolveAgents(opts.agent, Boolean(opts.all));
3082
3104
  if (source === "detected") {
3083
3105
  note(ctx.out, fmt.dim(ctx.out, `Detected installed agent(s): ${agents.join(", ")}`));
@@ -3093,7 +3115,7 @@ function registerSkillCommands(program) {
3093
3115
  if (existed && !opts.force) {
3094
3116
  return { agent, installed_to: dest, status: "skipped", reason: "already installed (use --force)" };
3095
3117
  }
3096
- copyDir(src, dest);
3118
+ writeSkillFiles(files, dest);
3097
3119
  return { agent, installed_to: dest, status: existed ? "overwritten" : "installed" };
3098
3120
  });
3099
3121
  capture("cli_skills_install", {
@@ -3111,16 +3133,46 @@ function registerSkillCommands(program) {
3111
3133
  note(o, fmt.green(o, `\u2022 ${r.agent}: ${r.status} \u2192 ${r.installed_to}`));
3112
3134
  }
3113
3135
  }
3114
- if (agents.includes("codex")) {
3115
- note(o, fmt.dim(o, 'Codex leans on AGENTS.md \u2014 also add "Use the videodraft skill for video/image generation" there.'));
3116
- }
3117
3136
  if (!anyInstalled) {
3118
3137
  note(o, fmt.dim(o, "Nothing changed. Re-run with --force to overwrite existing installs."));
3119
3138
  }
3120
3139
  note(o, fmt.dim(o, "Other agents: npx skills add videodraft-ai/cli"));
3121
3140
  });
3122
3141
  });
3123
- skills.command("path").description("Print the bundled skill's location (for manual installs)").action(async function() {
3142
+ skills.command("show [section]").description("Print the skill, or a section: skill | examples | models | pipeline").option("--all", "output every skill file as a JSON map (path \u2192 contents)").action(async function(section) {
3143
+ const ctx = buildContext(this);
3144
+ const opts = this.opts();
3145
+ const files = bundledSkillFiles();
3146
+ if (opts.all) {
3147
+ capture("cli_skills_show", { section: "all" });
3148
+ emit(ctx.out, { files }, (o) => {
3149
+ for (const [rel2, content2] of Object.entries(files)) {
3150
+ note(o, fmt.dim(o, `
3151
+ ===== ${rel2} =====`));
3152
+ process.stdout.write(content2.endsWith("\n") ? content2 : `${content2}
3153
+ `);
3154
+ }
3155
+ });
3156
+ return;
3157
+ }
3158
+ const key = (section ?? "").toLowerCase();
3159
+ let rel;
3160
+ if (Object.hasOwn(SECTION_ALIASES, key)) rel = SECTION_ALIASES[key];
3161
+ else if (section && Object.hasOwn(files, section)) rel = section;
3162
+ const content = rel === void 0 ? void 0 : files[rel];
3163
+ if (content === void 0) {
3164
+ throw new CliError(
3165
+ `Unknown skill section "${section}". Try: skill | examples | models | pipeline (or --all).`,
3166
+ EXIT.USAGE
3167
+ );
3168
+ }
3169
+ capture("cli_skills_show", { section: rel });
3170
+ emit(ctx.out, { section: rel, content }, () => {
3171
+ process.stdout.write(content.endsWith("\n") ? content : `${content}
3172
+ `);
3173
+ });
3174
+ });
3175
+ skills.command("path").description("Print the bundled skill's on-disk location (npm install; not the compiled binary)").action(async function() {
3124
3176
  const ctx = buildContext(this);
3125
3177
  const dir = bundledSkillDir();
3126
3178
  emit(ctx.out, { path: dir }, () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "videodraft",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "Official VideoDraft CLI — create AI videos, images and audio from your terminal. Agent-friendly: --json everywhere, stable exit codes, async job polling.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -52,7 +52,10 @@
52
52
  "test": "vitest run",
53
53
  "test:watch": "vitest",
54
54
  "test:e2e": "npm run build && node test/e2e-mock.mjs",
55
- "prepublishOnly": "npm run typecheck && npm run test && npm run build"
55
+ "gen:index": "tsx scripts/build-skills-index.ts",
56
+ "check:index": "tsx scripts/build-skills-index.ts --check",
57
+ "check:versions": "tsx scripts/check-manifest-versions.ts",
58
+ "prepublishOnly": "npm run typecheck && npm run check:versions && npm run check:index && npm run test && npm run build"
56
59
  },
57
60
  "dependencies": {
58
61
  "commander": "^14.0.0",
@@ -0,0 +1,31 @@
1
+ {
2
+ "version": 1,
3
+ "skills": [
4
+ {
5
+ "name": "videodraft",
6
+ "description": "Create AI videos, images, voiceovers, music, sound effects, dialogue, dubbing, storyboards, avatar videos and product/ad videos with VideoDraft. Use when the user mentions VideoDraft, or asks to generate/make a video, video ad, explainer, storyboard, talking-head/avatar video, AI image, voiceover/TTS, background music, sound effects, dialogue audio, voice changing, or dubbing — including batch/programmatic video generation in scripts or CI. Works via the `videodraft` CLI (preferred in terminals) or the VideoDraft MCP connector.",
7
+ "files": [
8
+ {
9
+ "path": "references/examples.md",
10
+ "sha256": "833120594712a0d07c30c31ab4e0f5974e0606900a2d045de819a0eeee71304c",
11
+ "bytes": 3590
12
+ },
13
+ {
14
+ "path": "references/models.md",
15
+ "sha256": "7a66b8fe74f67fff63ff6d40f89406dd6fed408c6b14ecfafa5339374296a822",
16
+ "bytes": 4537
17
+ },
18
+ {
19
+ "path": "references/pipeline.md",
20
+ "sha256": "bd2f89a96ad72035c794bb2e4d8000ae1c8278bcd7625e7db14477284d290726",
21
+ "bytes": 5392
22
+ },
23
+ {
24
+ "path": "SKILL.md",
25
+ "sha256": "50ca03232c37f60ff728524d15a49c5e76afcaae8ad4b85c61d12af2b1d183ef",
26
+ "bytes": 10791
27
+ }
28
+ ]
29
+ }
30
+ ]
31
+ }
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: videodraft
3
3
  description: Create AI videos, images, voiceovers, music, sound effects, dialogue, dubbing, storyboards, avatar videos and product/ad videos with VideoDraft. Use when the user mentions VideoDraft, or asks to generate/make a video, video ad, explainer, storyboard, talking-head/avatar video, AI image, voiceover/TTS, background music, sound effects, dialogue audio, voice changing, or dubbing — including batch/programmatic video generation in scripts or CI. Works via the `videodraft` CLI (preferred in terminals) or the VideoDraft MCP connector.
4
+ argument-hint: "[what to make, e.g. \"a 6s cinematic video of a red fox\"]"
5
+ allowed-tools: Bash(videodraft *) Bash(npx -y videodraft@latest *)
4
6
  ---
5
7
 
6
8
  # VideoDraft
@@ -15,7 +17,7 @@ VideoDraft is an AI video creation platform where asset generation is the priori
15
17
 
16
18
  Two equivalent surfaces (same backend, same credits, same projects):
17
19
 
18
- 1. **CLI** (preferred when you have a shell): run `videodraft` if it's on PATH; otherwise `npx videodraft` runs it with no install (needs Node ≥20; the package is fetched on first use and cached). For heavy use, `npm install -g videodraft`. If there's no Node/shell here but the MCP connector below is available, use that instead; if neither works, tell the user how to install (https://videodraft.ai/cli).
20
+ 1. **CLI** (preferred when you have a shell): run `videodraft` if it's on PATH; otherwise `npx -y videodraft@latest` runs it with no install (needs Node ≥20; the `-y` skips npx's install prompt so it runs non-interactively; the package is fetched on first use and cached). For heavy use, `npm install -g videodraft`. If there's no Node/shell here but the MCP connector below is available, use that instead; if neither works, tell the user how to install (https://videodraft.ai/cli).
19
21
  - Auth — pick by context, don't guess:
20
22
  • INTERACTIVE (a human is in the session, e.g. Claude Code / Codex): on exit code 3 ("not authenticated"), tell the user to run `videodraft login` in their terminal — it opens their browser for a one-click VideoDraft sign-in (OAuth), no key to copy. Wait for them to confirm it succeeded, then retry the command. This is the preferred path when the user is present.
21
23
  • HEADLESS / CI (no browser): set `VIDEODRAFT_API_KEY=vd_mcp_...` (a token the user mints at https://app.videodraft.ai/mcp-keys).
@@ -44,6 +46,7 @@ Generation costs credits (video is per-second; shot-image batches are the larges
44
46
  1. `videodraft credits` — check the balance.
45
47
  2. `videodraft generate video "..." --estimate` or `videodraft costs <model> --duration 8 --resolution 1080p` — get the quote. For ElevenLabs audio, use `--type audio` plus `--duration`, `--length`, or `--chars`.
46
48
  3. Tell the user the model + settings + rough cost and get a go-ahead. Ask rather than assume aspect ratio, duration, and model when they matter.
49
+ 4. Honor the user's stated preference on confirmation. If they tell you to stop asking (e.g. "don't ask me", "just go", "stop confirming cost"), proceed without a go-ahead for the rest of the session. If they say to always confirm, confirm every spend. Default when unspecified: confirm the first spend of a session and any unusually large one (a shot-image batch, a long or 1080p video).
47
50
 
48
51
  `videodraft models image|video|audio` lists every model with its supported inputs (aspect ratios, resolutions, reference limits, audio billing inputs) — consult it instead of guessing capabilities.
49
52
 
@@ -72,6 +75,20 @@ Never silently drop a reference you couldn't upload — stop and tell the user.
72
75
 
73
76
  When the user attaches media, classify each item before acting: a recurring **visual asset** (character/product/location/style), actual **footage to place as shots**, or **inspiration only**. See [references/pipeline.md](references/pipeline.md) for how each role flows into a project.
74
77
 
78
+ ## Showing media to the user
79
+
80
+ Generated media is **not** displayed in the chat automatically — you decide what to show. To preview an asset inline, save it locally (use `--download` so it lands under `media/`) and reference its **local path** as a Markdown link with a **leading `./`**:
81
+
82
+ ```
83
+ [ferrari shot](./media/ferrari_01.png) ← image card
84
+ [the clip](./media/clip.mp4) ← video player
85
+ [voiceover](./media/vo.mp3) ← audio player
86
+ ```
87
+
88
+ Put the Markdown link **in your message text** — video and audio embed exactly like images. Do **not** use `SendUserFile` (or other file-send tools) to display media: that renders inside a collapsible tool card and gets buried in the tool list. The Markdown link in your prose is what produces the inline card.
89
+
90
+ Use the path you saved to: a **workspace-relative** path (`./media/clip.mp4`, or `./<any-folder>/clip.mp4` — any folder in the workspace works), or the **absolute** path for a file outside the workspace (e.g. `/Users/you/Desktop/clip.mp4` or another workspace's path). Both render. Show the finished results worth showing (and only those — not every intermediate job). A bare CDN URL or a JSON dump of output URLs does **not** render; the local-path Markdown link is what produces an inline card.
91
+
75
92
  ## The full pipeline (idea → MP4)
76
93
 
77
94
  ```bash