@shotstack/cli 0.8.4 → 0.10.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shotstack/cli",
3
- "version": "0.8.4",
3
+ "version": "0.10.0",
4
4
  "description": "Command-line interface for the Shotstack video rendering API.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/shotstack/shotstack-cli",
@@ -27,7 +27,7 @@
27
27
  "test": "bun test"
28
28
  },
29
29
  "dependencies": {
30
- "@shotstack/schemas": "^1.20.1",
30
+ "@shotstack/schemas": "^1.22.0",
31
31
  "commander": "^12.1.0",
32
32
  "zod": "^4.4.3"
33
33
  },
@@ -13,11 +13,20 @@ license: Apache-2.0
13
13
 
14
14
  This skill loads in **terminal-based AI agents** (Claude Code, Cursor, Codex CLI, Gemini CLI, etc.). All operations here are shell commands. There is no embedded UI, no iframe, no inline canvas, no MCP tool surface — only `shotstack` invocations from a terminal. To hand off to a human, run `shotstack studio <file>`; this opens the user's default browser to a `shotstack.studio` URL. Tell the user to click Render *in the browser tab*, not in any UI inside the terminal.
15
15
 
16
+ ## Check versions once per session
17
+
18
+ This skill is version **0.10.0** and needs `@shotstack/cli` **0.10.0** or later. Before the first `shotstack` command in a session:
19
+
20
+ 1. Run `shotstack --version`. If it is older than 0.10.0, tell the user: what this skill documents, such as `generate --quote`, is missing until they run `npm install -g @shotstack/cli@latest`.
21
+ 2. Run `npm view @shotstack/cli version`. If it is newer than this skill's version, tell the user an update is available and ask whether to install it. Only on a yes, run `npx skills update shotstack -y` and `npm install -g @shotstack/cli@latest`. Never update without asking. `npx skills check` is not a read-only check: it installs the update.
22
+
23
+ If a check fails (no network, no npm, a sandbox), skip it and carry on.
24
+
16
25
  **Open-ended first render? Ask before composing.** If the ask doesn't state what the video is (subject, format or destination) — e.g. "render my first video", "make me a video", "set up Shotstack" — read [`references/onboarding.md`](references/onboarding.md) and ask its discovery questions, then WAIT for answers. Do not write an Edit first. An open-ended ask is not a specification, and a stray JSON file in the project doesn't make the user experienced. Compose without asking only when the user has stated what the video is, or explicitly says to just show anything.
17
26
 
18
- Commands for the Shotstack video rendering API. `render` submits an Edit JSON and returns a render ID; `status` polls a render until done. `ingest` uploads your own local files (or fetches remote URLs) and hosts them so they can be referenced from an Edit. `validate` lints an Edit — run it before every render. `studio` opens an edit in the browser editor for a human to preview, tweak, and render. `template list|get|create|update|delete` reads and writes templates saved to the account: `list` shows saved templates (id + name); `get <id>` fetches a saved template's Edit JSON (e.g. one the user designed in Studio) so you can render or remix it; `create <file> --name <name>` saves an edit as a new template; `update <id> <file>` overwrites one; `delete <id>` removes one.
27
+ Commands for the Shotstack video rendering API. `render` submits an Edit JSON and returns a render ID; `status` polls a render until done. `ingest` uploads your own local files (or fetches remote URLs) and hosts them so they can be referenced from an Edit. `validate` lints an Edit — run it before every render. `studio` opens an edit in the browser editor for a human to preview, tweak, and render. `template list|get|create|update|delete` reads and writes templates saved to the account: `list` shows saved templates (id + name); `get <id>` fetches a saved template's Edit JSON (e.g. one the user designed in Studio) so you can render or remix it; `create <file> --name <name>` saves an edit as a new template; `update <id> <file>` overwrites one; `delete <id>` removes one. `models` lists the generation models for prompt-driven assets and whether this key can use each one; `models <id>` prints the options a model accepts. `generate <model> "<prompt>"` generates one asset on its own and prints its URL.
19
28
 
20
- **Default loop — no API key required:** compose → `validate` (offline lint) → `studio` (browser preview). Only the API-backed commands (`render`, `status`, `ingest`) need a key. Reach for `render` when you specifically need a final MP4 exported in the cloud; reach for `studio` for everything else — it is the cheapest way to see an edit and the right default for any creative a human will review.
29
+ **Default loop — no API key required:** compose → `validate` (offline lint) → `studio` (browser preview). Only the API-backed commands (`render`, `status`, `ingest`, `models`, `generate`) need a key. Reach for `render` when you specifically need a final MP4 exported in the cloud; reach for `studio` for everything else — it is the cheapest way to see an edit and the right default for any creative a human will review.
21
30
 
22
31
  ## Authentication
23
32
 
@@ -36,7 +45,7 @@ Or set an environment variable (overrides the saved key — best for CI):
36
45
  export SHOTSTACK_API_KEY=...
37
46
  ```
38
47
 
39
- Resolution precedence: **`SHOTSTACK_API_KEY` env var → saved key for the target `--env` → error.** Get a key at <https://app.shotstack.io>. **`validate` and `studio` need no key** — only the API-backed commands (`render`, `status`, `ingest`) require one; without a key *those* exit 1, while compose → validate → studio keeps working.
48
+ Resolution precedence: **`SHOTSTACK_API_KEY` env var → saved key for the target `--env` → error.** Get a key at <https://app.shotstack.io>. **`validate` and `studio` need no key** — only the API-backed commands (`render`, `status`, `ingest`, `models`, `generate`) require one; without a key *those* exit 1, while compose → validate → studio keeps working.
40
49
 
41
50
  ## Environments
42
51
 
@@ -85,6 +94,31 @@ The bare command (no `--watch`) returns only an `id`; the hosted `source` URL do
85
94
 
86
95
  Other ingest subcommands: `ingest fetch <url>` (host a copy of a remote URL), `ingest status <id>`, `ingest list`, `ingest delete <id>`. **Read [`references/ingest.md`](references/ingest.md) for the full upload→render workflow, status values, and supported file types.**
87
96
 
97
+ ## Generating assets
98
+
99
+ An `image`, `video` or `audio` asset with a `prompt` and a `model` is generated by AI. `shotstack models` lists the models and whether this API key can use each one. `shotstack models <id>` adds the JSON Schema for that model's `options`. Read it before setting `options`, because values outside it are rejected.
100
+
101
+ ```sh
102
+ shotstack models --output json
103
+ shotstack models seedance-2.0-text-to-video --output json
104
+ ```
105
+
106
+ Offer only models marked available. `unavailable: AiCapabilityNotIncluded` means the plan doesn't include that kind of generation, `AiDisabled` means AI is turned off for the account, and `AiAccessUnavailable` means access couldn't be confirmed, so try again later. "availability unknown" means the check didn't run. It is not a yes.
107
+
108
+ `shotstack generate <model> "<prompt>"` generates one asset without rendering an edit and prints its URL. Use it to try a prompt, a voice or a still before building it into a timeline. Inside an edit, set `prompt` and `model` on the asset instead and it is generated at render time.
109
+
110
+ ```sh
111
+ shotstack generate nano-banana-2 "A ceramic mug on a walnut desk, soft window light" \
112
+ --options '{"resolution":"2K","aspectRatio":"16:9"}' --watch --output json | tail -n1 | jq -r .url
113
+ shotstack generate seedance-2.0-text-to-video "Waves break over black sand at dusk" --length 5 --watch
114
+ ```
115
+
116
+ `--length` is the clip length in seconds. Models that generate to a duration use it in place of their own duration option.
117
+
118
+ **Generation costs credits on stage as well as v1.** Before generating, run the same command with `--quote`, tell the user the model and the credits it prints (it says "up to" when the final charge can be lower), and wait for a yes. Identical requests share one job and its cached result: repeating a request while it runs, or after it finishes, returns the same job without charging again. That is also how to pick up a job started without `--watch`. Sending a failed generation again retries it, and that is charged.
119
+
120
+ **Read [`references/generation.md`](references/generation.md) before writing a prompt.** It covers what each model responds to, when to put text in a `rich-text` layer instead of the image, and how to size and chain generations inside an edit.
121
+
88
122
  ## Default workflow: preview in Studio (no key, no credits)
89
123
 
90
124
  **`shotstack studio <file>` is the default way to look at an edit** — prefer it over `render` unless you specifically need a cloud-exported MP4. It posts the JSON to https://shotstack.studio and opens `https://shotstack.studio/s/<slug>` in the browser — a short, shareable URL. No API key, no render credits charged; it previews client-side, so it works with no key. The human plays, edits, and decides whether to spend credits on a render.
@@ -163,6 +197,7 @@ This skill ships sub-references for the gnarly bits:
163
197
  - [`references/html5.md`](references/html5.md) — HTML5 asset: fields, preloaded libs (gsap/d3/anime/lottie), browser harness, sizing, worked examples
164
198
  - [`references/html5-snippets.md`](references/html5-snippets.md) — copy-paste motion-graphic clips: kinetic headline, value reveal, shine sweep, pulsing CTA, film grain
165
199
  - [`references/fonts.md`](references/fonts.md) — built-in fonts, Google Fonts URL pattern, custom-font workflow
200
+ - [`references/generation.md`](references/generation.md) — per-model prompting craft for AI-generated video, images, speech and music, and what a timeline adds to a prompt. Read before writing any `prompt`.
166
201
  - [`references/asset-library.md`](references/asset-library.md) — placeholder videos, images, music
167
202
  - [`references/troubleshooting.md`](references/troubleshooting.md) — common errors and fixes
168
203
 
@@ -183,7 +183,7 @@ Rich-caption transcribes audio to produce word-level timing. Three ways to sourc
183
183
 
184
184
  | `src` value | Behaviour |
185
185
  |---|---|
186
- | `alias://<name>` | Auto-transcribe a referenced audio/video/text-to-speech clip. Set `alias: "<name>"` on the source clip. **Preferred for sync.** |
186
+ | `alias://<name>` | Auto-transcribe a referenced audio or video clip, including generated speech. Set `alias: "<name>"` on the source clip. **Preferred for sync.** |
187
187
  | Subtitle file URL | Use existing `.srt` or `.vtt` file. No auto-transcription. |
188
188
  | Audio/video file URL | Auto-transcribe a standalone media file. Use when there's no source clip on the timeline. |
189
189
 
@@ -0,0 +1,100 @@
1
+ # Generating assets
2
+
3
+ `shotstack models <id>` shows what a model *accepts*. This is what produces a good result.
4
+
5
+ Set an asset's `prompt` and `model` and the asset is generated at render time; `options` configures the generator. Everything below is per-model craft, then a section on what the surrounding timeline can contribute.
6
+
7
+ ## Video — Seedance
8
+
9
+ **Verbs carry the generation.** The model animates motion, so spend the words there and describe consequences rather than states: "leaves scatter on each impact", not "leaves on the ground".
10
+
11
+ **Dialogue in double quotes gets lip-synced**, and picture and sound are generated in one pass rather than layered afterwards. Name the vocal tone you want.
12
+
13
+ **Silence is a parameter, not a phrase.** Set `generateAudio: false`. Writing "no music" in the prompt is not the mechanism.
14
+
15
+ **Cuts must be asked for**, with "cut to". Consistency holds across cuts inside a single generation — roughly three per take — and a multi-cut single generation is more consistent than the same shots generated separately.
16
+
17
+ **Duration is a beat budget.** Fit the described action to the time available. Overpacking a short clip produces rushing and incoherence; it does not compress gracefully. A prompt written for fifteen seconds will not survive being asked for five.
18
+
19
+ There is no prompt-length limit on the model itself. The API caps `prompt` at 4,000 characters.
20
+
21
+ **Choosing a generation.** 2.5 for duration: up to 30 seconds in one take, against 2.0's 15. ByteDance also claims better prompt adherence for 2.5, which its own pages don't corroborate. **2.0 for cost**: it is cheaper per second at every resolution, and both top out at 1080p. `shotstack models` has the current rates.
22
+
23
+ ## Images — Nano Banana
24
+
25
+ Write plain descriptive sentences, not comma-separated tags with quality boosters. Photographic and cinematographic vocabulary works and appears in the vendor's own examples: shot type, camera angle and proximity, lighting setup, lens and focal length.
26
+
27
+ **There is no negative prompt.** No such field exists. Phrase exclusions as positive instructions — "an empty desk" rather than "no clutter".
28
+
29
+ **Quote text that must appear**, and describe the font in plain words rather than by name:
30
+
31
+ ```
32
+ the text "Grand Opening" in a clean, bold, sans-serif
33
+ ```
34
+
35
+ Iterative refinement is not available on this route. Each generation is single-shot.
36
+
37
+ **Which tier.** The standard tier is the right default: on general image quality, character work and stylisation it matches or beats the Pro tier at roughly half the price, and it offers a 0.5K option Pro does not. Reach for Pro for hard, multi-instruction, information-dense compositions at high resolution, where its much larger output budget tells. Not for "better images" generally.
38
+
39
+ 1024–1536 px on the long edge suffices for screen use.
40
+
41
+ ### Text inside an image, or over it
42
+
43
+ Short, decorative, one line — generate it and check the result. Copy that must be spelled correctly, must run to several lines, or must survive a merge-field substitution — generate a plain background and composite a `rich-text` asset over it. A real font is spell-correct by construction, resolution-independent, and can be reworded without regenerating the image.
44
+
45
+ ## Speech
46
+
47
+ Three providers: **ElevenLabs**, **MiniMax** and **Amazon Polly**. Run `shotstack models` for the current ids.
48
+
49
+ The script is the instrument. Most bad output is a writing problem, not a settings problem.
50
+
51
+ **Numbers and currency are the most common defect.** Spell out anything you care about. Dates in numeric form are read as digit runs.
52
+
53
+ **ElevenLabs** is the default. Audio tags like `[laughs]` belong to a newer generation of its models and do nothing on the endpoints offered here. Stage directions written inline are read aloud rather than interpreted.
54
+
55
+ **Voice choice has no evidence behind it** beyond the vendors' own descriptors, and preset lists rotate. Pick by listening, not by name.
56
+
57
+ **Polly** takes a free-string voice and is the odd one out: its remedies are all SSML, which is unreachable because input is sent as plain text and escaped. Newscaster style works on four voices only — Matthew, Joanna, Lupe and Amy — and requesting it on any other fails the render.
58
+
59
+ **MiniMax** publishes a far larger voice catalogue than the seventeen names listed here, and several controls it supports — speed, volume, pitch, emotion — are not exposed. Treat the listed voices as the supported set.
60
+
61
+ Speech length is not knowable in advance. Set the clip's `length` to `"auto"` and let it take the produced file's duration, rather than guessing a slot and overrunning it.
62
+
63
+ ## Music
64
+
65
+ **Eleven Music.** A prompt answers genre, mood, instrumentation, tempo and production era whether or not you intend it to. Whatever you leave out, the model chooses.
66
+
67
+ **Production vocabulary does real work** — "dusty", "vinyl crackle", "sparse", "ethereal". Give a BPM when timing matters; the model holds a stated tempo precisely. Naming a key helps, less reliably.
68
+
69
+ **Naming a musician or band is refused**, as is quoting copyrighted lyrics. The error includes a suggested alternative prompt. Describe the era and production style instead: "1990s trip-hop with detuned Rhodes and a heavy swung break".
70
+
71
+ Add "instrumental only" to the prompt, or set `forceInstrumental` for a guarantee. That flag cannot be combined with a composition plan.
72
+
73
+ **Composition plans** describe a track section by section — reach for one when you need section structure, lyric placement or a multi-vocalist arrangement, not at any particular length. Section durations are exact and sum to the track length. Keep style entries as short tags, pair every positive list with a negative one, and put what should never change in the global styles. To keep a planned section instrumental, leave its `lines` empty and add "vocals" to its negative styles.
74
+
75
+ ## Working inside a timeline
76
+
77
+ An Edit knows things a bare prompt does not. This is the part no standalone generator can do for you.
78
+
79
+ **Match the generation's aspect ratio to your output.** A 9:16 generation inside a 16:9 edit gets cropped, and you paid for the pixels thrown away. The exception is deliberate: generate oversized when a later pan, zoom or reframe needs somewhere to move.
80
+
81
+ **Generate stills larger than the video that consumes them.** A 1K still feeding a 720p clip asks the video model to invent about half again as much detail as the source held. Use 2K when the target is 720p or above.
82
+
83
+ **Anchor stills become frame one, so everything static is inherited.** Composition, lighting and style all come from the still; the prompt should describe only motion. There is no fixing a badly-composed anchor in the video prompt. Artefacts get worse in motion rather than better, so a still with malformed hands or heavy compression is not usable.
84
+
85
+ **Chain at most two or three generated clips.** Feeding each clip's last frame into the next accumulates drift, and it degrades well before any advertised limit.
86
+
87
+ **Continuity across a cut is usually not what you want.** Most cuts are meant to break continuity — a new angle, a new location, a time jump. Carry a frame forward when you specifically want the shots to feel continuous, not by default.
88
+
89
+ **Keep a repeated style clause** across separately generated assets when they need to look like a set. There is no project-level style; the shared sentence is the mechanism.
90
+
91
+ ## What does not work
92
+
93
+ - **A fixed seed does not carry a look across different prompts.** Seeds give reproducibility for an identical prompt and nothing more.
94
+ - **Film stock names, "colour grade" and "LUT"** are not part of the documented vocabulary. Use shot type, lighting, angle and focal length instead.
95
+ - **Repeating the aspect ratio or resolution in the prompt** does nothing. Set the option.
96
+ - **Negative prompts** do not exist on the image models. Phrase it positively.
97
+
98
+ ## flux-schnell
99
+
100
+ No craft guidance. Its vendor no longer documents the endpoint anywhere, so nothing about it can be stated with confidence.
@@ -119,7 +119,7 @@ Then run `shotstack feedback` — the dossier captures the response body and the
119
119
 
120
120
  ## Render takes much longer than expected
121
121
 
122
- Renders containing AI-generation assets (`text-to-image`, `image-to-video`) take longer because the engine waits for the AI job to complete before rendering. Renders with very long source videos or many tracks also take longer.
122
+ Renders containing AI-generated assets (an `image`, `video` or `audio` asset with a `prompt`) take longer because the engine waits for the AI job to complete before rendering. Renders with very long source videos or many tracks also take longer.
123
123
 
124
124
  **Fix:** if you're iterating quickly, render with `output.resolution: "preview"` first (512×288 @ 15fps) to validate the timeline shape before spending credits on full-resolution output.
125
125
 
@@ -218,17 +218,14 @@ Use only the **current** asset types; the deprecated ones still parse but should
218
218
 
219
219
  | Type | Purpose |
220
220
  |---|---|
221
- | `video` | Video file (mp4, mov, webm). |
222
- | `image` | Static image — `jpg`, `png`, `webp`, `gif`, `bmp`, `tiff`. |
223
- | `audio` | Audio clip placed at a specific time on the timeline. |
221
+ | `video` | Video file (mp4, mov, webm), or AI-generated from a `prompt`. |
222
+ | `image` | Static image — `jpg`, `png`, `webp`, `gif`, `bmp`, `tiff` — or AI-generated from a `prompt`. |
223
+ | `audio` | Audio clip placed at a specific time on the timeline, or AI-generated speech or music from a `prompt`. |
224
224
  | `rich-text` | Styled text overlay with full typography control. **Use this instead of `text`/`html`/`title`.** |
225
225
  | `svg` | Vector graphics from raw SVG markup: `src` starts with `<svg`, never a URL or `data:` URI (the render fails). See `references/svg.md`. |
226
226
  | `html5` | Self-contained HTML/CSS/JS page rendered in an iframe (motion graphics, charts, animated overlays). Preloads gsap/d3/anime/lottie. See `references/html5.md`. **Never use the deprecated `html` asset.** |
227
227
  | `rich-caption` | Word-level animated captions sourced from audio, video, or subtitle files. See `references/caption.md`. |
228
228
  | `luma` | Luma matte for masking effects. |
229
- | `image-to-video` | **AI**: animate a still image into a short video clip. Billed per generation. |
230
- | `text-to-image` | **AI**: generate an image from a text prompt. Billed per generation. |
231
- | `text-to-speech` | **AI**: generate speech from a text prompt. Billed per generation. |
232
229
 
233
230
  `timeline.fonts[]` is a separate field for custom font URLs (not an asset type).
234
231
 
@@ -236,7 +233,7 @@ For background music, **use an `audio` asset on its own track** with `length: "e
236
233
 
237
234
  ### Deprecated — do not use
238
235
 
239
- `text`, `title`, `caption`, `html`, `shape`. They still parse but produce inferior output. Replace with:
236
+ `text`, `title`, `caption`, `html`, `shape`. They still parse but produce inferior output. `text-to-image`, `image-to-video` and `text-to-speech` still work, rewritten internally to the generated assets below. Replace with:
240
237
 
241
238
  | If you'd use… | Use instead |
242
239
  |---|---|
@@ -245,10 +242,19 @@ For background music, **use an `audio` asset on its own track** with `length: "e
245
242
  | `html` | `html5` (for motion graphics or animated overlays) or `rich-text` (for static styled text) |
246
243
  | `shape` | `svg` with `<rect>`, `<circle>`, `<polygon>` etc. |
247
244
  | `timeline.soundtrack` | `audio` asset on its own track with `length: "end"` |
245
+ | `text-to-image`, `image-to-video`, `text-to-speech` | `image`, `video` or `audio` with `prompt` and `model` (below) |
248
246
 
249
247
  ### AI-generated assets
250
248
 
251
- `image-to-video`, `text-to-speech`, and `text-to-image` are billed per generation **even when invoked through the sandbox stage endpoint** (which is otherwise free). They are async — the render submits the AI job and waits. Renders containing AI assets take longer.
249
+ Set `prompt` and `model` on an `image`, `video` or `audio` asset and it is generated at render time. `options` configures the model, and a `src` you set is only a preview placeholder that the generated file replaces. For speech, the prompt is the words to speak.
250
+
251
+ ```json
252
+ { "asset": { "type": "video", "prompt": "Slow dolly across a rain-soaked neon street at night", "model": "seedance-2.0-text-to-video", "options": { "resolution": "720p" } }, "start": 0, "length": 5 }
253
+ ```
254
+
255
+ The models endpoint (`GET /models`) lists each model, whether the account can use it, and the JSON Schema for its `options`. `POST /generate/quote` takes the same body as `POST /generate` and returns its cost in credits without charging. Options outside that schema are rejected. To animate a still, use an image-to-video model and put the image URL in `options.startSrc` (`inputSrc` on the original image-to-video models).
256
+
257
+ Generation is billed per asset **even on the stage endpoint**, which is otherwise free. Renders containing AI assets take longer, because the render waits for each generation.
252
258
 
253
259
  ## The design ladder — escalate from rich-text to html5
254
260