@shotstack/cli 0.2.0 → 0.3.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Shotstack CLI
2
2
 
3
- Command-line interface for the [Shotstack](https://shotstack.io) video rendering API. Built for humans and AI coding agents.
3
+ Command-line interface for the [Shotstack](https://shotstack.io) video rendering API. Built for humans and AI agents.
4
4
 
5
5
  ```sh
6
6
  shotstack render template.json
@@ -16,7 +16,7 @@ npm i -g @shotstack/cli
16
16
  # one-shot via npx
17
17
  npx @shotstack/cli render template.json
18
18
 
19
- # one-shot via bun (~100x faster than npx for cached invocations)
19
+ # one-shot via bun
20
20
  bunx @shotstack/cli render template.json
21
21
  ```
22
22
 
@@ -27,7 +27,7 @@ All three install paths use the same `@shotstack/cli` package on npm.
27
27
  Set your API key as an environment variable:
28
28
 
29
29
  ```sh
30
- export SHOTSTACK_API_KEY=sk_...
30
+ export SHOTSTACK_API_KEY=...
31
31
  ```
32
32
 
33
33
  Get a key at <https://shotstack.io>.
@@ -69,23 +69,24 @@ shotstack status 01ja7-x8m2k-... --watch
69
69
  shotstack status 01ja7-x8m2k-... --output json
70
70
  ```
71
71
 
72
- ### `shotstack preview <file>`
72
+ ### `shotstack studio <file>`
73
73
 
74
- Opens a `shotstack.studio` URL that loads the Edit JSON directly into the browser-based editor. No API call, no key, no charge — pure client-side encoding via the URL hash. Use it to hand a generated edit off to a human for review or quick tweaks before rendering.
74
+ Opens a `shotstack.studio` URL that loads the Edit JSON in the browser-based editor. By default, posts the JSON to the share API and emits a short URL like `https://shotstack.studio/s/abc12345` — clean, shareable, expires in 30 days. Falls back to inline base64url encoding if the share API is unreachable.
75
+
76
+ No render API key required; no render credits charged. Use to hand a generated edit off to a human for review or quick tweaks before rendering.
75
77
 
76
78
  ```sh
77
- shotstack preview my-template.json
78
- # → opens browser silently
79
+ shotstack studio my-template.json
80
+ # → opens browser silently with https://shotstack.studio/s/<slug>
79
81
 
80
- shotstack preview my-template.json --copy # also copies URL to clipboard
81
- shotstack preview my-template.json --no-open # print URL, don't open browser
82
- shotstack preview my-template.json --output json # emit {"url":"..."} on stdout
82
+ shotstack studio my-template.json --copy # also copies URL to clipboard
83
+ shotstack studio my-template.json --no-open # print URL, don't open browser
84
+ shotstack studio my-template.json --no-shorten # emit base64url inline (offline / debug)
85
+ shotstack studio my-template.json --output json # emit {"url":"...","shortened":true} on stdout
83
86
  ```
84
87
 
85
88
  When a browser can be launched, the command is silent — the URL only opens in the browser. On a headless server (no `$DISPLAY`, no `xdg-open`), the URL is printed to stdout instead so you can copy it elsewhere.
86
89
 
87
- Templates whose encoded URL exceeds ~6KB print a stderr warning. Browser URL limits vary; if you regularly exceed it, host the JSON publicly and link to it via `https://shotstack.studio/#src=<https-url>`.
88
-
89
90
  ### `shotstack feedback`
90
91
 
91
92
  Opens a pre-filled GitHub issue with a sanitised dossier of your last 5 CLI invocations (render IDs, errors, exit codes). API keys and signed URLs are stripped at write time. You review and submit in your browser; nothing is transmitted automatically. Inspect the log at `~/.shotstack/log.jsonl`.
package/SKILL.md CHANGED
@@ -47,16 +47,19 @@ shotstack status 01ja7-x8m2k-39rzv-cmvxve --watch
47
47
 
48
48
  ## Hand-off to a human before rendering
49
49
 
50
- When a human is in the loop and may want to tweak the result, prefer **`shotstack preview <file>`** over `shotstack render`. By default it opens the browser to `https://shotstack.studio/#json=<base64url>` and prints the URL — the timeline loads directly into the browser-based editor. No API call, no key, no charge. The human can play, edit, and decide whether to render — saving credits when the AI's first attempt isn't quite right.
50
+ When a human is in the loop and may want to tweak the result, prefer **`shotstack studio <file>`** over `shotstack render`. By default it posts the JSON to the share API and opens `https://shotstack.studio/s/<slug>` in the browser — a short, shareable URL. No API key, no render credits charged. The human can play, edit, and decide whether to render.
51
51
 
52
52
  ```sh
53
- shotstack preview template.json # opens browser + prints URL
54
- shotstack preview template.json --no-open # headless: just print the URL
55
- shotstack preview template.json --output json # piping: {"url":"..."}, no browser
53
+ shotstack studio template.json # opens browser + prints short URL
54
+ shotstack studio template.json --no-open # headless: just print the URL
55
+ shotstack studio template.json --no-shorten # emit base64url URL inline (offline / debug)
56
+ shotstack studio template.json --output json # piping: {"url":"...","shortened":true}, no browser
56
57
  ```
57
58
 
58
59
  On headless systems (no `xdg-open`, no `$DISPLAY`) the browser launch silently no-ops; the URL is still printed. Safe to run anywhere.
59
60
 
61
+ If the share API is unreachable, the command falls back to the inline base64url form automatically and prints a stderr warning. Shares expire after 30 days.
62
+
60
63
  Use `render` only when you're confident the JSON is final, or there's no human to review.
61
64
 
62
65
  ## Four CLI rules
@@ -67,164 +70,15 @@ Use `render` only when you're confident the JSON is final, or there's no human t
67
70
 
68
71
  3. **Fetch the current schema and docs before generating Edit JSON.** The Shotstack API evolves; LLM training data is often stale. Pull <https://shotstack.io/docs/api/api.edit.json> and <https://shotstack.io/docs/guide/llms-full.txt> for the current schema and guides before composing an Edit from scratch.
69
72
 
70
- 4. **Hand off to a human via `preview` when uncertain.** Don't burn render credits iterating. Generate JSON → `shotstack preview` → human reviews/tweaks → render only when right.
73
+ 4. **Hand off to a human via `studio` when uncertain.** Don't burn render credits iterating. Generate JSON → `shotstack studio` → human reviews/tweaks → render only when right.
71
74
 
72
75
  ## Authoring Edit JSON
73
76
 
74
- These are the conventions agents most often get wrong. Read this section before generating any Edit JSON.
75
-
76
- ### Before composing JSON: check the schema
77
-
78
- Don't invent property names or enum values. The Shotstack schema is published — fetch one of these before composing JSON from scratch:
79
-
80
- - <https://shotstack.io/docs/api/api.edit.json> — single-file OpenAPI Schema. Machine-validatable; load it once and validate locally instead of round-tripping the API.
81
- - <https://shotstack.io/docs/api/> — interactive HTML reference. Fastest for human scanning.
82
- - <https://shotstack.io/docs/guide/llms-full.txt> — single-file LLM-friendly version of the full guide + reference.
83
- - <https://github.com/shotstack/oas-api-definition/tree/main/schemas> — raw OpenAPI YAML, source of truth.
84
-
85
- CSS naming conventions (`alignment`, `vertical: "center"`) **do not** apply. The spec uses precise names that often differ from web/CSS instincts:
86
-
87
- | You'd guess (wrong) | API uses (right) |
88
- |---|---|
89
- | `alignment` | `align` |
90
- | `align.vertical: "center"` | `align.vertical: "middle"` |
91
- | `font.name` | `font.family` |
92
- | `duration` | `length` |
93
- | `transitions: [...]` (array) | `transition: { in, out }` (object) |
94
- | `fit: "cover"` (CSS instinct: scale+crop maintaining aspect) | `fit: "crop"` — Shotstack's `cover` STRETCHES without maintaining aspect ratio |
95
-
96
- When the API rejects a property, the error message names the field — fix and retry. Don't guess twice.
97
-
98
- ### Track ordering is REVERSED
99
-
100
- `timeline.tracks` is an array. **The first element (`tracks[0]`) is the TOP layer; the last element is the BOTTOM layer.** This is opposite to most z-index conventions.
101
-
102
- > "Tracks are layered on top of each other in the same order they are added to the array with the top most track layered over the top of those below it." — [Shotstack docs](https://shotstack.io/docs/guide/architecting-an-application/guidelines/)
103
-
104
- Practical rule: **put captions, overlays, and titles in early tracks; put video/image backgrounds in later tracks.**
105
-
106
- ```json
107
- {
108
- "timeline": {
109
- "tracks": [
110
- { "clips": [/* TOP — captions */] },
111
- { "clips": [/* MIDDLE — title overlay */] },
112
- { "clips": [/* BOTTOM — background video */] }
113
- ]
114
- }
115
- }
116
- ```
117
-
118
- ### Smart clip strings
119
-
120
- These string values are accepted in addition to numbers:
121
-
122
- | Where | Value | Meaning |
123
- |---|---|---|
124
- | `clip.start` | `"auto"` | Start when the previous clip on the same track finishes |
125
- | `clip.start` | `"alias://<name>"` | Inherit start from another clip with `alias: "<name>"` |
126
- | `clip.length` | `"auto"` | Play for the full duration of the asset |
127
- | `clip.length` | `"end"` | Play until the end of the timeline |
128
- | `clip.length` | `"alias://<name>"` | Inherit length from another clip |
129
-
130
- The `alias://` protocol is also used in `rich-caption` `src` to auto-transcribe a referenced audio/video clip — see `references/rich-caption.md`.
131
-
132
- ### Public HTTPS URLs only
133
-
134
- All asset `src` URLs must be publicly accessible HTTPS. **No local file paths, no `data:` URIs, no signed URLs that expire mid-render.** The render workers fetch assets from the public internet.
135
-
136
- For test renders without your own assets, use the placeholder library at <https://shotstack-assets.s3.amazonaws.com/> — see `references/asset-library.md`.
137
-
138
- ### Don't overlap clips on the same track
139
-
140
- Clips on the same track must not have overlapping `start`/`length` ranges. Overlapping clips flicker because the engine can't decide which to display. Put parallel content on separate tracks.
141
-
142
- ### Output resolution
143
-
144
- Pick `output.resolution` (preset) OR `output.size.width`+`output.size.height` (custom):
145
-
146
- | Preset | Pixels @ fps |
147
- |---|---|
148
- | `preview` | 512×288 @ 15 |
149
- | `mobile` | 640×360 @ 25 |
150
- | `sd` | 1024×576 @ 25 |
151
- | `hd` | 1280×720 @ 25 (default) |
152
- | `1080` | 1920×1080 @ 25 |
153
-
154
- Custom sizes must be divisible by 2.
155
-
156
- ## Asset types
157
-
158
- The render API supports many asset types. Use only the **current** ones; the deprecated ones still parse but should not be used in new templates.
159
-
160
- ### Current
161
-
162
- | Type | Purpose |
163
- |---|---|
164
- | `video` | Video file (mp4, mov, webm). |
165
- | `image` | Static image (jpg, png). |
166
- | `audio` | Audio clip placed at a specific time on the timeline. |
167
- | `rich-text` | Styled text overlay with full typography control. **Use this instead of `text`/`html`/`title`.** |
168
- | `svg` | Vector graphics from raw SVG markup. See `references/svg.md`. |
169
- | `rich-caption` | Word-level animated captions sourced from audio, video, or subtitle files. See `references/rich-caption.md`. |
170
- | `luma` | Luma matte for masking effects. |
171
- | `image-to-video` | **AI**: animate a still image into a short video clip. Billed per generation. |
172
- | `text-to-image` | **AI**: generate an image from a text prompt. Billed per generation. |
173
-
174
- `timeline.soundtrack` is a separate top-level field (not an asset type) for a single background music track. `timeline.fonts[]` is a separate field for custom font URLs.
175
-
176
- ### Deprecated — do not use
177
-
178
- `text`, `title`, `caption`, `html`, `shape`. They still parse but produce inferior output. Replace with:
179
-
180
- | If you'd use… | Use instead |
181
- |---|---|
182
- | `text` or `title` | `rich-text` |
183
- | `caption` | `rich-caption` |
184
- | `html` | `rich-text` |
185
- | `shape` | `svg` with `<rect>`, `<circle>`, `<polygon>` etc. |
186
-
187
- ### AI-generated assets
188
-
189
- `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.
190
-
191
- ## Fonts
192
-
193
- Prefer **custom Google Fonts via `timeline.fonts[]`** over the built-in font list. The Studio SDK exposes ~400 Google Fonts. See `references/fonts.md` for the URL pattern and the built-in fallback list.
194
-
195
- Per the [Shotstack docs](https://shotstack.io/docs/guide/architecting-an-application/rich-text/#custom-fonts), custom fonts give you the full Google Fonts catalogue with predictable rendering. System fonts like `Arial`, `Helvetica`, and `Times New Roman` are NOT installed and will fail with "Font not found".
196
-
197
- ```json
198
- {
199
- "timeline": {
200
- "fonts": [
201
- { "src": "https://fonts.gstatic.com/s/montserrat/v31/JTUSjIg1_i6t8kCHKm45xW5rygbi49c.ttf" }
202
- ],
203
- "tracks": [
204
- {
205
- "clips": [{
206
- "asset": {
207
- "type": "rich-text",
208
- "text": "Hello",
209
- "font": { "family": "JTUSjIg1_i6t8kCHKm45xW5rygbi49c", "size": 60, "color": "#ffffff" }
210
- },
211
- "start": 0, "length": 3
212
- }]
213
- }
214
- ]
215
- }
216
- }
217
- ```
218
-
219
- The `font.family` value is the **font file basename** (without `.ttf`/`.otf`).
77
+ The conventions agents most often get wrong (track order is reversed, asset type names, font allowlist, smart strings) live in the shared agent-core guide:
220
78
 
221
- ## Top 5 mistakes
79
+ **See [`shared/agent-core.md`](shared/agent-core.md)** before composing any Edit JSON.
222
80
 
223
- 1. **Reverse track order.** `tracks[0]` is the TOP layer, not the bottom. Captions go in early tracks; backgrounds go in late tracks.
224
- 2. **System fonts.** `Arial`, `Helvetica`, `Times New Roman`, etc. are not installed. Use Google Fonts via `timeline.fonts[]` (preferred) or one of the built-in fonts in `references/fonts.md`.
225
- 3. **Captions fill the whole frame.** A `rich-caption` clip without `width`, `height`, and `fit: "none"` covers the entire output. Use a named preset from `references/rich-caption.md`.
226
- 4. **`<text>` inside an SVG asset.** Raw `<text>` is unsupported. Use a `rich-text` asset for any text content; reserve SVG for shapes only.
227
- 5. **Composing custom caption styles when presets exist.** The five named presets (Nico, Kai, Kapow, Lovely Little Lychee, Rizz) cover the common styles. Use one verbatim from `references/rich-caption.md` unless the user asks for something specific.
81
+ This file is also delivered to chat-based clients (Claude.ai, ChatGPT) via the Shotstack MCP server, so the conventions stay identical across surfaces.
228
82
 
229
83
  ## Exit codes
230
84
 
@@ -239,6 +93,7 @@ The `font.family` value is the **font file basename** (without `.ttf`/`.otf`).
239
93
  Authoritative sources, in order of preference:
240
94
 
241
95
  - `shotstack --help` and `shotstack <command> --help` — current CLI flag listing
96
+ - [`shared/agent-core.md`](shared/agent-core.md) — Edit JSON authoring conventions (shared with MCP server)
242
97
  - <https://shotstack.io/docs/api/api.edit.json> — OpenAPI Schema for the render API (machine-validatable)
243
98
  - <https://shotstack.io/docs/guide/llms-full.txt> — full API docs in LLM-friendly single file
244
99
  - <https://github.com/shotstack/oas-api-definition/tree/main/schemas> — raw OpenAPI YAML, source of truth for property names and enums
@@ -248,8 +103,8 @@ Authoritative sources, in order of preference:
248
103
 
249
104
  This skill ships sub-references for the gnarly bits:
250
105
 
251
- - [`references/timeline.md`](references/timeline.md) — track layering, transitions, soundtrack vs audio
252
- - [`references/rich-caption.md`](references/rich-caption.md) — sizing per resolution, default style, the 5 named presets, alias pattern
106
+ - [`references/timeline.md`](references/timeline.md) — track layering, transitions, background music via audio assets
107
+ - [`references/caption.md`](references/caption.md) — sizing per resolution, default style, the 5 named presets, alias pattern (asset type: `rich-caption`)
253
108
  - [`references/svg.md`](references/svg.md) — required attrs, supported elements
254
109
  - [`references/fonts.md`](references/fonts.md) — built-in fonts, Google Fonts URL pattern, custom-font workflow
255
110
  - [`references/asset-library.md`](references/asset-library.md) — placeholder videos, images, music
package/dist/shotstack.js CHANGED
@@ -1,26 +1,26 @@
1
1
  #!/usr/bin/env node
2
- import{createRequire as sf}from"node:module";var Df=Object.create;var{getPrototypeOf:Ff,defineProperty:d,getOwnPropertyNames:kf}=Object;var uf=Object.prototype.hasOwnProperty;function Af(f){return this[f]}var Vf,xf,bf=(f,E,R)=>{var S=f!=null&&typeof f==="object";if(S){var w=E?Vf??=new WeakMap:xf??=new WeakMap,$=w.get(f);if($)return $}R=f!=null?Df(Ff(f)):{};let T=E||!f||!f.__esModule?d(R,"default",{value:f,enumerable:!0}):R;for(let _ of kf(f))if(!uf.call(T,_))d(T,_,{get:Af.bind(f,_),enumerable:!0});if(S)w.set(f,T);return T};var M=(f,E)=>()=>(E||f((E={exports:{}}).exports,E),E.exports);var N=sf(import.meta.url);var Q=M((Cf)=>{class x extends Error{constructor(f,E,R){super(R);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=E,this.exitCode=f,this.nestedError=void 0}}class o extends x{constructor(f){super(1,"commander.invalidArgument",f);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}}Cf.CommanderError=x;Cf.InvalidArgumentError=o});var K=M((nf)=>{var{InvalidArgumentError:vf}=Q();class e{constructor(f,E){switch(this.description=E||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,f[0]){case"<":this.required=!0,this._name=f.slice(1,-1);break;case"[":this.required=!1,this._name=f.slice(1,-1);break;default:this.required=!0,this._name=f;break}if(this._name.length>3&&this._name.slice(-3)==="...")this.variadic=!0,this._name=this._name.slice(0,-3)}name(){return this._name}_concatValue(f,E){if(E===this.defaultValue||!Array.isArray(E))return[f];return E.concat(f)}default(f,E){return this.defaultValue=f,this.defaultValueDescription=E,this}argParser(f){return this.parseArg=f,this}choices(f){return this.argChoices=f.slice(),this.parseArg=(E,R)=>{if(!this.argChoices.includes(E))throw new vf(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._concatValue(E,R);return E},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}}function cf(f){let E=f.name()+(f.variadic===!0?"...":"");return f.required?"<"+E+">":"["+E+"]"}nf.Argument=e;nf.humanReadableArgName=cf});var b=M((df)=>{var{humanReadableArgName:lf}=K();class p{constructor(){this.helpWidth=void 0,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}visibleCommands(f){let E=f.commands.filter((S)=>!S._hidden),R=f._getHelpCommand();if(R&&!R._hidden)E.push(R);if(this.sortSubcommands)E.sort((S,w)=>{return S.name().localeCompare(w.name())});return E}compareOptions(f,E){let R=(S)=>{return S.short?S.short.replace(/^-/,""):S.long.replace(/^--/,"")};return R(f).localeCompare(R(E))}visibleOptions(f){let E=f.options.filter((S)=>!S.hidden),R=f._getHelpOption();if(R&&!R.hidden){let S=R.short&&f._findOption(R.short),w=R.long&&f._findOption(R.long);if(!S&&!w)E.push(R);else if(R.long&&!w)E.push(f.createOption(R.long,R.description));else if(R.short&&!S)E.push(f.createOption(R.short,R.description))}if(this.sortOptions)E.sort(this.compareOptions);return E}visibleGlobalOptions(f){if(!this.showGlobalOptions)return[];let E=[];for(let R=f.parent;R;R=R.parent){let S=R.options.filter((w)=>!w.hidden);E.push(...S)}if(this.sortOptions)E.sort(this.compareOptions);return E}visibleArguments(f){if(f._argsDescription)f.registeredArguments.forEach((E)=>{E.description=E.description||f._argsDescription[E.name()]||""});if(f.registeredArguments.find((E)=>E.description))return f.registeredArguments;return[]}subcommandTerm(f){let E=f.registeredArguments.map((R)=>lf(R)).join(" ");return f._name+(f._aliases[0]?"|"+f._aliases[0]:"")+(f.options.length?" [options]":"")+(E?" "+E:"")}optionTerm(f){return f.flags}argumentTerm(f){return f.name()}longestSubcommandTermLength(f,E){return E.visibleCommands(f).reduce((R,S)=>{return Math.max(R,E.subcommandTerm(S).length)},0)}longestOptionTermLength(f,E){return E.visibleOptions(f).reduce((R,S)=>{return Math.max(R,E.optionTerm(S).length)},0)}longestGlobalOptionTermLength(f,E){return E.visibleGlobalOptions(f).reduce((R,S)=>{return Math.max(R,E.optionTerm(S).length)},0)}longestArgumentTermLength(f,E){return E.visibleArguments(f).reduce((R,S)=>{return Math.max(R,E.argumentTerm(S).length)},0)}commandUsage(f){let E=f._name;if(f._aliases[0])E=E+"|"+f._aliases[0];let R="";for(let S=f.parent;S;S=S.parent)R=S.name()+" "+R;return R+E+" "+f.usage()}commandDescription(f){return f.description()}subcommandDescription(f){return f.summary()||f.description()}optionDescription(f){let E=[];if(f.argChoices)E.push(`choices: ${f.argChoices.map((R)=>JSON.stringify(R)).join(", ")}`);if(f.defaultValue!==void 0){if(f.required||f.optional||f.isBoolean()&&typeof f.defaultValue==="boolean")E.push(`default: ${f.defaultValueDescription||JSON.stringify(f.defaultValue)}`)}if(f.presetArg!==void 0&&f.optional)E.push(`preset: ${JSON.stringify(f.presetArg)}`);if(f.envVar!==void 0)E.push(`env: ${f.envVar}`);if(E.length>0)return`${f.description} (${E.join(", ")})`;return f.description}argumentDescription(f){let E=[];if(f.argChoices)E.push(`choices: ${f.argChoices.map((R)=>JSON.stringify(R)).join(", ")}`);if(f.defaultValue!==void 0)E.push(`default: ${f.defaultValueDescription||JSON.stringify(f.defaultValue)}`);if(E.length>0){let R=`(${E.join(", ")})`;if(f.description)return`${f.description} ${R}`;return R}return f.description}formatHelp(f,E){let R=E.padWidth(f,E),S=E.helpWidth||80,w=2,$=2;function T(U,Y){if(Y){let V=`${U.padEnd(R+2)}${Y}`;return E.wrap(V,S-2,R+2)}return U}function _(U){return U.join(`
3
- `).replace(/^/gm," ".repeat(2))}let y=[`Usage: ${E.commandUsage(f)}`,""],L=E.commandDescription(f);if(L.length>0)y=y.concat([E.wrap(L,S,0),""]);let r=E.visibleArguments(f).map((U)=>{return T(E.argumentTerm(U),E.argumentDescription(U))});if(r.length>0)y=y.concat(["Arguments:",_(r),""]);let J=E.visibleOptions(f).map((U)=>{return T(E.optionTerm(U),E.optionDescription(U))});if(J.length>0)y=y.concat(["Options:",_(J),""]);if(this.showGlobalOptions){let U=E.visibleGlobalOptions(f).map((Y)=>{return T(E.optionTerm(Y),E.optionDescription(Y))});if(U.length>0)y=y.concat(["Global Options:",_(U),""])}let P=E.visibleCommands(f).map((U)=>{return T(E.subcommandTerm(U),E.subcommandDescription(U))});if(P.length>0)y=y.concat(["Commands:",_(P),""]);return y.join(`
4
- `)}padWidth(f,E){return Math.max(E.longestOptionTermLength(f,E),E.longestGlobalOptionTermLength(f,E),E.longestSubcommandTermLength(f,E),E.longestArgumentTermLength(f,E))}wrap(f,E,R,S=40){let $=new RegExp(`[\\n][${" \\f\\t\\v   -    \uFEFF"}]+`);if(f.match($))return f;let T=E-R;if(T<S)return f;let _=f.slice(0,R),y=f.slice(R).replace(`\r
2
+ import{createRequire as hf}from"node:module";var sf=Object.create;var{getPrototypeOf:kf,defineProperty:m,getOwnPropertyNames:Df}=Object;var Ff=Object.prototype.hasOwnProperty;function Af(f){return this[f]}var Vf,bf,xf=(f,r,E)=>{var t=f!=null&&typeof f==="object";if(t){var S=r?Vf??=new WeakMap:bf??=new WeakMap,R=S.get(f);if(R)return R}E=f!=null?sf(kf(f)):{};let w=r||!f||!f.__esModule?m(E,"default",{value:f,enumerable:!0}):E;for(let T of Df(f))if(!Ff.call(w,T))m(w,T,{get:Af.bind(f,T),enumerable:!0});if(t)S.set(f,w);return w};var M=(f,r)=>()=>(r||f((r={exports:{}}).exports,r),r.exports);var N=hf(import.meta.url);var Z=M((Cf)=>{class V extends Error{constructor(f,r,E){super(E);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=r,this.exitCode=f,this.nestedError=void 0}}class d extends V{constructor(f){super(1,"commander.invalidArgument",f);Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}}Cf.CommanderError=V;Cf.InvalidArgumentError=d});var H=M((gf)=>{var{InvalidArgumentError:cf}=Z();class e{constructor(f,r){switch(this.description=r||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,f[0]){case"<":this.required=!0,this._name=f.slice(1,-1);break;case"[":this.required=!1,this._name=f.slice(1,-1);break;default:this.required=!0,this._name=f;break}if(this._name.length>3&&this._name.slice(-3)==="...")this.variadic=!0,this._name=this._name.slice(0,-3)}name(){return this._name}_concatValue(f,r){if(r===this.defaultValue||!Array.isArray(r))return[f];return r.concat(f)}default(f,r){return this.defaultValue=f,this.defaultValueDescription=r,this}argParser(f){return this.parseArg=f,this}choices(f){return this.argChoices=f.slice(),this.parseArg=(r,E)=>{if(!this.argChoices.includes(r))throw new cf(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._concatValue(r,E);return r},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}}function nf(f){let r=f.name()+(f.variadic===!0?"...":"");return f.required?"<"+r+">":"["+r+"]"}gf.Argument=e;gf.humanReadableArgName=nf});var b=M((df)=>{var{humanReadableArgName:mf}=H();class p{constructor(){this.helpWidth=void 0,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}visibleCommands(f){let r=f.commands.filter((t)=>!t._hidden),E=f._getHelpCommand();if(E&&!E._hidden)r.push(E);if(this.sortSubcommands)r.sort((t,S)=>{return t.name().localeCompare(S.name())});return r}compareOptions(f,r){let E=(t)=>{return t.short?t.short.replace(/^-/,""):t.long.replace(/^--/,"")};return E(f).localeCompare(E(r))}visibleOptions(f){let r=f.options.filter((t)=>!t.hidden),E=f._getHelpOption();if(E&&!E.hidden){let t=E.short&&f._findOption(E.short),S=E.long&&f._findOption(E.long);if(!t&&!S)r.push(E);else if(E.long&&!S)r.push(f.createOption(E.long,E.description));else if(E.short&&!t)r.push(f.createOption(E.short,E.description))}if(this.sortOptions)r.sort(this.compareOptions);return r}visibleGlobalOptions(f){if(!this.showGlobalOptions)return[];let r=[];for(let E=f.parent;E;E=E.parent){let t=E.options.filter((S)=>!S.hidden);r.push(...t)}if(this.sortOptions)r.sort(this.compareOptions);return r}visibleArguments(f){if(f._argsDescription)f.registeredArguments.forEach((r)=>{r.description=r.description||f._argsDescription[r.name()]||""});if(f.registeredArguments.find((r)=>r.description))return f.registeredArguments;return[]}subcommandTerm(f){let r=f.registeredArguments.map((E)=>mf(E)).join(" ");return f._name+(f._aliases[0]?"|"+f._aliases[0]:"")+(f.options.length?" [options]":"")+(r?" "+r:"")}optionTerm(f){return f.flags}argumentTerm(f){return f.name()}longestSubcommandTermLength(f,r){return r.visibleCommands(f).reduce((E,t)=>{return Math.max(E,r.subcommandTerm(t).length)},0)}longestOptionTermLength(f,r){return r.visibleOptions(f).reduce((E,t)=>{return Math.max(E,r.optionTerm(t).length)},0)}longestGlobalOptionTermLength(f,r){return r.visibleGlobalOptions(f).reduce((E,t)=>{return Math.max(E,r.optionTerm(t).length)},0)}longestArgumentTermLength(f,r){return r.visibleArguments(f).reduce((E,t)=>{return Math.max(E,r.argumentTerm(t).length)},0)}commandUsage(f){let r=f._name;if(f._aliases[0])r=r+"|"+f._aliases[0];let E="";for(let t=f.parent;t;t=t.parent)E=t.name()+" "+E;return E+r+" "+f.usage()}commandDescription(f){return f.description()}subcommandDescription(f){return f.summary()||f.description()}optionDescription(f){let r=[];if(f.argChoices)r.push(`choices: ${f.argChoices.map((E)=>JSON.stringify(E)).join(", ")}`);if(f.defaultValue!==void 0){if(f.required||f.optional||f.isBoolean()&&typeof f.defaultValue==="boolean")r.push(`default: ${f.defaultValueDescription||JSON.stringify(f.defaultValue)}`)}if(f.presetArg!==void 0&&f.optional)r.push(`preset: ${JSON.stringify(f.presetArg)}`);if(f.envVar!==void 0)r.push(`env: ${f.envVar}`);if(r.length>0)return`${f.description} (${r.join(", ")})`;return f.description}argumentDescription(f){let r=[];if(f.argChoices)r.push(`choices: ${f.argChoices.map((E)=>JSON.stringify(E)).join(", ")}`);if(f.defaultValue!==void 0)r.push(`default: ${f.defaultValueDescription||JSON.stringify(f.defaultValue)}`);if(r.length>0){let E=`(${r.join(", ")})`;if(f.description)return`${f.description} ${E}`;return E}return f.description}formatHelp(f,r){let E=r.padWidth(f,r),t=r.helpWidth||80,S=2,R=2;function w(I,u){if(u){let A=`${I.padEnd(E+2)}${u}`;return r.wrap(A,t-2,E+2)}return I}function T(I){return I.join(`
3
+ `).replace(/^/gm," ".repeat(2))}let $=[`Usage: ${r.commandUsage(f)}`,""],_=r.commandDescription(f);if(_.length>0)$=$.concat([r.wrap(_,t,0),""]);let y=r.visibleArguments(f).map((I)=>{return w(r.argumentTerm(I),r.argumentDescription(I))});if(y.length>0)$=$.concat(["Arguments:",T(y),""]);let U=r.visibleOptions(f).map((I)=>{return w(r.optionTerm(I),r.optionDescription(I))});if(U.length>0)$=$.concat(["Options:",T(U),""]);if(this.showGlobalOptions){let I=r.visibleGlobalOptions(f).map((u)=>{return w(r.optionTerm(u),r.optionDescription(u))});if(I.length>0)$=$.concat(["Global Options:",T(I),""])}let P=r.visibleCommands(f).map((I)=>{return w(r.subcommandTerm(I),r.subcommandDescription(I))});if(P.length>0)$=$.concat(["Commands:",T(P),""]);return $.join(`
4
+ `)}padWidth(f,r){return Math.max(r.longestOptionTermLength(f,r),r.longestGlobalOptionTermLength(f,r),r.longestSubcommandTermLength(f,r),r.longestArgumentTermLength(f,r))}wrap(f,r,E,t=40){let R=new RegExp(`[\\n][${" \\f\\t\\v   -    \uFEFF"}]+`);if(f.match(R))return f;let w=r-E;if(w<t)return f;let T=f.slice(0,E),$=f.slice(E).replace(`\r
5
5
  `,`
6
- `),L=" ".repeat(R),J=`\\s${"​"}`,P=new RegExp(`
7
- |.{1,${T-1}}([${J}]|$)|[^${J}]+?([${J}]|$)`,"g"),U=y.match(P)||[];return _+U.map((Y,V)=>{if(Y===`
8
- `)return"";return(V>0?L:"")+Y.trimEnd()}).join(`
9
- `)}}df.Help=p});var s=M((fE)=>{var{InvalidArgumentError:ef}=Q();class a{constructor(f,E){this.flags=f,this.description=E||"",this.required=f.includes("<"),this.optional=f.includes("["),this.variadic=/\w\.\.\.[>\]]$/.test(f),this.mandatory=!1;let R=af(f);if(this.short=R.shortFlag,this.long=R.longFlag,this.negate=!1,this.long)this.negate=this.long.startsWith("--no-");this.defaultValue=void 0,this.defaultValueDescription=void 0,this.presetArg=void 0,this.envVar=void 0,this.parseArg=void 0,this.hidden=!1,this.argChoices=void 0,this.conflictsWith=[],this.implied=void 0}default(f,E){return this.defaultValue=f,this.defaultValueDescription=E,this}preset(f){return this.presetArg=f,this}conflicts(f){return this.conflictsWith=this.conflictsWith.concat(f),this}implies(f){let E=f;if(typeof f==="string")E={[f]:!0};return this.implied=Object.assign(this.implied||{},E),this}env(f){return this.envVar=f,this}argParser(f){return this.parseArg=f,this}makeOptionMandatory(f=!0){return this.mandatory=!!f,this}hideHelp(f=!0){return this.hidden=!!f,this}_concatValue(f,E){if(E===this.defaultValue||!Array.isArray(E))return[f];return E.concat(f)}choices(f){return this.argChoices=f.slice(),this.parseArg=(E,R)=>{if(!this.argChoices.includes(E))throw new ef(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._concatValue(E,R);return E},this}name(){if(this.long)return this.long.replace(/^--/,"");return this.short.replace(/^-/,"")}attributeName(){return pf(this.name().replace(/^no-/,""))}is(f){return this.short===f||this.long===f}isBoolean(){return!this.required&&!this.optional&&!this.negate}}class ff{constructor(f){this.positiveOptions=new Map,this.negativeOptions=new Map,this.dualOptions=new Set,f.forEach((E)=>{if(E.negate)this.negativeOptions.set(E.attributeName(),E);else this.positiveOptions.set(E.attributeName(),E)}),this.negativeOptions.forEach((E,R)=>{if(this.positiveOptions.has(R))this.dualOptions.add(R)})}valueFromOption(f,E){let R=E.attributeName();if(!this.dualOptions.has(R))return!0;let S=this.negativeOptions.get(R).presetArg,w=S!==void 0?S:!1;return E.negate===(w===f)}}function pf(f){return f.split("-").reduce((E,R)=>{return E+R[0].toUpperCase()+R.slice(1)})}function af(f){let E,R,S=f.split(/[ |,]+/);if(S.length>1&&!/^[[<]/.test(S[1]))E=S.shift();if(R=S.shift(),!E&&/^-[^-]$/.test(R))E=R,R=void 0;return{shortFlag:E,longFlag:R}}fE.Option=a;fE.DualOptions=ff});var Ef=M(($E)=>{function SE(f,E){if(Math.abs(f.length-E.length)>3)return Math.max(f.length,E.length);let R=[];for(let S=0;S<=f.length;S++)R[S]=[S];for(let S=0;S<=E.length;S++)R[0][S]=S;for(let S=1;S<=E.length;S++)for(let w=1;w<=f.length;w++){let $=1;if(f[w-1]===E[S-1])$=0;else $=1;if(R[w][S]=Math.min(R[w-1][S]+1,R[w][S-1]+1,R[w-1][S-1]+$),w>1&&S>1&&f[w-1]===E[S-2]&&f[w-2]===E[S-1])R[w][S]=Math.min(R[w][S],R[w-2][S-2]+1)}return R[f.length][E.length]}function wE(f,E){if(!E||E.length===0)return"";E=Array.from(new Set(E));let R=f.startsWith("--");if(R)f=f.slice(2),E=E.map((T)=>T.slice(2));let S=[],w=3,$=0.4;if(E.forEach((T)=>{if(T.length<=1)return;let _=SE(f,T),y=Math.max(f.length,T.length);if((y-_)/y>$){if(_<w)w=_,S=[T];else if(_===w)S.push(T)}}),S.sort((T,_)=>T.localeCompare(_)),R)S=S.map((T)=>`--${T}`);if(S.length>1)return`
10
- (Did you mean one of ${S.join(", ")}?)`;if(S.length===1)return`
11
- (Did you mean ${S[0]}?)`;return""}$E.suggestSimilar=wE});var $f=M((UE)=>{var _E=N("node:events").EventEmitter,C=N("node:child_process"),q=N("node:path"),h=N("node:fs"),I=N("node:process"),{Argument:yE,humanReadableArgName:LE}=K(),{CommanderError:O}=Q(),{Help:rE}=b(),{Option:Rf,DualOptions:IE}=s(),{suggestSimilar:Sf}=Ef();class v extends _E{constructor(f){super();this.commands=[],this.options=[],this.parent=null,this._allowUnknownOption=!1,this._allowExcessArguments=!0,this.registeredArguments=[],this._args=this.registeredArguments,this.args=[],this.rawArgs=[],this.processedArgs=[],this._scriptPath=null,this._name=f||"",this._optionValues={},this._optionValueSources={},this._storeOptionsAsProperties=!1,this._actionHandler=null,this._executableHandler=!1,this._executableFile=null,this._executableDir=null,this._defaultCommandName=null,this._exitCallback=null,this._aliases=[],this._combineFlagAndOptionalValue=!0,this._description="",this._summary="",this._argsDescription=void 0,this._enablePositionalOptions=!1,this._passThroughOptions=!1,this._lifeCycleHooks={},this._showHelpAfterError=!1,this._showSuggestionAfterError=!0,this._outputConfiguration={writeOut:(E)=>I.stdout.write(E),writeErr:(E)=>I.stderr.write(E),getOutHelpWidth:()=>I.stdout.isTTY?I.stdout.columns:void 0,getErrHelpWidth:()=>I.stderr.isTTY?I.stderr.columns:void 0,outputError:(E,R)=>R(E)},this._hidden=!1,this._helpOption=void 0,this._addImplicitHelpCommand=void 0,this._helpCommand=void 0,this._helpConfiguration={}}copyInheritedSettings(f){return this._outputConfiguration=f._outputConfiguration,this._helpOption=f._helpOption,this._helpCommand=f._helpCommand,this._helpConfiguration=f._helpConfiguration,this._exitCallback=f._exitCallback,this._storeOptionsAsProperties=f._storeOptionsAsProperties,this._combineFlagAndOptionalValue=f._combineFlagAndOptionalValue,this._allowExcessArguments=f._allowExcessArguments,this._enablePositionalOptions=f._enablePositionalOptions,this._showHelpAfterError=f._showHelpAfterError,this._showSuggestionAfterError=f._showSuggestionAfterError,this}_getCommandAndAncestors(){let f=[];for(let E=this;E;E=E.parent)f.push(E);return f}command(f,E,R){let S=E,w=R;if(typeof S==="object"&&S!==null)w=S,S=null;w=w||{};let[,$,T]=f.match(/([^ ]+) *(.*)/),_=this.createCommand($);if(S)_.description(S),_._executableHandler=!0;if(w.isDefault)this._defaultCommandName=_._name;if(_._hidden=!!(w.noHelp||w.hidden),_._executableFile=w.executableFile||null,T)_.arguments(T);if(this._registerCommand(_),_.parent=this,_.copyInheritedSettings(this),S)return this;return _}createCommand(f){return new v(f)}createHelp(){return Object.assign(new rE,this.configureHelp())}configureHelp(f){if(f===void 0)return this._helpConfiguration;return this._helpConfiguration=f,this}configureOutput(f){if(f===void 0)return this._outputConfiguration;return Object.assign(this._outputConfiguration,f),this}showHelpAfterError(f=!0){if(typeof f!=="string")f=!!f;return this._showHelpAfterError=f,this}showSuggestionAfterError(f=!0){return this._showSuggestionAfterError=!!f,this}addCommand(f,E){if(!f._name)throw Error(`Command passed to .addCommand() must have a name
12
- - specify the name in Command constructor or using .name()`);if(E=E||{},E.isDefault)this._defaultCommandName=f._name;if(E.noHelp||E.hidden)f._hidden=!0;return this._registerCommand(f),f.parent=this,f._checkForBrokenPassThrough(),this}createArgument(f,E){return new yE(f,E)}argument(f,E,R,S){let w=this.createArgument(f,E);if(typeof R==="function")w.default(S).argParser(R);else w.default(R);return this.addArgument(w),this}arguments(f){return f.trim().split(/ +/).forEach((E)=>{this.argument(E)}),this}addArgument(f){let E=this.registeredArguments.slice(-1)[0];if(E&&E.variadic)throw Error(`only the last argument can be variadic '${E.name()}'`);if(f.required&&f.defaultValue!==void 0&&f.parseArg===void 0)throw Error(`a default value for a required argument is never used: '${f.name()}'`);return this.registeredArguments.push(f),this}helpCommand(f,E){if(typeof f==="boolean")return this._addImplicitHelpCommand=f,this;f=f??"help [command]";let[,R,S]=f.match(/([^ ]+) *(.*)/),w=E??"display help for command",$=this.createCommand(R);if($.helpOption(!1),S)$.arguments(S);if(w)$.description(w);return this._addImplicitHelpCommand=!0,this._helpCommand=$,this}addHelpCommand(f,E){if(typeof f!=="object")return this.helpCommand(f,E),this;return this._addImplicitHelpCommand=!0,this._helpCommand=f,this}_getHelpCommand(){if(this._addImplicitHelpCommand??(this.commands.length&&!this._actionHandler&&!this._findCommand("help"))){if(this._helpCommand===void 0)this.helpCommand(void 0,void 0);return this._helpCommand}return null}hook(f,E){let R=["preSubcommand","preAction","postAction"];if(!R.includes(f))throw Error(`Unexpected value for event passed to hook : '${f}'.
13
- Expecting one of '${R.join("', '")}'`);if(this._lifeCycleHooks[f])this._lifeCycleHooks[f].push(E);else this._lifeCycleHooks[f]=[E];return this}exitOverride(f){if(f)this._exitCallback=f;else this._exitCallback=(E)=>{if(E.code!=="commander.executeSubCommandAsync")throw E};return this}_exit(f,E,R){if(this._exitCallback)this._exitCallback(new O(f,E,R));I.exit(f)}action(f){let E=(R)=>{let S=this.registeredArguments.length,w=R.slice(0,S);if(this._storeOptionsAsProperties)w[S]=this;else w[S]=this.opts();return w.push(this),f.apply(this,w)};return this._actionHandler=E,this}createOption(f,E){return new Rf(f,E)}_callParseArg(f,E,R,S){try{return f.parseArg(E,R)}catch(w){if(w.code==="commander.invalidArgument"){let $=`${S} ${w.message}`;this.error($,{exitCode:w.exitCode,code:w.code})}throw w}}_registerOption(f){let E=f.short&&this._findOption(f.short)||f.long&&this._findOption(f.long);if(E){let R=f.long&&this._findOption(f.long)?f.long:f.short;throw Error(`Cannot add option '${f.flags}'${this._name&&` to command '${this._name}'`} due to conflicting flag '${R}'
14
- - already used by option '${E.flags}'`)}this.options.push(f)}_registerCommand(f){let E=(S)=>{return[S.name()].concat(S.aliases())},R=E(f).find((S)=>this._findCommand(S));if(R){let S=E(this._findCommand(R)).join("|"),w=E(f).join("|");throw Error(`cannot add command '${w}' as already have command '${S}'`)}this.commands.push(f)}addOption(f){this._registerOption(f);let E=f.name(),R=f.attributeName();if(f.negate){let w=f.long.replace(/^--no-/,"--");if(!this._findOption(w))this.setOptionValueWithSource(R,f.defaultValue===void 0?!0:f.defaultValue,"default")}else if(f.defaultValue!==void 0)this.setOptionValueWithSource(R,f.defaultValue,"default");let S=(w,$,T)=>{if(w==null&&f.presetArg!==void 0)w=f.presetArg;let _=this.getOptionValue(R);if(w!==null&&f.parseArg)w=this._callParseArg(f,w,_,$);else if(w!==null&&f.variadic)w=f._concatValue(w,_);if(w==null)if(f.negate)w=!1;else if(f.isBoolean()||f.optional)w=!0;else w="";this.setOptionValueWithSource(R,w,T)};if(this.on("option:"+E,(w)=>{let $=`error: option '${f.flags}' argument '${w}' is invalid.`;S(w,$,"cli")}),f.envVar)this.on("optionEnv:"+E,(w)=>{let $=`error: option '${f.flags}' value '${w}' from env '${f.envVar}' is invalid.`;S(w,$,"env")});return this}_optionEx(f,E,R,S,w){if(typeof E==="object"&&E instanceof Rf)throw Error("To add an Option object use addOption() instead of option() or requiredOption()");let $=this.createOption(E,R);if($.makeOptionMandatory(!!f.mandatory),typeof S==="function")$.default(w).argParser(S);else if(S instanceof RegExp){let T=S;S=(_,y)=>{let L=T.exec(_);return L?L[0]:y},$.default(w).argParser(S)}else $.default(S);return this.addOption($)}option(f,E,R,S){return this._optionEx({},f,E,R,S)}requiredOption(f,E,R,S){return this._optionEx({mandatory:!0},f,E,R,S)}combineFlagAndOptionalValue(f=!0){return this._combineFlagAndOptionalValue=!!f,this}allowUnknownOption(f=!0){return this._allowUnknownOption=!!f,this}allowExcessArguments(f=!0){return this._allowExcessArguments=!!f,this}enablePositionalOptions(f=!0){return this._enablePositionalOptions=!!f,this}passThroughOptions(f=!0){return this._passThroughOptions=!!f,this._checkForBrokenPassThrough(),this}_checkForBrokenPassThrough(){if(this.parent&&this._passThroughOptions&&!this.parent._enablePositionalOptions)throw Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`)}storeOptionsAsProperties(f=!0){if(this.options.length)throw Error("call .storeOptionsAsProperties() before adding options");if(Object.keys(this._optionValues).length)throw Error("call .storeOptionsAsProperties() before setting option values");return this._storeOptionsAsProperties=!!f,this}getOptionValue(f){if(this._storeOptionsAsProperties)return this[f];return this._optionValues[f]}setOptionValue(f,E){return this.setOptionValueWithSource(f,E,void 0)}setOptionValueWithSource(f,E,R){if(this._storeOptionsAsProperties)this[f]=E;else this._optionValues[f]=E;return this._optionValueSources[f]=R,this}getOptionValueSource(f){return this._optionValueSources[f]}getOptionValueSourceWithGlobals(f){let E;return this._getCommandAndAncestors().forEach((R)=>{if(R.getOptionValueSource(f)!==void 0)E=R.getOptionValueSource(f)}),E}_prepareUserArgs(f,E){if(f!==void 0&&!Array.isArray(f))throw Error("first parameter to parse must be array or undefined");if(E=E||{},f===void 0&&E.from===void 0){if(I.versions?.electron)E.from="electron";let S=I.execArgv??[];if(S.includes("-e")||S.includes("--eval")||S.includes("-p")||S.includes("--print"))E.from="eval"}if(f===void 0)f=I.argv;this.rawArgs=f.slice();let R;switch(E.from){case void 0:case"node":this._scriptPath=f[1],R=f.slice(2);break;case"electron":if(I.defaultApp)this._scriptPath=f[1],R=f.slice(2);else R=f.slice(1);break;case"user":R=f.slice(0);break;case"eval":R=f.slice(1);break;default:throw Error(`unexpected parse option { from: '${E.from}' }`)}if(!this._name&&this._scriptPath)this.nameFromFilename(this._scriptPath);return this._name=this._name||"program",R}parse(f,E){let R=this._prepareUserArgs(f,E);return this._parseCommand([],R),this}async parseAsync(f,E){let R=this._prepareUserArgs(f,E);return await this._parseCommand([],R),this}_executeSubCommand(f,E){E=E.slice();let R=!1,S=[".js",".ts",".tsx",".mjs",".cjs"];function w(L,r){let J=q.resolve(L,r);if(h.existsSync(J))return J;if(S.includes(q.extname(r)))return;let P=S.find((U)=>h.existsSync(`${J}${U}`));if(P)return`${J}${P}`;return}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let $=f._executableFile||`${this._name}-${f._name}`,T=this._executableDir||"";if(this._scriptPath){let L;try{L=h.realpathSync(this._scriptPath)}catch(r){L=this._scriptPath}T=q.resolve(q.dirname(L),T)}if(T){let L=w(T,$);if(!L&&!f._executableFile&&this._scriptPath){let r=q.basename(this._scriptPath,q.extname(this._scriptPath));if(r!==this._name)L=w(T,`${r}-${f._name}`)}$=L||$}R=S.includes(q.extname($));let _;if(I.platform!=="win32")if(R)E.unshift($),E=wf(I.execArgv).concat(E),_=C.spawn(I.argv[0],E,{stdio:"inherit"});else _=C.spawn($,E,{stdio:"inherit"});else E.unshift($),E=wf(I.execArgv).concat(E),_=C.spawn(I.execPath,E,{stdio:"inherit"});if(!_.killed)["SIGUSR1","SIGUSR2","SIGTERM","SIGINT","SIGHUP"].forEach((r)=>{I.on(r,()=>{if(_.killed===!1&&_.exitCode===null)_.kill(r)})});let y=this._exitCallback;_.on("close",(L)=>{if(L=L??1,!y)I.exit(L);else y(new O(L,"commander.executeSubCommandAsync","(close)"))}),_.on("error",(L)=>{if(L.code==="ENOENT"){let r=T?`searched for local subcommand relative to directory '${T}'`:"no directory for search for local subcommand, use .executableDir() to supply a custom directory",J=`'${$}' does not exist
6
+ `),_=" ".repeat(E),U=`\\s${"​"}`,P=new RegExp(`
7
+ |.{1,${w-1}}([${U}]|$)|[^${U}]+?([${U}]|$)`,"g"),I=$.match(P)||[];return T+I.map((u,A)=>{if(u===`
8
+ `)return"";return(A>0?_:"")+u.trimEnd()}).join(`
9
+ `)}}df.Help=p});var x=M((rr)=>{var{InvalidArgumentError:pf}=Z();class a{constructor(f,r){this.flags=f,this.description=r||"",this.required=f.includes("<"),this.optional=f.includes("["),this.variadic=/\w\.\.\.[>\]]$/.test(f),this.mandatory=!1;let E=fr(f);if(this.short=E.shortFlag,this.long=E.longFlag,this.negate=!1,this.long)this.negate=this.long.startsWith("--no-");this.defaultValue=void 0,this.defaultValueDescription=void 0,this.presetArg=void 0,this.envVar=void 0,this.parseArg=void 0,this.hidden=!1,this.argChoices=void 0,this.conflictsWith=[],this.implied=void 0}default(f,r){return this.defaultValue=f,this.defaultValueDescription=r,this}preset(f){return this.presetArg=f,this}conflicts(f){return this.conflictsWith=this.conflictsWith.concat(f),this}implies(f){let r=f;if(typeof f==="string")r={[f]:!0};return this.implied=Object.assign(this.implied||{},r),this}env(f){return this.envVar=f,this}argParser(f){return this.parseArg=f,this}makeOptionMandatory(f=!0){return this.mandatory=!!f,this}hideHelp(f=!0){return this.hidden=!!f,this}_concatValue(f,r){if(r===this.defaultValue||!Array.isArray(r))return[f];return r.concat(f)}choices(f){return this.argChoices=f.slice(),this.parseArg=(r,E)=>{if(!this.argChoices.includes(r))throw new pf(`Allowed choices are ${this.argChoices.join(", ")}.`);if(this.variadic)return this._concatValue(r,E);return r},this}name(){if(this.long)return this.long.replace(/^--/,"");return this.short.replace(/^-/,"")}attributeName(){return af(this.name().replace(/^no-/,""))}is(f){return this.short===f||this.long===f}isBoolean(){return!this.required&&!this.optional&&!this.negate}}class ff{constructor(f){this.positiveOptions=new Map,this.negativeOptions=new Map,this.dualOptions=new Set,f.forEach((r)=>{if(r.negate)this.negativeOptions.set(r.attributeName(),r);else this.positiveOptions.set(r.attributeName(),r)}),this.negativeOptions.forEach((r,E)=>{if(this.positiveOptions.has(E))this.dualOptions.add(E)})}valueFromOption(f,r){let E=r.attributeName();if(!this.dualOptions.has(E))return!0;let t=this.negativeOptions.get(E).presetArg,S=t!==void 0?t:!1;return r.negate===(S===f)}}function af(f){return f.split("-").reduce((r,E)=>{return r+E[0].toUpperCase()+E.slice(1)})}function fr(f){let r,E,t=f.split(/[ |,]+/);if(t.length>1&&!/^[[<]/.test(t[1]))r=t.shift();if(E=t.shift(),!r&&/^-[^-]$/.test(E))r=E,E=void 0;return{shortFlag:r,longFlag:E}}rr.Option=a;rr.DualOptions=ff});var rf=M((wr)=>{function Sr(f,r){if(Math.abs(f.length-r.length)>3)return Math.max(f.length,r.length);let E=[];for(let t=0;t<=f.length;t++)E[t]=[t];for(let t=0;t<=r.length;t++)E[0][t]=t;for(let t=1;t<=r.length;t++)for(let S=1;S<=f.length;S++){let R=1;if(f[S-1]===r[t-1])R=0;else R=1;if(E[S][t]=Math.min(E[S-1][t]+1,E[S][t-1]+1,E[S-1][t-1]+R),S>1&&t>1&&f[S-1]===r[t-2]&&f[S-2]===r[t-1])E[S][t]=Math.min(E[S][t],E[S-2][t-2]+1)}return E[f.length][r.length]}function Rr(f,r){if(!r||r.length===0)return"";r=Array.from(new Set(r));let E=f.startsWith("--");if(E)f=f.slice(2),r=r.map((w)=>w.slice(2));let t=[],S=3,R=0.4;if(r.forEach((w)=>{if(w.length<=1)return;let T=Sr(f,w),$=Math.max(f.length,w.length);if(($-T)/$>R){if(T<S)S=T,t=[w];else if(T===S)t.push(w)}}),t.sort((w,T)=>w.localeCompare(T)),E)t=t.map((w)=>`--${w}`);if(t.length>1)return`
10
+ (Did you mean one of ${t.join(", ")}?)`;if(t.length===1)return`
11
+ (Did you mean ${t[0]}?)`;return""}wr.suggestSimilar=Rr});var Rf=M((Ur)=>{var $r=N("node:events").EventEmitter,h=N("node:child_process"),q=N("node:path"),C=N("node:fs"),L=N("node:process"),{Argument:_r,humanReadableArgName:yr}=H(),{CommanderError:O}=Z(),{Help:Lr}=b(),{Option:Ef,DualOptions:Ir}=x(),{suggestSimilar:tf}=rf();class v extends $r{constructor(f){super();this.commands=[],this.options=[],this.parent=null,this._allowUnknownOption=!1,this._allowExcessArguments=!0,this.registeredArguments=[],this._args=this.registeredArguments,this.args=[],this.rawArgs=[],this.processedArgs=[],this._scriptPath=null,this._name=f||"",this._optionValues={},this._optionValueSources={},this._storeOptionsAsProperties=!1,this._actionHandler=null,this._executableHandler=!1,this._executableFile=null,this._executableDir=null,this._defaultCommandName=null,this._exitCallback=null,this._aliases=[],this._combineFlagAndOptionalValue=!0,this._description="",this._summary="",this._argsDescription=void 0,this._enablePositionalOptions=!1,this._passThroughOptions=!1,this._lifeCycleHooks={},this._showHelpAfterError=!1,this._showSuggestionAfterError=!0,this._outputConfiguration={writeOut:(r)=>L.stdout.write(r),writeErr:(r)=>L.stderr.write(r),getOutHelpWidth:()=>L.stdout.isTTY?L.stdout.columns:void 0,getErrHelpWidth:()=>L.stderr.isTTY?L.stderr.columns:void 0,outputError:(r,E)=>E(r)},this._hidden=!1,this._helpOption=void 0,this._addImplicitHelpCommand=void 0,this._helpCommand=void 0,this._helpConfiguration={}}copyInheritedSettings(f){return this._outputConfiguration=f._outputConfiguration,this._helpOption=f._helpOption,this._helpCommand=f._helpCommand,this._helpConfiguration=f._helpConfiguration,this._exitCallback=f._exitCallback,this._storeOptionsAsProperties=f._storeOptionsAsProperties,this._combineFlagAndOptionalValue=f._combineFlagAndOptionalValue,this._allowExcessArguments=f._allowExcessArguments,this._enablePositionalOptions=f._enablePositionalOptions,this._showHelpAfterError=f._showHelpAfterError,this._showSuggestionAfterError=f._showSuggestionAfterError,this}_getCommandAndAncestors(){let f=[];for(let r=this;r;r=r.parent)f.push(r);return f}command(f,r,E){let t=r,S=E;if(typeof t==="object"&&t!==null)S=t,t=null;S=S||{};let[,R,w]=f.match(/([^ ]+) *(.*)/),T=this.createCommand(R);if(t)T.description(t),T._executableHandler=!0;if(S.isDefault)this._defaultCommandName=T._name;if(T._hidden=!!(S.noHelp||S.hidden),T._executableFile=S.executableFile||null,w)T.arguments(w);if(this._registerCommand(T),T.parent=this,T.copyInheritedSettings(this),t)return this;return T}createCommand(f){return new v(f)}createHelp(){return Object.assign(new Lr,this.configureHelp())}configureHelp(f){if(f===void 0)return this._helpConfiguration;return this._helpConfiguration=f,this}configureOutput(f){if(f===void 0)return this._outputConfiguration;return Object.assign(this._outputConfiguration,f),this}showHelpAfterError(f=!0){if(typeof f!=="string")f=!!f;return this._showHelpAfterError=f,this}showSuggestionAfterError(f=!0){return this._showSuggestionAfterError=!!f,this}addCommand(f,r){if(!f._name)throw Error(`Command passed to .addCommand() must have a name
12
+ - specify the name in Command constructor or using .name()`);if(r=r||{},r.isDefault)this._defaultCommandName=f._name;if(r.noHelp||r.hidden)f._hidden=!0;return this._registerCommand(f),f.parent=this,f._checkForBrokenPassThrough(),this}createArgument(f,r){return new _r(f,r)}argument(f,r,E,t){let S=this.createArgument(f,r);if(typeof E==="function")S.default(t).argParser(E);else S.default(E);return this.addArgument(S),this}arguments(f){return f.trim().split(/ +/).forEach((r)=>{this.argument(r)}),this}addArgument(f){let r=this.registeredArguments.slice(-1)[0];if(r&&r.variadic)throw Error(`only the last argument can be variadic '${r.name()}'`);if(f.required&&f.defaultValue!==void 0&&f.parseArg===void 0)throw Error(`a default value for a required argument is never used: '${f.name()}'`);return this.registeredArguments.push(f),this}helpCommand(f,r){if(typeof f==="boolean")return this._addImplicitHelpCommand=f,this;f=f??"help [command]";let[,E,t]=f.match(/([^ ]+) *(.*)/),S=r??"display help for command",R=this.createCommand(E);if(R.helpOption(!1),t)R.arguments(t);if(S)R.description(S);return this._addImplicitHelpCommand=!0,this._helpCommand=R,this}addHelpCommand(f,r){if(typeof f!=="object")return this.helpCommand(f,r),this;return this._addImplicitHelpCommand=!0,this._helpCommand=f,this}_getHelpCommand(){if(this._addImplicitHelpCommand??(this.commands.length&&!this._actionHandler&&!this._findCommand("help"))){if(this._helpCommand===void 0)this.helpCommand(void 0,void 0);return this._helpCommand}return null}hook(f,r){let E=["preSubcommand","preAction","postAction"];if(!E.includes(f))throw Error(`Unexpected value for event passed to hook : '${f}'.
13
+ Expecting one of '${E.join("', '")}'`);if(this._lifeCycleHooks[f])this._lifeCycleHooks[f].push(r);else this._lifeCycleHooks[f]=[r];return this}exitOverride(f){if(f)this._exitCallback=f;else this._exitCallback=(r)=>{if(r.code!=="commander.executeSubCommandAsync")throw r};return this}_exit(f,r,E){if(this._exitCallback)this._exitCallback(new O(f,r,E));L.exit(f)}action(f){let r=(E)=>{let t=this.registeredArguments.length,S=E.slice(0,t);if(this._storeOptionsAsProperties)S[t]=this;else S[t]=this.opts();return S.push(this),f.apply(this,S)};return this._actionHandler=r,this}createOption(f,r){return new Ef(f,r)}_callParseArg(f,r,E,t){try{return f.parseArg(r,E)}catch(S){if(S.code==="commander.invalidArgument"){let R=`${t} ${S.message}`;this.error(R,{exitCode:S.exitCode,code:S.code})}throw S}}_registerOption(f){let r=f.short&&this._findOption(f.short)||f.long&&this._findOption(f.long);if(r){let E=f.long&&this._findOption(f.long)?f.long:f.short;throw Error(`Cannot add option '${f.flags}'${this._name&&` to command '${this._name}'`} due to conflicting flag '${E}'
14
+ - already used by option '${r.flags}'`)}this.options.push(f)}_registerCommand(f){let r=(t)=>{return[t.name()].concat(t.aliases())},E=r(f).find((t)=>this._findCommand(t));if(E){let t=r(this._findCommand(E)).join("|"),S=r(f).join("|");throw Error(`cannot add command '${S}' as already have command '${t}'`)}this.commands.push(f)}addOption(f){this._registerOption(f);let r=f.name(),E=f.attributeName();if(f.negate){let S=f.long.replace(/^--no-/,"--");if(!this._findOption(S))this.setOptionValueWithSource(E,f.defaultValue===void 0?!0:f.defaultValue,"default")}else if(f.defaultValue!==void 0)this.setOptionValueWithSource(E,f.defaultValue,"default");let t=(S,R,w)=>{if(S==null&&f.presetArg!==void 0)S=f.presetArg;let T=this.getOptionValue(E);if(S!==null&&f.parseArg)S=this._callParseArg(f,S,T,R);else if(S!==null&&f.variadic)S=f._concatValue(S,T);if(S==null)if(f.negate)S=!1;else if(f.isBoolean()||f.optional)S=!0;else S="";this.setOptionValueWithSource(E,S,w)};if(this.on("option:"+r,(S)=>{let R=`error: option '${f.flags}' argument '${S}' is invalid.`;t(S,R,"cli")}),f.envVar)this.on("optionEnv:"+r,(S)=>{let R=`error: option '${f.flags}' value '${S}' from env '${f.envVar}' is invalid.`;t(S,R,"env")});return this}_optionEx(f,r,E,t,S){if(typeof r==="object"&&r instanceof Ef)throw Error("To add an Option object use addOption() instead of option() or requiredOption()");let R=this.createOption(r,E);if(R.makeOptionMandatory(!!f.mandatory),typeof t==="function")R.default(S).argParser(t);else if(t instanceof RegExp){let w=t;t=(T,$)=>{let _=w.exec(T);return _?_[0]:$},R.default(S).argParser(t)}else R.default(t);return this.addOption(R)}option(f,r,E,t){return this._optionEx({},f,r,E,t)}requiredOption(f,r,E,t){return this._optionEx({mandatory:!0},f,r,E,t)}combineFlagAndOptionalValue(f=!0){return this._combineFlagAndOptionalValue=!!f,this}allowUnknownOption(f=!0){return this._allowUnknownOption=!!f,this}allowExcessArguments(f=!0){return this._allowExcessArguments=!!f,this}enablePositionalOptions(f=!0){return this._enablePositionalOptions=!!f,this}passThroughOptions(f=!0){return this._passThroughOptions=!!f,this._checkForBrokenPassThrough(),this}_checkForBrokenPassThrough(){if(this.parent&&this._passThroughOptions&&!this.parent._enablePositionalOptions)throw Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`)}storeOptionsAsProperties(f=!0){if(this.options.length)throw Error("call .storeOptionsAsProperties() before adding options");if(Object.keys(this._optionValues).length)throw Error("call .storeOptionsAsProperties() before setting option values");return this._storeOptionsAsProperties=!!f,this}getOptionValue(f){if(this._storeOptionsAsProperties)return this[f];return this._optionValues[f]}setOptionValue(f,r){return this.setOptionValueWithSource(f,r,void 0)}setOptionValueWithSource(f,r,E){if(this._storeOptionsAsProperties)this[f]=r;else this._optionValues[f]=r;return this._optionValueSources[f]=E,this}getOptionValueSource(f){return this._optionValueSources[f]}getOptionValueSourceWithGlobals(f){let r;return this._getCommandAndAncestors().forEach((E)=>{if(E.getOptionValueSource(f)!==void 0)r=E.getOptionValueSource(f)}),r}_prepareUserArgs(f,r){if(f!==void 0&&!Array.isArray(f))throw Error("first parameter to parse must be array or undefined");if(r=r||{},f===void 0&&r.from===void 0){if(L.versions?.electron)r.from="electron";let t=L.execArgv??[];if(t.includes("-e")||t.includes("--eval")||t.includes("-p")||t.includes("--print"))r.from="eval"}if(f===void 0)f=L.argv;this.rawArgs=f.slice();let E;switch(r.from){case void 0:case"node":this._scriptPath=f[1],E=f.slice(2);break;case"electron":if(L.defaultApp)this._scriptPath=f[1],E=f.slice(2);else E=f.slice(1);break;case"user":E=f.slice(0);break;case"eval":E=f.slice(1);break;default:throw Error(`unexpected parse option { from: '${r.from}' }`)}if(!this._name&&this._scriptPath)this.nameFromFilename(this._scriptPath);return this._name=this._name||"program",E}parse(f,r){let E=this._prepareUserArgs(f,r);return this._parseCommand([],E),this}async parseAsync(f,r){let E=this._prepareUserArgs(f,r);return await this._parseCommand([],E),this}_executeSubCommand(f,r){r=r.slice();let E=!1,t=[".js",".ts",".tsx",".mjs",".cjs"];function S(_,y){let U=q.resolve(_,y);if(C.existsSync(U))return U;if(t.includes(q.extname(y)))return;let P=t.find((I)=>C.existsSync(`${U}${I}`));if(P)return`${U}${P}`;return}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let R=f._executableFile||`${this._name}-${f._name}`,w=this._executableDir||"";if(this._scriptPath){let _;try{_=C.realpathSync(this._scriptPath)}catch(y){_=this._scriptPath}w=q.resolve(q.dirname(_),w)}if(w){let _=S(w,R);if(!_&&!f._executableFile&&this._scriptPath){let y=q.basename(this._scriptPath,q.extname(this._scriptPath));if(y!==this._name)_=S(w,`${y}-${f._name}`)}R=_||R}E=t.includes(q.extname(R));let T;if(L.platform!=="win32")if(E)r.unshift(R),r=Sf(L.execArgv).concat(r),T=h.spawn(L.argv[0],r,{stdio:"inherit"});else T=h.spawn(R,r,{stdio:"inherit"});else r.unshift(R),r=Sf(L.execArgv).concat(r),T=h.spawn(L.execPath,r,{stdio:"inherit"});if(!T.killed)["SIGUSR1","SIGUSR2","SIGTERM","SIGINT","SIGHUP"].forEach((y)=>{L.on(y,()=>{if(T.killed===!1&&T.exitCode===null)T.kill(y)})});let $=this._exitCallback;T.on("close",(_)=>{if(_=_??1,!$)L.exit(_);else $(new O(_,"commander.executeSubCommandAsync","(close)"))}),T.on("error",(_)=>{if(_.code==="ENOENT"){let y=w?`searched for local subcommand relative to directory '${w}'`:"no directory for search for local subcommand, use .executableDir() to supply a custom directory",U=`'${R}' does not exist
15
15
  - if '${f._name}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
16
16
  - if the default executable name is not suitable, use the executableFile option to supply a custom name or path
17
- - ${r}`;throw Error(J)}else if(L.code==="EACCES")throw Error(`'${$}' not executable`);if(!y)I.exit(1);else{let r=new O(1,"commander.executeSubCommandAsync","(error)");r.nestedError=L,y(r)}}),this.runningCommand=_}_dispatchSubcommand(f,E,R){let S=this._findCommand(f);if(!S)this.help({error:!0});let w;return w=this._chainOrCallSubCommandHook(w,S,"preSubcommand"),w=this._chainOrCall(w,()=>{if(S._executableHandler)this._executeSubCommand(S,E.concat(R));else return S._parseCommand(E,R)}),w}_dispatchHelpCommand(f){if(!f)this.help();let E=this._findCommand(f);if(E&&!E._executableHandler)E.help();return this._dispatchSubcommand(f,[],[this._getHelpOption()?.long??this._getHelpOption()?.short??"--help"])}_checkNumberOfArguments(){if(this.registeredArguments.forEach((f,E)=>{if(f.required&&this.args[E]==null)this.missingArgument(f.name())}),this.registeredArguments.length>0&&this.registeredArguments[this.registeredArguments.length-1].variadic)return;if(this.args.length>this.registeredArguments.length)this._excessArguments(this.args)}_processArguments(){let f=(R,S,w)=>{let $=S;if(S!==null&&R.parseArg){let T=`error: command-argument value '${S}' is invalid for argument '${R.name()}'.`;$=this._callParseArg(R,S,w,T)}return $};this._checkNumberOfArguments();let E=[];this.registeredArguments.forEach((R,S)=>{let w=R.defaultValue;if(R.variadic){if(S<this.args.length){if(w=this.args.slice(S),R.parseArg)w=w.reduce(($,T)=>{return f(R,T,$)},R.defaultValue)}else if(w===void 0)w=[]}else if(S<this.args.length){if(w=this.args[S],R.parseArg)w=f(R,w,R.defaultValue)}E[S]=w}),this.processedArgs=E}_chainOrCall(f,E){if(f&&f.then&&typeof f.then==="function")return f.then(()=>E());return E()}_chainOrCallHooks(f,E){let R=f,S=[];if(this._getCommandAndAncestors().reverse().filter((w)=>w._lifeCycleHooks[E]!==void 0).forEach((w)=>{w._lifeCycleHooks[E].forEach(($)=>{S.push({hookedCommand:w,callback:$})})}),E==="postAction")S.reverse();return S.forEach((w)=>{R=this._chainOrCall(R,()=>{return w.callback(w.hookedCommand,this)})}),R}_chainOrCallSubCommandHook(f,E,R){let S=f;if(this._lifeCycleHooks[R]!==void 0)this._lifeCycleHooks[R].forEach((w)=>{S=this._chainOrCall(S,()=>{return w(this,E)})});return S}_parseCommand(f,E){let R=this.parseOptions(E);if(this._parseOptionsEnv(),this._parseOptionsImplied(),f=f.concat(R.operands),E=R.unknown,this.args=f.concat(E),f&&this._findCommand(f[0]))return this._dispatchSubcommand(f[0],f.slice(1),E);if(this._getHelpCommand()&&f[0]===this._getHelpCommand().name())return this._dispatchHelpCommand(f[1]);if(this._defaultCommandName)return this._outputHelpIfRequested(E),this._dispatchSubcommand(this._defaultCommandName,f,E);if(this.commands.length&&this.args.length===0&&!this._actionHandler&&!this._defaultCommandName)this.help({error:!0});this._outputHelpIfRequested(R.unknown),this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let S=()=>{if(R.unknown.length>0)this.unknownOption(R.unknown[0])},w=`command:${this.name()}`;if(this._actionHandler){S(),this._processArguments();let $;if($=this._chainOrCallHooks($,"preAction"),$=this._chainOrCall($,()=>this._actionHandler(this.processedArgs)),this.parent)$=this._chainOrCall($,()=>{this.parent.emit(w,f,E)});return $=this._chainOrCallHooks($,"postAction"),$}if(this.parent&&this.parent.listenerCount(w))S(),this._processArguments(),this.parent.emit(w,f,E);else if(f.length){if(this._findCommand("*"))return this._dispatchSubcommand("*",f,E);if(this.listenerCount("command:*"))this.emit("command:*",f,E);else if(this.commands.length)this.unknownCommand();else S(),this._processArguments()}else if(this.commands.length)S(),this.help({error:!0});else S(),this._processArguments()}_findCommand(f){if(!f)return;return this.commands.find((E)=>E._name===f||E._aliases.includes(f))}_findOption(f){return this.options.find((E)=>E.is(f))}_checkForMissingMandatoryOptions(){this._getCommandAndAncestors().forEach((f)=>{f.options.forEach((E)=>{if(E.mandatory&&f.getOptionValue(E.attributeName())===void 0)f.missingMandatoryOptionValue(E)})})}_checkForConflictingLocalOptions(){let f=this.options.filter((R)=>{let S=R.attributeName();if(this.getOptionValue(S)===void 0)return!1;return this.getOptionValueSource(S)!=="default"});f.filter((R)=>R.conflictsWith.length>0).forEach((R)=>{let S=f.find((w)=>R.conflictsWith.includes(w.attributeName()));if(S)this._conflictingOption(R,S)})}_checkForConflictingOptions(){this._getCommandAndAncestors().forEach((f)=>{f._checkForConflictingLocalOptions()})}parseOptions(f){let E=[],R=[],S=E,w=f.slice();function $(_){return _.length>1&&_[0]==="-"}let T=null;while(w.length){let _=w.shift();if(_==="--"){if(S===R)S.push(_);S.push(...w);break}if(T&&!$(_)){this.emit(`option:${T.name()}`,_);continue}if(T=null,$(_)){let y=this._findOption(_);if(y){if(y.required){let L=w.shift();if(L===void 0)this.optionMissingArgument(y);this.emit(`option:${y.name()}`,L)}else if(y.optional){let L=null;if(w.length>0&&!$(w[0]))L=w.shift();this.emit(`option:${y.name()}`,L)}else this.emit(`option:${y.name()}`);T=y.variadic?y:null;continue}}if(_.length>2&&_[0]==="-"&&_[1]!=="-"){let y=this._findOption(`-${_[1]}`);if(y){if(y.required||y.optional&&this._combineFlagAndOptionalValue)this.emit(`option:${y.name()}`,_.slice(2));else this.emit(`option:${y.name()}`),w.unshift(`-${_.slice(2)}`);continue}}if(/^--[^=]+=/.test(_)){let y=_.indexOf("="),L=this._findOption(_.slice(0,y));if(L&&(L.required||L.optional)){this.emit(`option:${L.name()}`,_.slice(y+1));continue}}if($(_))S=R;if((this._enablePositionalOptions||this._passThroughOptions)&&E.length===0&&R.length===0){if(this._findCommand(_)){if(E.push(_),w.length>0)R.push(...w);break}else if(this._getHelpCommand()&&_===this._getHelpCommand().name()){if(E.push(_),w.length>0)E.push(...w);break}else if(this._defaultCommandName){if(R.push(_),w.length>0)R.push(...w);break}}if(this._passThroughOptions){if(S.push(_),w.length>0)S.push(...w);break}S.push(_)}return{operands:E,unknown:R}}opts(){if(this._storeOptionsAsProperties){let f={},E=this.options.length;for(let R=0;R<E;R++){let S=this.options[R].attributeName();f[S]=S===this._versionOptionName?this._version:this[S]}return f}return this._optionValues}optsWithGlobals(){return this._getCommandAndAncestors().reduce((f,E)=>Object.assign(f,E.opts()),{})}error(f,E){if(this._outputConfiguration.outputError(`${f}
17
+ - ${y}`;throw Error(U)}else if(_.code==="EACCES")throw Error(`'${R}' not executable`);if(!$)L.exit(1);else{let y=new O(1,"commander.executeSubCommandAsync","(error)");y.nestedError=_,$(y)}}),this.runningCommand=T}_dispatchSubcommand(f,r,E){let t=this._findCommand(f);if(!t)this.help({error:!0});let S;return S=this._chainOrCallSubCommandHook(S,t,"preSubcommand"),S=this._chainOrCall(S,()=>{if(t._executableHandler)this._executeSubCommand(t,r.concat(E));else return t._parseCommand(r,E)}),S}_dispatchHelpCommand(f){if(!f)this.help();let r=this._findCommand(f);if(r&&!r._executableHandler)r.help();return this._dispatchSubcommand(f,[],[this._getHelpOption()?.long??this._getHelpOption()?.short??"--help"])}_checkNumberOfArguments(){if(this.registeredArguments.forEach((f,r)=>{if(f.required&&this.args[r]==null)this.missingArgument(f.name())}),this.registeredArguments.length>0&&this.registeredArguments[this.registeredArguments.length-1].variadic)return;if(this.args.length>this.registeredArguments.length)this._excessArguments(this.args)}_processArguments(){let f=(E,t,S)=>{let R=t;if(t!==null&&E.parseArg){let w=`error: command-argument value '${t}' is invalid for argument '${E.name()}'.`;R=this._callParseArg(E,t,S,w)}return R};this._checkNumberOfArguments();let r=[];this.registeredArguments.forEach((E,t)=>{let S=E.defaultValue;if(E.variadic){if(t<this.args.length){if(S=this.args.slice(t),E.parseArg)S=S.reduce((R,w)=>{return f(E,w,R)},E.defaultValue)}else if(S===void 0)S=[]}else if(t<this.args.length){if(S=this.args[t],E.parseArg)S=f(E,S,E.defaultValue)}r[t]=S}),this.processedArgs=r}_chainOrCall(f,r){if(f&&f.then&&typeof f.then==="function")return f.then(()=>r());return r()}_chainOrCallHooks(f,r){let E=f,t=[];if(this._getCommandAndAncestors().reverse().filter((S)=>S._lifeCycleHooks[r]!==void 0).forEach((S)=>{S._lifeCycleHooks[r].forEach((R)=>{t.push({hookedCommand:S,callback:R})})}),r==="postAction")t.reverse();return t.forEach((S)=>{E=this._chainOrCall(E,()=>{return S.callback(S.hookedCommand,this)})}),E}_chainOrCallSubCommandHook(f,r,E){let t=f;if(this._lifeCycleHooks[E]!==void 0)this._lifeCycleHooks[E].forEach((S)=>{t=this._chainOrCall(t,()=>{return S(this,r)})});return t}_parseCommand(f,r){let E=this.parseOptions(r);if(this._parseOptionsEnv(),this._parseOptionsImplied(),f=f.concat(E.operands),r=E.unknown,this.args=f.concat(r),f&&this._findCommand(f[0]))return this._dispatchSubcommand(f[0],f.slice(1),r);if(this._getHelpCommand()&&f[0]===this._getHelpCommand().name())return this._dispatchHelpCommand(f[1]);if(this._defaultCommandName)return this._outputHelpIfRequested(r),this._dispatchSubcommand(this._defaultCommandName,f,r);if(this.commands.length&&this.args.length===0&&!this._actionHandler&&!this._defaultCommandName)this.help({error:!0});this._outputHelpIfRequested(E.unknown),this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let t=()=>{if(E.unknown.length>0)this.unknownOption(E.unknown[0])},S=`command:${this.name()}`;if(this._actionHandler){t(),this._processArguments();let R;if(R=this._chainOrCallHooks(R,"preAction"),R=this._chainOrCall(R,()=>this._actionHandler(this.processedArgs)),this.parent)R=this._chainOrCall(R,()=>{this.parent.emit(S,f,r)});return R=this._chainOrCallHooks(R,"postAction"),R}if(this.parent&&this.parent.listenerCount(S))t(),this._processArguments(),this.parent.emit(S,f,r);else if(f.length){if(this._findCommand("*"))return this._dispatchSubcommand("*",f,r);if(this.listenerCount("command:*"))this.emit("command:*",f,r);else if(this.commands.length)this.unknownCommand();else t(),this._processArguments()}else if(this.commands.length)t(),this.help({error:!0});else t(),this._processArguments()}_findCommand(f){if(!f)return;return this.commands.find((r)=>r._name===f||r._aliases.includes(f))}_findOption(f){return this.options.find((r)=>r.is(f))}_checkForMissingMandatoryOptions(){this._getCommandAndAncestors().forEach((f)=>{f.options.forEach((r)=>{if(r.mandatory&&f.getOptionValue(r.attributeName())===void 0)f.missingMandatoryOptionValue(r)})})}_checkForConflictingLocalOptions(){let f=this.options.filter((E)=>{let t=E.attributeName();if(this.getOptionValue(t)===void 0)return!1;return this.getOptionValueSource(t)!=="default"});f.filter((E)=>E.conflictsWith.length>0).forEach((E)=>{let t=f.find((S)=>E.conflictsWith.includes(S.attributeName()));if(t)this._conflictingOption(E,t)})}_checkForConflictingOptions(){this._getCommandAndAncestors().forEach((f)=>{f._checkForConflictingLocalOptions()})}parseOptions(f){let r=[],E=[],t=r,S=f.slice();function R(T){return T.length>1&&T[0]==="-"}let w=null;while(S.length){let T=S.shift();if(T==="--"){if(t===E)t.push(T);t.push(...S);break}if(w&&!R(T)){this.emit(`option:${w.name()}`,T);continue}if(w=null,R(T)){let $=this._findOption(T);if($){if($.required){let _=S.shift();if(_===void 0)this.optionMissingArgument($);this.emit(`option:${$.name()}`,_)}else if($.optional){let _=null;if(S.length>0&&!R(S[0]))_=S.shift();this.emit(`option:${$.name()}`,_)}else this.emit(`option:${$.name()}`);w=$.variadic?$:null;continue}}if(T.length>2&&T[0]==="-"&&T[1]!=="-"){let $=this._findOption(`-${T[1]}`);if($){if($.required||$.optional&&this._combineFlagAndOptionalValue)this.emit(`option:${$.name()}`,T.slice(2));else this.emit(`option:${$.name()}`),S.unshift(`-${T.slice(2)}`);continue}}if(/^--[^=]+=/.test(T)){let $=T.indexOf("="),_=this._findOption(T.slice(0,$));if(_&&(_.required||_.optional)){this.emit(`option:${_.name()}`,T.slice($+1));continue}}if(R(T))t=E;if((this._enablePositionalOptions||this._passThroughOptions)&&r.length===0&&E.length===0){if(this._findCommand(T)){if(r.push(T),S.length>0)E.push(...S);break}else if(this._getHelpCommand()&&T===this._getHelpCommand().name()){if(r.push(T),S.length>0)r.push(...S);break}else if(this._defaultCommandName){if(E.push(T),S.length>0)E.push(...S);break}}if(this._passThroughOptions){if(t.push(T),S.length>0)t.push(...S);break}t.push(T)}return{operands:r,unknown:E}}opts(){if(this._storeOptionsAsProperties){let f={},r=this.options.length;for(let E=0;E<r;E++){let t=this.options[E].attributeName();f[t]=t===this._versionOptionName?this._version:this[t]}return f}return this._optionValues}optsWithGlobals(){return this._getCommandAndAncestors().reduce((f,r)=>Object.assign(f,r.opts()),{})}error(f,r){if(this._outputConfiguration.outputError(`${f}
18
18
  `,this._outputConfiguration.writeErr),typeof this._showHelpAfterError==="string")this._outputConfiguration.writeErr(`${this._showHelpAfterError}
19
19
  `);else if(this._showHelpAfterError)this._outputConfiguration.writeErr(`
20
- `),this.outputHelp({error:!0});let R=E||{},S=R.exitCode||1,w=R.code||"commander.error";this._exit(S,w,f)}_parseOptionsEnv(){this.options.forEach((f)=>{if(f.envVar&&f.envVar in I.env){let E=f.attributeName();if(this.getOptionValue(E)===void 0||["default","config","env"].includes(this.getOptionValueSource(E)))if(f.required||f.optional)this.emit(`optionEnv:${f.name()}`,I.env[f.envVar]);else this.emit(`optionEnv:${f.name()}`)}})}_parseOptionsImplied(){let f=new IE(this.options),E=(R)=>{return this.getOptionValue(R)!==void 0&&!["default","implied"].includes(this.getOptionValueSource(R))};this.options.filter((R)=>R.implied!==void 0&&E(R.attributeName())&&f.valueFromOption(this.getOptionValue(R.attributeName()),R)).forEach((R)=>{Object.keys(R.implied).filter((S)=>!E(S)).forEach((S)=>{this.setOptionValueWithSource(S,R.implied[S],"implied")})})}missingArgument(f){let E=`error: missing required argument '${f}'`;this.error(E,{code:"commander.missingArgument"})}optionMissingArgument(f){let E=`error: option '${f.flags}' argument missing`;this.error(E,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue(f){let E=`error: required option '${f.flags}' not specified`;this.error(E,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption(f,E){let R=($)=>{let T=$.attributeName(),_=this.getOptionValue(T),y=this.options.find((r)=>r.negate&&T===r.attributeName()),L=this.options.find((r)=>!r.negate&&T===r.attributeName());if(y&&(y.presetArg===void 0&&_===!1||y.presetArg!==void 0&&_===y.presetArg))return y;return L||$},S=($)=>{let T=R($),_=T.attributeName();if(this.getOptionValueSource(_)==="env")return`environment variable '${T.envVar}'`;return`option '${T.flags}'`},w=`error: ${S(f)} cannot be used with ${S(E)}`;this.error(w,{code:"commander.conflictingOption"})}unknownOption(f){if(this._allowUnknownOption)return;let E="";if(f.startsWith("--")&&this._showSuggestionAfterError){let S=[],w=this;do{let $=w.createHelp().visibleOptions(w).filter((T)=>T.long).map((T)=>T.long);S=S.concat($),w=w.parent}while(w&&!w._enablePositionalOptions);E=Sf(f,S)}let R=`error: unknown option '${f}'${E}`;this.error(R,{code:"commander.unknownOption"})}_excessArguments(f){if(this._allowExcessArguments)return;let E=this.registeredArguments.length,R=E===1?"":"s",w=`error: too many arguments${this.parent?` for '${this.name()}'`:""}. Expected ${E} argument${R} but got ${f.length}.`;this.error(w,{code:"commander.excessArguments"})}unknownCommand(){let f=this.args[0],E="";if(this._showSuggestionAfterError){let S=[];this.createHelp().visibleCommands(this).forEach((w)=>{if(S.push(w.name()),w.alias())S.push(w.alias())}),E=Sf(f,S)}let R=`error: unknown command '${f}'${E}`;this.error(R,{code:"commander.unknownCommand"})}version(f,E,R){if(f===void 0)return this._version;this._version=f,E=E||"-V, --version",R=R||"output the version number";let S=this.createOption(E,R);return this._versionOptionName=S.attributeName(),this._registerOption(S),this.on("option:"+S.name(),()=>{this._outputConfiguration.writeOut(`${f}
21
- `),this._exit(0,"commander.version",f)}),this}description(f,E){if(f===void 0&&E===void 0)return this._description;if(this._description=f,E)this._argsDescription=E;return this}summary(f){if(f===void 0)return this._summary;return this._summary=f,this}alias(f){if(f===void 0)return this._aliases[0];let E=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler)E=this.commands[this.commands.length-1];if(f===E._name)throw Error("Command alias can't be the same as its name");let R=this.parent?._findCommand(f);if(R){let S=[R.name()].concat(R.aliases()).join("|");throw Error(`cannot add alias '${f}' to command '${this.name()}' as already have command '${S}'`)}return E._aliases.push(f),this}aliases(f){if(f===void 0)return this._aliases;return f.forEach((E)=>this.alias(E)),this}usage(f){if(f===void 0){if(this._usage)return this._usage;let E=this.registeredArguments.map((R)=>{return LE(R)});return[].concat(this.options.length||this._helpOption!==null?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?E:[]).join(" ")}return this._usage=f,this}name(f){if(f===void 0)return this._name;return this._name=f,this}nameFromFilename(f){return this._name=q.basename(f,q.extname(f)),this}executableDir(f){if(f===void 0)return this._executableDir;return this._executableDir=f,this}helpInformation(f){let E=this.createHelp();if(E.helpWidth===void 0)E.helpWidth=f&&f.error?this._outputConfiguration.getErrHelpWidth():this._outputConfiguration.getOutHelpWidth();return E.formatHelp(this,E)}_getHelpContext(f){f=f||{};let E={error:!!f.error},R;if(E.error)R=(S)=>this._outputConfiguration.writeErr(S);else R=(S)=>this._outputConfiguration.writeOut(S);return E.write=f.write||R,E.command=this,E}outputHelp(f){let E;if(typeof f==="function")E=f,f=void 0;let R=this._getHelpContext(f);this._getCommandAndAncestors().reverse().forEach((w)=>w.emit("beforeAllHelp",R)),this.emit("beforeHelp",R);let S=this.helpInformation(R);if(E){if(S=E(S),typeof S!=="string"&&!Buffer.isBuffer(S))throw Error("outputHelp callback must return a string or a Buffer")}if(R.write(S),this._getHelpOption()?.long)this.emit(this._getHelpOption().long);this.emit("afterHelp",R),this._getCommandAndAncestors().forEach((w)=>w.emit("afterAllHelp",R))}helpOption(f,E){if(typeof f==="boolean"){if(f)this._helpOption=this._helpOption??void 0;else this._helpOption=null;return this}return f=f??"-h, --help",E=E??"display help for command",this._helpOption=this.createOption(f,E),this}_getHelpOption(){if(this._helpOption===void 0)this.helpOption(void 0,void 0);return this._helpOption}addHelpOption(f){return this._helpOption=f,this}help(f){this.outputHelp(f);let E=I.exitCode||0;if(E===0&&f&&typeof f!=="function"&&f.error)E=1;this._exit(E,"commander.help","(outputHelp)")}addHelpText(f,E){let R=["beforeAll","before","after","afterAll"];if(!R.includes(f))throw Error(`Unexpected value for position to addHelpText.
22
- Expecting one of '${R.join("', '")}'`);let S=`${f}Help`;return this.on(S,(w)=>{let $;if(typeof E==="function")$=E({error:w.error,command:w.command});else $=E;if($)w.write(`${$}
23
- `)}),this}_outputHelpIfRequested(f){let E=this._getHelpOption();if(E&&f.find((S)=>E.is(S)))this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)")}}function wf(f){return f.map((E)=>{if(!E.startsWith("--inspect"))return E;let R,S="127.0.0.1",w="9229",$;if(($=E.match(/^(--inspect(-brk)?)$/))!==null)R=$[1];else if(($=E.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null)if(R=$[1],/^\d+$/.test($[3]))w=$[3];else S=$[3];else if(($=E.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null)R=$[1],S=$[3],w=$[4];if(R&&w!=="0")return`${R}=${S}:${parseInt(w)+1}`;return E})}UE.Command=v});var Lf=M((qE)=>{var{Argument:Tf}=K(),{Command:c}=$f(),{CommanderError:tE,InvalidArgumentError:_f}=Q(),{Help:PE}=b(),{Option:yf}=s();qE.program=new c;qE.createCommand=(f)=>new c(f);qE.createOption=(f,E)=>new yf(f,E);qE.createArgument=(f,E)=>new Tf(f,E);qE.Command=c;qE.Option=yf;qE.Argument=Tf;qE.Help=PE;qE.CommanderError=tE;qE.InvalidArgumentError=_f;qE.InvalidOptionArgumentError=_f});var rf=bf(Lf(),1),{program:uR,createCommand:AR,createArgument:VR,createOption:xR,CommanderError:bR,InvalidArgumentError:sR,InvalidOptionArgumentError:CR,Command:t,Argument:hR,Option:OR,Help:vR}=rf.default;import{readFile as pE}from"node:fs/promises";import{resolve as aE}from"node:path";var If={name:"@shotstack/cli",version:"0.2.0",description:"Command-line interface for the Shotstack video rendering API.",license:"Apache-2.0",homepage:"https://github.com/shotstack/shotstack-cli",repository:{type:"git",url:"git+https://github.com/shotstack/shotstack-cli.git"},bugs:{url:"https://github.com/shotstack/shotstack-cli/issues"},type:"module",bin:{shotstack:"dist/shotstack.js"},files:["dist/shotstack.js","SKILL.md","references"],scripts:{start:"bun run src/index.ts",build:"bun build src/index.ts --target=node --minify --outfile=dist/shotstack.js --banner='#!/usr/bin/env node' && chmod +x dist/shotstack.js",prepack:"bun run build",typecheck:"tsc --noEmit",test:"bun test"},dependencies:{commander:"^12.1.0"},devDependencies:{"@types/bun":"latest",typescript:"^5.6.0"}};var H=If.version,Uf=`shotstack-cli/${H} (${process.platform}-${process.arch})`;class G extends Error{status;body;constructor(f,E,R){super(R);this.status=f;this.body=E;this.name="ApiError"}get isTransient(){return this.status>=500||this.status===429}}function W(f){let E=f.env.baseUrl.replace(/\/$/,"");async function R(S,w,$){let T=await fetch(`${E}${w}`,{method:S,headers:{"x-api-key":f.apiKey,"x-shotstack-origin":"cli","x-shotstack-environment":f.env.name,"user-agent":Uf,...$!==void 0?{"content-type":"application/json"}:{}},body:$!==void 0?JSON.stringify($):void 0}),_=await T.text(),y=_?WE(_):void 0;if(!T.ok)throw new G(T.status,y??_,`${S} ${w} → ${T.status} ${T.statusText}`);return y}return{post:(S,w)=>R("POST",S,w),get:(S)=>R("GET",S)}}function WE(f){try{return JSON.parse(f)}catch{return f}}class j extends Error{constructor(){super("SHOTSTACK_API_KEY is not set. Get a key at https://shotstack.io.");this.name="MissingApiKeyError"}}function D(){let f=process.env.SHOTSTACK_API_KEY?.trim();if(!f)throw new j;return f}var Jf={dev:"https://api.shotstack.io/edit/dev",stage:"https://api.shotstack.io/edit/stage",v1:"https://api.shotstack.io/edit/v1"},X=Object.keys(Jf);class z extends Error{constructor(f){super(`Invalid environment "${f}". Use one of: ${X.join(", ")}.`);this.name="InvalidEnvError"}}function F(f){let E=process.env.SHOTSTACK_API_BASE_URL?.trim();if(E)return{name:"custom",baseUrl:E};let R=f??process.env.SHOTSTACK_ENV?.trim()??"v1";if(!DE(R))throw new z(R);return{name:R,baseUrl:Jf[R]}}function DE(f){return X.includes(f)}function B(f){if(f==="json")return"json";return"text"}function Z(f,E,R){if(f==="json")console.log(JSON.stringify(E));else console.log(R)}import{mkdir as FE,appendFile as kE,stat as Yf,readFile as uE,writeFile as Mf}from"node:fs/promises";import{join as n,dirname as AE}from"node:path";import{homedir as tf}from"node:os";var VE=1e6,xE=500000,Pf=2000;function k(){if(process.platform==="win32"){let f=process.env.APPDATA??n(tf(),"AppData","Roaming");return n(f,"shotstack","log.jsonl")}return n(tf(),".shotstack","log.jsonl")}function bE(f,E=new Date){let R={ts:E.toISOString(),cmd:f.cmd,args:f.args.map(nE),exit:f.exit,durationMs:f.durationMs};if(f.renderId)R.renderId=f.renderId;if(f.response!==void 0)R.response=gE(i(f.response));if(f.error)R.error=sE(f.error);return R}function sE(f){return{name:f.name,message:typeof f.message==="string"?g(f.message):String(f.message)}}function CE(f){if(f instanceof Error)return{name:f.name,message:f.message};if(f===void 0||f===null)return;return{name:"Unknown",message:String(f)}}async function qf(f,E=k()){let R=bE(f),S=JSON.stringify(R)+`
24
- `;if(await FE(AE(E),{recursive:!0,mode:448}),!await hE(E))await Mf(E,"",{mode:384});await kE(E,S),await OE(E)}async function hE(f){try{return await Yf(f),!0}catch{return!1}}async function OE(f){let E=await Yf(f).catch(()=>null);if(!E||E.size<=VE)return;let R=await uE(f),S=R.subarray(Math.max(0,R.length-xE)),w=S.indexOf(10),$=w>=0?S.subarray(w+1):S;await Mf(f,$,{mode:384})}var vE=/^https?:\/\//i,cE=/(https?:\/\/[^\s'"<>]+?)\?[^\s'"<>]*?(?:Signature|X-Amz-[A-Za-z0-9-]*)=[^\s'"<>]*/gi;function g(f){return f.replace(cE,"$1?[redacted-signed]")}function nE(f){if(typeof f!=="string")return f;if(f.startsWith("-"))return f;if(vE.test(f))return g(f);if(/[\/\\]/.test(f))return iE(f);return f}function iE(f){let E=f.split(/[\/\\]/);return E[E.length-1]||f}function i(f){if(typeof f==="string")return g(f);if(Array.isArray(f))return f.map(i);if(f&&typeof f==="object"){let E={};for(let[R,S]of Object.entries(f))E[R]=i(S);return E}return f}function gE(f){let E=JSON.stringify(f);if(E===void 0||E.length<=Pf)return f;return E.slice(0,Pf)+"...[truncated]"}async function u(f,E,R){let S=Date.now();try{let w=await R(),$=w.exitCode??0;if(await qf({cmd:f,args:E,exit:$,durationMs:Date.now()-S,renderId:w.renderId,response:w.response}).catch(()=>{}),$!==0)process.exit($)}catch(w){let $=mE(w),T=w instanceof G?w.body:void 0;throw await qf({cmd:f,args:E,exit:$,durationMs:Date.now()-S,response:T,error:CE(w)}).catch(()=>{}),w}}function mE(f){if(f instanceof G)return f.isTransient?2:1;if(f instanceof j||f instanceof z)return 1;if(f instanceof Error&&f.code==="ENOENT")return 1;return 2}function A(f){let E=process.argv.slice(2),R=E.indexOf(f);return R>=0?E.slice(R+1):E}var lE=new Set(["done","failed"]),dE=3000,Gf=new t("status").description("Poll the status of a Shotstack render").argument("<id>","Render ID returned by `shotstack render`").option("--watch","Poll continuously until the render reaches a terminal state").option("--env <name>",`Environment: ${X.join(" | ")}`).option("--output <format>","Output format: text | json","text").action(async(f,E)=>{await u("status",A("status"),async()=>{let R=B(E.output),S=D(),w=F(E.env),$=W({apiKey:S,env:w}),T=await m($,f,R,E.watch===!0),_=T.status==="failed"?1:0;return{renderId:T.id,response:T,exitCode:_}})});async function m(f,E,R,S){while(!0){let $=(await f.get(`/render/${encodeURIComponent(E)}`)).response;if(Z(R,$,oE($)),!S||lE.has($.status))return $;await eE(dE)}}function oE(f){let E=[f.status];if(f.url)E.push(f.url);if(f.error)E.push(`error: ${f.error}`);return E.join(" ")}function eE(f){return new Promise((E)=>setTimeout(E,f))}var jf=new t("render").description("Submit a Shotstack Edit JSON to the render API").argument("<file>","Path to a Shotstack Edit JSON file").option("--env <name>",`Environment: ${X.join(" | ")}`).option("--watch","After submitting, poll until the render reaches a terminal state").option("--output <format>","Output format: text | json","text").action(async(f,E)=>{await u("render",A("render"),async()=>{let R=B(E.output),S=D(),w=F(E.env),$=aE(process.cwd(),f),T=await pE($,"utf8"),_=JSON.parse(T),y=W({apiKey:S,env:w}),L=await y.post("/render",_),r=L.response.id;if(!E.watch)return Z(R,{id:r},r),{renderId:r,response:L.response};let J=await m(y,r,R,!0),P=J.status==="failed"?1:0;return{renderId:r,response:J,exitCode:P}})});import{readFile as fR,writeFile as ER,mkdtemp as RR}from"node:fs/promises";import{tmpdir as SR}from"node:os";import{join as Xf}from"node:path";import{spawn as wR}from"node:child_process";var zf="https://github.com/shotstack/shotstack-cli/issues/new?template=bug.yml",$R=6000,Qf=5,Hf=new t("feedback").description("Open a pre-filled GitHub issue with a flight-recorder dossier from your last 5 invocations").action(async()=>{let f=await TR(Qf),E=_R(f),R=LR(f),S=`&title=${encodeURIComponent(R)}`,w=`${zf}${S}&body=${encodeURIComponent(E)}`;if(w.length<=$R){Nf(w),console.log("Opened browser with pre-filled issue. Review before submitting.");return}let $=await RR(Xf(SR(),"shotstack-feedback-")),T=Xf($,"dossier.md");await ER(T,E),Nf(`${zf}${S}`),console.log(`Dossier too large to inline. Saved to: ${T}`),console.log("Drag the file into the issue body, or paste its contents.")});async function TR(f){let E=k(),R;try{R=await fR(E,"utf8")}catch{return[]}let w=R.split(`
25
- `).filter((T)=>T.trim().length>0).slice(-f).reverse(),$=[];for(let T of w)try{$.push(JSON.parse(T))}catch{}return $}function _R(f){let E=[];if(E.push("## Environment"),E.push(`- Shotstack CLI: ${H}`),E.push(`- OS: ${process.platform}-${process.arch}`),E.push(""),E.push(`## Last ${Qf} invocations (most recent first)`),E.push(""),f.length===0)E.push("_No recorded invocations._");else for(let R of f){let S=(R.args??[]).join(" "),w=`### ${R.ts} — shotstack ${R.cmd}${S?" "+S:""}`;if(E.push(w),E.push(`- Exit: ${R.exit} Duration: ${R.durationMs}ms`),R.renderId)E.push(`- Render ID: ${R.renderId}`);if(R.response!==void 0){let $=typeof R.response==="string"?R.response:JSON.stringify(R.response);E.push(`- Response: ${$}`)}if(R.error)E.push(`- Error: ${R.error.name}: ${R.error.message}`);E.push("")}return E.push(`[full log at ${k()}]`),E.push(""),E.push("## What I expected vs what happened"),E.push("<!-- Describe the issue, request, or question here. -->"),E.join(`
26
- `)}var Bf=80,yR="Feedback from shotstack CLI";function LR(f){let E=f.find((w)=>w.error);if(E&&E.error)return l(`${E.cmd}: ${E.error.name} — ${E.error.message}`);let R=f.find((w)=>Zf(w.response)!==null);if(R){let w=Zf(R.response);return l(`Render failed: ${w}`)}let S=f.find((w)=>w.exit!==0);if(S)return l(`${S.cmd} exited ${S.exit}`);return yR}function Zf(f){if(!f||typeof f!=="object"||Array.isArray(f))return null;let E=f;if(E.state!=="failed")return null;return typeof E.error==="string"&&E.error.length>0?E.error:"unknown error"}function l(f){return f.length<=Bf?f:f.slice(0,Bf-1)+"…"}function Nf(f){let E=process.platform==="win32",R=process.platform==="darwin"?"open":E?"cmd":"xdg-open",w=wR(R,E?["/c","start","",f]:[f],{stdio:"ignore",detached:!0});w.on("error",()=>{console.error(`Could not open browser. Visit: ${f}`)}),w.unref()}import{readFile as rR}from"node:fs/promises";import{resolve as IR}from"node:path";import{spawn as Kf,execSync as UR}from"node:child_process";var JR="https://shotstack.studio",tR=6000,Wf=new t("preview").description("Open a shotstack.studio URL that loads the Edit JSON in the browser editor").argument("<file>","Path to a Shotstack Edit JSON file").option("--copy","Copy the URL to the clipboard").option("--no-open","Do not try to open the URL in a browser").option("--output <format>","Output format: text | json","text").action(async(f,E)=>{let R=B(E.output),S=IR(process.cwd(),f),w=await rR(S,"utf8"),$=JSON.parse(w);qR($);let T=PR($);if(T.length>tR)console.error(`warning: encoded URL is ${T.length} characters; large templates may exceed browser URL limits.`);if(E.copy)await YR(T);let _=E.open&&XR()&&GR(T);if(R==="json"||!_)Z(R,{url:T},T)});function PR(f){let E=Buffer.from(JSON.stringify(f),"utf8").toString("base64url");return`${JR}/#json=${E}`}function qR(f){if(!f||typeof f!=="object")throw Error("Template must be a JSON object.");if(!("timeline"in f))throw Error("Template missing required field: timeline.");if(!("output"in f))throw Error("Template missing required field: output.")}async function YR(f){let{cmd:E,args:R}=MR();await new Promise((S,w)=>{let $=Kf(E,R,{stdio:["pipe","ignore","ignore"]});$.on("error",w),$.on("exit",(T)=>T===0?S():w(Error(`${E} exited ${T}`))),$.stdin.end(f)})}function MR(){if(process.platform==="darwin")return{cmd:"pbcopy",args:[]};if(process.platform==="win32")return{cmd:"clip",args:[]};return{cmd:"xclip",args:["-selection","clipboard"]}}function GR(f){let{cmd:E,args:R}=jR(f);try{let S=Kf(E,R,{detached:!0,stdio:"ignore"});return S.on("error",()=>{}),S.unref(),!0}catch{return!1}}function jR(f){if(process.platform==="win32")return{cmd:"cmd",args:["/c","start","",f]};if(process.platform==="darwin")return{cmd:"open",args:[f]};return{cmd:"xdg-open",args:[f]}}function XR(){if(process.platform==="darwin"||process.platform==="win32")return!0;if(!process.env.DISPLAY&&!process.env.WAYLAND_DISPLAY)return!1;try{return UR("command -v xdg-open",{stdio:"ignore"}),!0}catch{return!1}}var zR=new t().name("shotstack").description("Command-line interface for the Shotstack video rendering API").version(H).addCommand(jf).addCommand(Gf).addCommand(Wf).addCommand(Hf);try{await zR.parseAsync(process.argv)}catch(f){process.exit(BR(f))}function BR(f){if(f instanceof j||f instanceof z)return console.error(f.message),1;if(f instanceof G){if(console.error(f.message),f.body)console.error(typeof f.body==="string"?f.body:JSON.stringify(f.body));return f.isTransient?2:1}if(f instanceof Error){if("code"in f&&f.code==="ENOENT")return console.error(f.message),1;return console.error(f.message),2}return console.error(String(f)),2}
20
+ `),this.outputHelp({error:!0});let E=r||{},t=E.exitCode||1,S=E.code||"commander.error";this._exit(t,S,f)}_parseOptionsEnv(){this.options.forEach((f)=>{if(f.envVar&&f.envVar in L.env){let r=f.attributeName();if(this.getOptionValue(r)===void 0||["default","config","env"].includes(this.getOptionValueSource(r)))if(f.required||f.optional)this.emit(`optionEnv:${f.name()}`,L.env[f.envVar]);else this.emit(`optionEnv:${f.name()}`)}})}_parseOptionsImplied(){let f=new Ir(this.options),r=(E)=>{return this.getOptionValue(E)!==void 0&&!["default","implied"].includes(this.getOptionValueSource(E))};this.options.filter((E)=>E.implied!==void 0&&r(E.attributeName())&&f.valueFromOption(this.getOptionValue(E.attributeName()),E)).forEach((E)=>{Object.keys(E.implied).filter((t)=>!r(t)).forEach((t)=>{this.setOptionValueWithSource(t,E.implied[t],"implied")})})}missingArgument(f){let r=`error: missing required argument '${f}'`;this.error(r,{code:"commander.missingArgument"})}optionMissingArgument(f){let r=`error: option '${f.flags}' argument missing`;this.error(r,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue(f){let r=`error: required option '${f.flags}' not specified`;this.error(r,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption(f,r){let E=(R)=>{let w=R.attributeName(),T=this.getOptionValue(w),$=this.options.find((y)=>y.negate&&w===y.attributeName()),_=this.options.find((y)=>!y.negate&&w===y.attributeName());if($&&($.presetArg===void 0&&T===!1||$.presetArg!==void 0&&T===$.presetArg))return $;return _||R},t=(R)=>{let w=E(R),T=w.attributeName();if(this.getOptionValueSource(T)==="env")return`environment variable '${w.envVar}'`;return`option '${w.flags}'`},S=`error: ${t(f)} cannot be used with ${t(r)}`;this.error(S,{code:"commander.conflictingOption"})}unknownOption(f){if(this._allowUnknownOption)return;let r="";if(f.startsWith("--")&&this._showSuggestionAfterError){let t=[],S=this;do{let R=S.createHelp().visibleOptions(S).filter((w)=>w.long).map((w)=>w.long);t=t.concat(R),S=S.parent}while(S&&!S._enablePositionalOptions);r=tf(f,t)}let E=`error: unknown option '${f}'${r}`;this.error(E,{code:"commander.unknownOption"})}_excessArguments(f){if(this._allowExcessArguments)return;let r=this.registeredArguments.length,E=r===1?"":"s",S=`error: too many arguments${this.parent?` for '${this.name()}'`:""}. Expected ${r} argument${E} but got ${f.length}.`;this.error(S,{code:"commander.excessArguments"})}unknownCommand(){let f=this.args[0],r="";if(this._showSuggestionAfterError){let t=[];this.createHelp().visibleCommands(this).forEach((S)=>{if(t.push(S.name()),S.alias())t.push(S.alias())}),r=tf(f,t)}let E=`error: unknown command '${f}'${r}`;this.error(E,{code:"commander.unknownCommand"})}version(f,r,E){if(f===void 0)return this._version;this._version=f,r=r||"-V, --version",E=E||"output the version number";let t=this.createOption(r,E);return this._versionOptionName=t.attributeName(),this._registerOption(t),this.on("option:"+t.name(),()=>{this._outputConfiguration.writeOut(`${f}
21
+ `),this._exit(0,"commander.version",f)}),this}description(f,r){if(f===void 0&&r===void 0)return this._description;if(this._description=f,r)this._argsDescription=r;return this}summary(f){if(f===void 0)return this._summary;return this._summary=f,this}alias(f){if(f===void 0)return this._aliases[0];let r=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler)r=this.commands[this.commands.length-1];if(f===r._name)throw Error("Command alias can't be the same as its name");let E=this.parent?._findCommand(f);if(E){let t=[E.name()].concat(E.aliases()).join("|");throw Error(`cannot add alias '${f}' to command '${this.name()}' as already have command '${t}'`)}return r._aliases.push(f),this}aliases(f){if(f===void 0)return this._aliases;return f.forEach((r)=>this.alias(r)),this}usage(f){if(f===void 0){if(this._usage)return this._usage;let r=this.registeredArguments.map((E)=>{return yr(E)});return[].concat(this.options.length||this._helpOption!==null?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?r:[]).join(" ")}return this._usage=f,this}name(f){if(f===void 0)return this._name;return this._name=f,this}nameFromFilename(f){return this._name=q.basename(f,q.extname(f)),this}executableDir(f){if(f===void 0)return this._executableDir;return this._executableDir=f,this}helpInformation(f){let r=this.createHelp();if(r.helpWidth===void 0)r.helpWidth=f&&f.error?this._outputConfiguration.getErrHelpWidth():this._outputConfiguration.getOutHelpWidth();return r.formatHelp(this,r)}_getHelpContext(f){f=f||{};let r={error:!!f.error},E;if(r.error)E=(t)=>this._outputConfiguration.writeErr(t);else E=(t)=>this._outputConfiguration.writeOut(t);return r.write=f.write||E,r.command=this,r}outputHelp(f){let r;if(typeof f==="function")r=f,f=void 0;let E=this._getHelpContext(f);this._getCommandAndAncestors().reverse().forEach((S)=>S.emit("beforeAllHelp",E)),this.emit("beforeHelp",E);let t=this.helpInformation(E);if(r){if(t=r(t),typeof t!=="string"&&!Buffer.isBuffer(t))throw Error("outputHelp callback must return a string or a Buffer")}if(E.write(t),this._getHelpOption()?.long)this.emit(this._getHelpOption().long);this.emit("afterHelp",E),this._getCommandAndAncestors().forEach((S)=>S.emit("afterAllHelp",E))}helpOption(f,r){if(typeof f==="boolean"){if(f)this._helpOption=this._helpOption??void 0;else this._helpOption=null;return this}return f=f??"-h, --help",r=r??"display help for command",this._helpOption=this.createOption(f,r),this}_getHelpOption(){if(this._helpOption===void 0)this.helpOption(void 0,void 0);return this._helpOption}addHelpOption(f){return this._helpOption=f,this}help(f){this.outputHelp(f);let r=L.exitCode||0;if(r===0&&f&&typeof f!=="function"&&f.error)r=1;this._exit(r,"commander.help","(outputHelp)")}addHelpText(f,r){let E=["beforeAll","before","after","afterAll"];if(!E.includes(f))throw Error(`Unexpected value for position to addHelpText.
22
+ Expecting one of '${E.join("', '")}'`);let t=`${f}Help`;return this.on(t,(S)=>{let R;if(typeof r==="function")R=r({error:S.error,command:S.command});else R=r;if(R)S.write(`${R}
23
+ `)}),this}_outputHelpIfRequested(f){let r=this._getHelpOption();if(r&&f.find((t)=>r.is(t)))this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)")}}function Sf(f){return f.map((r)=>{if(!r.startsWith("--inspect"))return r;let E,t="127.0.0.1",S="9229",R;if((R=r.match(/^(--inspect(-brk)?)$/))!==null)E=R[1];else if((R=r.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null)if(E=R[1],/^\d+$/.test(R[3]))S=R[3];else t=R[3];else if((R=r.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null)E=R[1],t=R[3],S=R[4];if(E&&S!=="0")return`${E}=${t}:${parseInt(S)+1}`;return r})}Ur.Command=v});var _f=M((ur)=>{var{Argument:wf}=H(),{Command:c}=Rf(),{CommanderError:Pr,InvalidArgumentError:Tf}=Z(),{Help:qr}=b(),{Option:$f}=x();ur.program=new c;ur.createCommand=(f)=>new c(f);ur.createOption=(f,r)=>new $f(f,r);ur.createArgument=(f,r)=>new wf(f,r);ur.Command=c;ur.Option=$f;ur.Argument=wf;ur.Help=qr;ur.CommanderError=Pr;ur.InvalidArgumentError=Tf;ur.InvalidOptionArgumentError=Tf});var yf=xf(_f(),1),{program:bE,createCommand:xE,createArgument:hE,createOption:CE,CommanderError:OE,InvalidArgumentError:vE,InvalidOptionArgumentError:cE,Command:J,Argument:nE,Option:iE,Help:gE}=yf.default;import{readFile as ar}from"node:fs/promises";import{resolve as fE}from"node:path";var Lf={name:"@shotstack/cli",version:"0.3.0",description:"Command-line interface for the Shotstack video rendering API.",license:"Apache-2.0",homepage:"https://github.com/shotstack/shotstack-cli",repository:{type:"git",url:"git+https://github.com/shotstack/shotstack-cli.git"},bugs:{url:"https://github.com/shotstack/shotstack-cli/issues"},type:"module",bin:{shotstack:"dist/shotstack.js"},files:["dist/shotstack.js","SKILL.md","references"],scripts:{start:"bun run src/index.ts",build:"bun build src/index.ts --target=node --minify --outfile=dist/shotstack.js --banner='#!/usr/bin/env node' && chmod +x dist/shotstack.js",prepack:"bun run build",typecheck:"tsc --noEmit",test:"bun test"},dependencies:{commander:"^12.1.0"},devDependencies:{"@types/bun":"latest",typescript:"^5.6.0"}};var Q=Lf.version,If=`shotstack-cli/${Q} (${process.platform}-${process.arch})`;class j extends Error{status;body;constructor(f,r,E){super(E);this.status=f;this.body=r;this.name="ApiError"}get isTransient(){return this.status>=500||this.status===429}}function K(f){let r=f.env.baseUrl.replace(/\/$/,"");async function E(t,S,R){let w=await fetch(`${r}${S}`,{method:t,headers:{"x-api-key":f.apiKey,"x-shotstack-origin":"cli","x-shotstack-environment":f.env.name,"user-agent":If,...R!==void 0?{"content-type":"application/json"}:{}},body:R!==void 0?JSON.stringify(R):void 0}),T=await w.text(),$=T?Wr(T):void 0;if(!w.ok)throw new j(w.status,$??T,`${t} ${S} → ${w.status} ${w.statusText}`);return $}return{post:(t,S)=>E("POST",t,S),get:(t)=>E("GET",t)}}function Wr(f){try{return JSON.parse(f)}catch{return f}}class Y extends Error{constructor(){super("SHOTSTACK_API_KEY is not set. Get a key at https://shotstack.io.");this.name="MissingApiKeyError"}}function W(){let f=process.env.SHOTSTACK_API_KEY?.trim();if(!f)throw new Y;return f}var Uf={dev:"https://api.shotstack.io/edit/dev",stage:"https://api.shotstack.io/edit/stage",v1:"https://api.shotstack.io/edit/v1"},G=Object.keys(Uf);class X extends Error{constructor(f){super(`Invalid environment "${f}". Use one of: ${G.join(", ")}.`);this.name="InvalidEnvError"}}function s(f){let r=process.env.SHOTSTACK_API_BASE_URL?.trim();if(r)return{name:"custom",baseUrl:r};let E=f??process.env.SHOTSTACK_ENV?.trim()??"v1";if(!sr(E))throw new X(E);return{name:E,baseUrl:Uf[E]}}function sr(f){return G.includes(f)}function B(f){if(f==="json")return"json";return"text"}function z(f,r,E){if(f==="json")console.log(JSON.stringify(r));else console.log(E)}import{mkdir as kr,appendFile as Dr,stat as uf,readFile as Fr,writeFile as Mf}from"node:fs/promises";import{join as n,dirname as Ar}from"node:path";import{homedir as Jf}from"node:os";var Vr=1e6,br=500000,Pf=2000;function k(){if(process.platform==="win32"){let f=process.env.APPDATA??n(Jf(),"AppData","Roaming");return n(f,"shotstack","log.jsonl")}return n(Jf(),".shotstack","log.jsonl")}function xr(f,r=new Date){let E={ts:r.toISOString(),cmd:f.cmd,args:f.args.map(ir),exit:f.exit,durationMs:f.durationMs};if(f.renderId)E.renderId=f.renderId;if(f.response!==void 0)E.response=or(i(f.response));if(f.error)E.error=hr(f.error);return E}function hr(f){return{name:f.name,message:typeof f.message==="string"?g(f.message):String(f.message)}}function Cr(f){if(f instanceof Error)return{name:f.name,message:f.message};if(f===void 0||f===null)return;return{name:"Unknown",message:String(f)}}async function qf(f,r=k()){let E=xr(f),t=JSON.stringify(E)+`
24
+ `;if(await kr(Ar(r),{recursive:!0,mode:448}),!await Or(r))await Mf(r,"",{mode:384});await Dr(r,t),await vr(r)}async function Or(f){try{return await uf(f),!0}catch{return!1}}async function vr(f){let r=await uf(f).catch(()=>null);if(!r||r.size<=Vr)return;let E=await Fr(f),t=E.subarray(Math.max(0,E.length-br)),S=t.indexOf(10),R=S>=0?t.subarray(S+1):t;await Mf(f,R,{mode:384})}var cr=/^https?:\/\//i,nr=/(https?:\/\/[^\s'"<>]+?)\?[^\s'"<>]*?(?:Signature|X-Amz-[A-Za-z0-9-]*)=[^\s'"<>]*/gi;function g(f){return f.replace(nr,"$1?[redacted-signed]")}function ir(f){if(typeof f!=="string")return f;if(f.startsWith("-"))return f;if(cr.test(f))return g(f);if(/[\/\\]/.test(f))return gr(f);return f}function gr(f){let r=f.split(/[\/\\]/);return r[r.length-1]||f}function i(f){if(typeof f==="string")return g(f);if(Array.isArray(f))return f.map(i);if(f&&typeof f==="object"){let r={};for(let[E,t]of Object.entries(f))r[E]=i(t);return r}return f}function or(f){let r=JSON.stringify(f);if(r===void 0||r.length<=Pf)return f;return r.slice(0,Pf)+"...[truncated]"}async function D(f,r,E){let t=Date.now();try{let S=await E(),R=S.exitCode??0;if(await qf({cmd:f,args:r,exit:R,durationMs:Date.now()-t,renderId:S.renderId,response:S.response}).catch(()=>{}),R!==0)process.exit(R)}catch(S){let R=lr(S),w=S instanceof j?S.body:void 0;throw await qf({cmd:f,args:r,exit:R,durationMs:Date.now()-t,response:w,error:Cr(S)}).catch(()=>{}),S}}function lr(f){if(f instanceof j)return f.isTransient?2:1;if(f instanceof Y||f instanceof X)return 1;if(f instanceof Error&&f.code==="ENOENT")return 1;return 2}function F(f){let r=process.argv.slice(2),E=r.indexOf(f);return E>=0?r.slice(E+1):r}var mr=new Set(["done","failed"]),dr=3000,jf=new J("status").description("Poll the status of a Shotstack render").argument("<id>","Render ID returned by `shotstack render`").option("--watch","Poll continuously until the render reaches a terminal state").option("--env <name>",`Environment: ${G.join(" | ")}`).option("--output <format>","Output format: text | json","text").action(async(f,r)=>{await D("status",F("status"),async()=>{let E=B(r.output),t=W(),S=s(r.env),R=K({apiKey:t,env:S}),w=await o(R,f,E,r.watch===!0),T=w.status==="failed"?1:0;return{renderId:w.id,response:w,exitCode:T}})});async function o(f,r,E,t){while(!0){let R=(await f.get(`/render/${encodeURIComponent(r)}`)).response;if(z(E,R,er(R)),!t||mr.has(R.status))return R;await pr(dr)}}function er(f){let r=[f.status];if(f.url)r.push(f.url);if(f.error)r.push(`error: ${f.error}`);return r.join(" ")}function pr(f){return new Promise((r)=>setTimeout(r,f))}var Yf=new J("render").description("Submit a Shotstack Edit JSON to the render API").argument("<file>","Path to a Shotstack Edit JSON file").option("--env <name>",`Environment: ${G.join(" | ")}`).option("--watch","After submitting, poll until the render reaches a terminal state").option("--output <format>","Output format: text | json","text").action(async(f,r)=>{await D("render",F("render"),async()=>{let E=B(r.output),t=W(),S=s(r.env),R=fE(process.cwd(),f),w=await ar(R,"utf8"),T=JSON.parse(w),$=K({apiKey:t,env:S}),_=await $.post("/render",T),y=_.response.id;if(!r.watch)return z(E,{id:y},y),{renderId:y,response:_.response};let U=await o($,y,E,!0),P=U.status==="failed"?1:0;return{renderId:y,response:U,exitCode:P}})});import{readFile as rE,writeFile as EE,mkdtemp as tE}from"node:fs/promises";import{tmpdir as SE}from"node:os";import{join as Gf}from"node:path";import{spawn as RE}from"node:child_process";var Xf="https://github.com/shotstack/shotstack-cli/issues/new?template=bug.yml",wE=6000,Zf=5,Qf=new J("feedback").description("Open a pre-filled GitHub issue with a flight-recorder dossier from your last 5 invocations").action(async()=>{let f=await TE(Zf),r=$E(f),E=yE(f),t=`&title=${encodeURIComponent(E)}`,S=`${Xf}${t}&body=${encodeURIComponent(r)}`;if(S.length<=wE){Nf(S),console.log("Opened browser with pre-filled issue. Review before submitting.");return}let R=await tE(Gf(SE(),"shotstack-feedback-")),w=Gf(R,"dossier.md");await EE(w,r),Nf(`${Xf}${t}`),console.log(`Dossier too large to inline. Saved to: ${w}`),console.log("Drag the file into the issue body, or paste its contents.")});async function TE(f){let r=k(),E;try{E=await rE(r,"utf8")}catch{return[]}let S=E.split(`
25
+ `).filter((w)=>w.trim().length>0).slice(-f).reverse(),R=[];for(let w of S)try{R.push(JSON.parse(w))}catch{}return R}function $E(f){let r=[];if(r.push("## Environment"),r.push(`- Shotstack CLI: ${Q}`),r.push(`- OS: ${process.platform}-${process.arch}`),r.push(""),r.push(`## Last ${Zf} invocations (most recent first)`),r.push(""),f.length===0)r.push("_No recorded invocations._");else for(let E of f){let t=(E.args??[]).join(" "),S=`### ${E.ts} — shotstack ${E.cmd}${t?" "+t:""}`;if(r.push(S),r.push(`- Exit: ${E.exit} Duration: ${E.durationMs}ms`),E.renderId)r.push(`- Render ID: ${E.renderId}`);if(E.response!==void 0){let R=typeof E.response==="string"?E.response:JSON.stringify(E.response);r.push(`- Response: ${R}`)}if(E.error)r.push(`- Error: ${E.error.name}: ${E.error.message}`);r.push("")}return r.push(`[full log at ${k()}]`),r.push(""),r.push("## What I expected vs what happened"),r.push("<!-- Describe the issue, request, or question here. -->"),r.join(`
26
+ `)}var Bf=80,_E="Feedback from shotstack CLI";function yE(f){let r=f.find((S)=>S.error);if(r&&r.error)return l(`${r.cmd}: ${r.error.name} — ${r.error.message}`);let E=f.find((S)=>zf(S.response)!==null);if(E){let S=zf(E.response);return l(`Render failed: ${S}`)}let t=f.find((S)=>S.exit!==0);if(t)return l(`${t.cmd} exited ${t.exit}`);return _E}function zf(f){if(!f||typeof f!=="object"||Array.isArray(f))return null;let r=f;if(r.state!=="failed")return null;return typeof r.error==="string"&&r.error.length>0?r.error:"unknown error"}function l(f){return f.length<=Bf?f:f.slice(0,Bf-1)+"…"}function Nf(f){let r=process.platform==="win32",E=process.platform==="darwin"?"open":r?"cmd":"xdg-open",S=RE(E,r?["/c","start","",f]:[f],{stdio:"ignore",detached:!0});S.on("error",()=>{console.error(`Could not open browser. Visit: ${f}`)}),S.unref()}import{readFile as LE}from"node:fs/promises";import{resolve as IE}from"node:path";import{spawn as Hf,execSync as UE}from"node:child_process";var Kf="https://shotstack.studio",JE=`${Kf}/api/share`,PE=3000,qE=6000,Wf=new J("studio").description("Open the Edit JSON in the shotstack.studio web editor. By default, posts the JSON to the share API and returns a short URL.").argument("<file>","Path to a Shotstack Edit JSON file").option("--copy","Copy the URL to the clipboard").option("--no-open","Do not try to open the URL in a browser").option("--no-shorten","Skip the share API; emit a base64url URL inline").option("--output <format>","Output format: text | json","text").action(async(f,r)=>{let E=B(r.output),t=IE(process.cwd(),f),S=await LE(t,"utf8"),R=JSON.parse(S);YE(R);let{url:w,shortened:T}=await uE(R,{shorten:r.shorten});if(!T&&w.length>qE)console.error(`warning: encoded URL is ${w.length} characters; large templates may exceed browser URL limits.`);if(r.copy)await GE(w);let $=r.open&&NE()&&BE(w);if(E==="json"||!$)z(E,{url:w,shortened:T},w)});async function uE(f,r={}){if(r.shorten!==!1){let t=await jE(f);if(t)return{url:t,shortened:!0};console.error("warning: could not reach the shotstack.studio share API; falling back to inline URL.")}return{url:ME(f),shortened:!1}}function ME(f){let r=Buffer.from(JSON.stringify(f),"utf8").toString("base64url");return`${Kf}/#json=${r}`}async function jE(f){try{let r=await fetch(JE,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(f),signal:AbortSignal.timeout(PE)});if(!r.ok)return null;return(await r.json()).url??null}catch{return null}}function YE(f){if(!f||typeof f!=="object")throw Error("Template must be a JSON object.");if(!("timeline"in f))throw Error("Template missing required field: timeline.");if(!("output"in f))throw Error("Template missing required field: output.")}async function GE(f){let{cmd:r,args:E}=XE();await new Promise((t,S)=>{let R=Hf(r,E,{stdio:["pipe","ignore","ignore"]});R.on("error",S),R.on("exit",(w)=>w===0?t():S(Error(`${r} exited ${w}`))),R.stdin.end(f)})}function XE(){if(process.platform==="darwin")return{cmd:"pbcopy",args:[]};if(process.platform==="win32")return{cmd:"clip",args:[]};return{cmd:"xclip",args:["-selection","clipboard"]}}function BE(f){let{cmd:r,args:E}=zE(f);try{let t=Hf(r,E,{detached:!0,stdio:"ignore"});return t.on("error",()=>{}),t.unref(),!0}catch{return!1}}function zE(f){if(process.platform==="win32")return{cmd:"cmd",args:["/c","start","",f]};if(process.platform==="darwin")return{cmd:"open",args:[f]};return{cmd:"xdg-open",args:[f]}}function NE(){if(process.platform==="darwin"||process.platform==="win32")return!0;if(!process.env.DISPLAY&&!process.env.WAYLAND_DISPLAY)return!1;try{return UE("command -v xdg-open",{stdio:"ignore"}),!0}catch{return!1}}var ZE=new J().name("shotstack").description("Command-line interface for the Shotstack video rendering API").version(Q).addCommand(Yf).addCommand(jf).addCommand(Wf).addCommand(Qf);try{await ZE.parseAsync(process.argv)}catch(f){process.exit(QE(f))}function QE(f){if(f instanceof Y||f instanceof X)return console.error(f.message),1;if(f instanceof j){if(console.error(f.message),f.body)console.error(typeof f.body==="string"?f.body:JSON.stringify(f.body));return f.isTransient?2:1}if(f instanceof Error){if("code"in f&&f.code==="ENOENT")return console.error(f.message),1;return console.error(f.message),2}return console.error(String(f)),2}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shotstack/cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.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",
@@ -30,7 +30,7 @@ https://shotstack-assets.s3.amazonaws.com/images/waterfall.jpeg
30
30
 
31
31
  ## Music
32
32
 
33
- Royalty-free tracks from the Unminus library, hosted on Shotstack's CDN. Suitable for `timeline.soundtrack` or as audio assets.
33
+ Royalty-free tracks from the Unminus library, hosted on Shotstack's CDN. Use as `audio` assets on a dedicated track. (`timeline.soundtrack` is deprecated — use `audio` with `length: "end"` instead.)
34
34
 
35
35
  ```
36
36
  https://shotstack-assets.s3.amazonaws.com/music/unminus/white.mp3
@@ -1,7 +1,9 @@
1
- # Rich-caption guide
1
+ # Caption guide
2
2
 
3
3
  Word-level animated captions. The most failure-prone asset type — read this fully before composing one.
4
4
 
5
+ The asset type to use is **`rich-caption`** (Shotstack's name for word-level captions). The deprecated `caption` type still parses but produces inferior output — always use `rich-caption`.
6
+
5
7
  ## Contents
6
8
 
7
9
  - The five named presets (use these verbatim when possible)
@@ -31,7 +33,7 @@ White Montserrat, uppercase, with subtle drop shadow. Slides each word down on a
31
33
  "type": "rich-caption",
32
34
  "src": "alias://audio",
33
35
  "font": { "family": "JTUSjIg1_i6t8kCHKm45xW5rygbi49c", "size": 88, "color": "#ffffff", "opacity": 1, "weight": 700 },
34
- "wordAnimation": { "style": "slide", "direction": "down" },
36
+ "animation": { "style": "slide", "direction": "down" },
35
37
  "border": { "width": 0, "color": "#000000", "opacity": 1, "radius": 18 },
36
38
  "style": { "textTransform": "uppercase" },
37
39
  "padding": { "top": 25, "right": 0, "bottom": 0, "left": 0 },
@@ -58,7 +60,7 @@ Inter, black text on white pill background. Active word greys out. Clean editori
58
60
  "type": "rich-caption",
59
61
  "src": "alias://audio",
60
62
  "font": { "family": "UcCo3FwrK3iLTfvlaQc78lA2", "size": 52, "color": "#000000", "opacity": 1, "weight": 700 },
61
- "wordAnimation": { "style": "fade" },
63
+ "animation": { "style": "fade" },
62
64
  "border": { "width": 0, "color": "#000000", "opacity": 1, "radius": 18 },
63
65
  "style": { "textTransform": "none" },
64
66
  "padding": { "top": 25, "right": 0, "bottom": 15, "left": 0 },
@@ -83,7 +85,7 @@ Luckiest Guy, white with thick black stroke, rotated -7.5°, active word gets a
83
85
  "type": "rich-caption",
84
86
  "src": "alias://audio",
85
87
  "font": { "family": "_gP_1RrxsjcxVyin9l9n_j2RStR3qDpraA", "size": 52, "color": "#ffffff", "opacity": 1, "weight": 700 },
86
- "wordAnimation": { "style": "highlight" },
88
+ "animation": { "style": "highlight" },
87
89
  "border": { "width": 0, "color": "#000000", "opacity": 1, "radius": 18 },
88
90
  "style": { "textTransform": "uppercase" },
89
91
  "padding": { "top": 0, "right": 0, "bottom": 0, "left": 0 },
@@ -112,7 +114,7 @@ Montserrat, white with thin stroke and shadow, active word in soft pink. Romanti
112
114
  "type": "rich-caption",
113
115
  "src": "alias://audio",
114
116
  "font": { "family": "JTUSjIg1_i6t8kCHKm45xW5rygbi49c", "size": 36, "color": "#ffffff", "opacity": 1, "weight": 700 },
115
- "wordAnimation": { "style": "highlight" },
117
+ "animation": { "style": "highlight" },
116
118
  "border": { "width": 0, "color": "#000000", "opacity": 1, "radius": 18 },
117
119
  "style": { "textTransform": "none" },
118
120
  "padding": { "top": 15, "right": 0, "bottom": 0, "left": 0 },
@@ -142,7 +144,7 @@ Bangers, white with very thick black stroke, active word turns blue. High-energy
142
144
  "type": "rich-caption",
143
145
  "src": "alias://audio",
144
146
  "font": { "family": "FeVQS0BTqb0h60ACL5la2bxii28", "size": 84, "color": "#ffffff", "opacity": 1, "weight": 700 },
145
- "wordAnimation": { "style": "pop" },
147
+ "animation": { "style": "pop" },
146
148
  "border": { "width": 0, "color": "#000000", "opacity": 1, "radius": 18 },
147
149
  "style": { "textTransform": "none" },
148
150
  "padding": { "top": 35, "right": 0, "bottom": 0, "left": 0 },
@@ -182,7 +184,7 @@ Rich-caption transcribes audio to produce word-level timing. Three ways to sourc
182
184
  | `src` value | Behaviour |
183
185
  |---|---|
184
186
  | `alias://<name>` | Auto-transcribe a referenced audio/video/text-to-speech clip. Set `alias: "<name>"` on the source clip. **Preferred for sync.** |
185
- | Subtitle file URL | Use existing `.srt`, `.vtt`, `.ttml`, or `.dfxp` file. No auto-transcription. |
187
+ | Subtitle file URL | Use existing `.srt` or `.vtt` file. No auto-transcription. |
186
188
  | Audio/video file URL | Auto-transcribe a standalone media file. Use when there's no source clip on the timeline. |
187
189
 
188
190
  The `alias://` form keeps the captions in sync with the source clip even when you change its `start` or `length`.
@@ -210,7 +212,7 @@ If none of the five presets fits, copy the closest preset and modify. The proper
210
212
  | Group | Properties |
211
213
  |---|---|
212
214
  | `font` | `family`, `size`, `color`, `opacity`, `weight` |
213
- | `wordAnimation` | `style`: `fade`, `slide`, `highlight`, `pop`. `direction` for slide: `up`, `down`, `left`, `right`. |
215
+ | `animation` | `style`: `fade`, `slide`, `highlight`, `pop`. `direction` for slide: `up`, `down`, `left`, `right`. |
214
216
  | `border` | `width`, `color`, `opacity`, `radius` |
215
217
  | `padding` | `top`, `right`, `bottom`, `left` (numbers) |
216
218
  | `stroke` | `width`, `color`, `opacity` (text outline) |
@@ -1,6 +1,6 @@
1
1
  # Fonts guide
2
2
 
3
- The Shotstack render engine ships a small built-in font set; everything else must be loaded as a custom font via `timeline.fonts[]`. Per the [Shotstack docs](https://shotstack.io/docs/guide/architecting-an-application/rich-text/#custom-fonts), **prefer custom Google Fonts** for predictable rendering and full typographic range.
3
+ The Shotstack render engine ships a small built-in font set; everything else must be loaded as a custom font via `timeline.fonts[]`. Per the [Shotstack docs](https://shotstack.io/docs/guide/architecting-an-application/rich-text.md), **prefer custom Google Fonts** for predictable rendering and full typographic range.
4
4
 
5
5
  ## Contents
6
6
 
package/references/svg.md CHANGED
@@ -57,46 +57,97 @@ Standard fill, stroke, and transform attributes work: `fill`, `fill-opacity`, `s
57
57
 
58
58
  Animated SVGs are not rendered — only the static initial frame is used.
59
59
 
60
- ## Worked example: lower-third bar
60
+ ## Worked example: speech bubble for a testimonial
61
+
62
+ Speech bubbles are an example "rich-text can't do this" case — a rounded body with a tail pointing at the speaker requires a `<path>`. Pair the SVG bubble with a `rich-text` clip for the quote inside it.
61
63
 
62
64
  ```json
63
65
  {
64
66
  "timeline": {
65
67
  "tracks": [
66
68
  {
67
- "clips": [{
68
- "asset": {
69
- "type": "rich-text",
70
- "text": "Jane Smith — CEO",
71
- "font": { "family": "JTUSjIg1_i6t8kCHKm45xW5rygbi49c", "size": 48, "color": "#ffffff" }
72
- },
73
- "start": 0, "length": 5,
74
- "offset": { "x": -0.2, "y": -0.35 }
75
- }]
69
+ "clips": [
70
+ {
71
+ "asset": {
72
+ "type": "rich-text",
73
+ "text": "This changed our workflow completely.",
74
+ "font": {
75
+ "family": "JTUSjIg1_i6t8kCHKm45xW5rygbi49c",
76
+ "size": 44,
77
+ "color": "#0f172a",
78
+ "weight": 600
79
+ },
80
+ "align": {
81
+ "horizontal": "center",
82
+ "vertical": "middle"
83
+ }
84
+ },
85
+ "start": 0.5,
86
+ "length": 4,
87
+ "width": 540,
88
+ "height": 160,
89
+ "offset": {
90
+ "x": 0.235,
91
+ "y": 0.373
92
+ }
93
+ }
94
+ ]
76
95
  },
77
96
  {
78
- "clips": [{
79
- "asset": {
80
- "type": "svg",
81
- "src": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 1920 200\" width=\"1920\" height=\"200\"><rect x=\"0\" y=\"0\" width=\"1920\" height=\"200\" fill=\"#000000\" fill-opacity=\"0.7\"/></svg>"
82
- },
83
- "start": 0, "length": 5,
84
- "offset": { "x": 0, "y": -0.35 }
85
- }]
97
+ "clips": [
98
+ {
99
+ "asset": {
100
+ "type": "svg",
101
+ "src": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 600 220\" width=\"600\" height=\"220\"><path d=\"M 40 0 H 560 Q 600 0 600 40 V 140 Q 600 180 560 180 H 200 L 160 220 L 170 180 H 40 Q 0 180 0 140 V 40 Q 0 0 40 0 Z\" fill=\"#ffffff\" stroke=\"#0f172a\" stroke-width=\"4\"/></svg>"
102
+ },
103
+ "start": 0.5,
104
+ "length": 4,
105
+ "width": 600,
106
+ "height": 220,
107
+ "offset": {
108
+ "x": 0.235,
109
+ "y": 0.356
110
+ },
111
+ "transition": {
112
+ "in": "fade",
113
+ "out": "fade"
114
+ }
115
+ }
116
+ ]
86
117
  },
87
118
  {
88
- "clips": [{
89
- "asset": { "type": "video", "src": "https://shotstack-assets.s3.amazonaws.com/footage/beach.mp4" },
90
- "start": 0, "length": 5
91
- }]
119
+ "clips": [
120
+ {
121
+ "asset": {
122
+ "type": "image",
123
+ "src": "https://shotstack-assets.s3.amazonaws.com/images/business-man.jpg"
124
+ },
125
+ "start": 0,
126
+ "length": 5,
127
+ "fit": "crop"
128
+ }
129
+ ]
92
130
  }
93
131
  ]
94
132
  },
95
- "output": { "format": "mp4", "resolution": "1080" }
133
+ "output": {
134
+ "format": "mp4",
135
+ "resolution": "1080"
136
+ }
96
137
  }
97
138
  ```
98
139
 
99
- Track order: text on top, semi-transparent black bar in the middle, video on the bottom.
140
+ Track order: rich-text quote on top, SVG bubble in the middle, talking-head video at the bottom. The `<path>` `d` attribute draws a rounded rectangle (40px corner radius via `Q` curves) with a triangular tail at the bottom pointing toward the speaker. `stroke` gives the bubble an outline; `fill="#ffffff"` makes the body opaque.
141
+
142
+ Position the bubble with `offset` so the tail points at the subject's head. Adjust the path's tail coordinates (`L 160 220 L 170 180`) to point left/right/up depending on where the speaker is in frame.
143
+
144
+ Other patterns SVG is right for:
145
+
146
+ - **Tutorial highlight rings** — `<circle>` with `fill="none"` and a thick `stroke`, positioned over a UI element.
147
+ - **Brand badges** — small geometric lockups using `<rect>`/`<polygon>` plus `transform`.
148
+ - **Decorative dividers** — wavy lines or geometric frames between scenes.
149
+
150
+ If you only need a coloured rectangle behind text, **don't reach for SVG** — `rich-text` already supports `background.color`/`opacity`/`borderRadius`. Reserve SVG for shapes rich-text can't produce.
100
151
 
101
152
  ## When to use SVG vs rich-text
102
153
 
@@ -1,6 +1,6 @@
1
1
  # Timeline conventions
2
2
 
3
- Detailed guide to track layering, the soundtrack vs audio distinction, and `timeline.fonts[]`. Read this when building any non-trivial Edit JSON.
3
+ Detailed guide to track layering, background music (via `audio` assets — `timeline.soundtrack` is deprecated), and `timeline.fonts[]`. Read this when building any non-trivial Edit JSON.
4
4
 
5
5
  ## Contents
6
6
 
@@ -17,7 +17,7 @@ The single most counter-intuitive Shotstack convention.
17
17
 
18
18
  `timeline.tracks` is an array. **The first element is the TOP layer (foreground); the last is the BOTTOM (background).** The order of the JSON array IS the visual stacking order, top-to-bottom.
19
19
 
20
- Per the [official docs](https://shotstack.io/docs/guide/architecting-an-application/guidelines/):
20
+ Per the [official docs](https://shotstack.io/docs/guide/getting-started/core-concepts.md):
21
21
 
22
22
  > Tracks are layered on top of each other in the same order they are added to the array with the top most track layered over the top of those below it.
23
23
 
@@ -72,25 +72,32 @@ If you put the video first and the captions last, the video covers the captions
72
72
  | Title card on video | Title clip in early track, video in later track |
73
73
  | Picture-in-picture | PiP video in early track, main video in later track |
74
74
 
75
- ## Soundtrack vs audio asset
75
+ ## Background music: use `audio`, not `timeline.soundtrack`
76
76
 
77
- Prefer `Audio` assets — they support custom timing, keyframes, and effects, and can do everything `timeline.soundtrack` can. Use `timeline.soundtrack` only when you want a single background track spanning the whole edit.
77
+ `timeline.soundtrack` is **deprecated**. Always use an `audio` asset on its own track with `length: "end"`. The audio asset path supports keyframes, custom timing, multi-clip mixing, and the full effect set; soundtrack does not.
78
78
 
79
79
  ```json
80
80
  {
81
81
  "timeline": {
82
- "soundtrack": {
83
- "src": "https://shotstack-assets.s3.amazonaws.com/music/unminus/palmtrees.mp3",
84
- "effect": "fadeOut"
85
- },
86
- "tracks": [/* ... */]
82
+ "tracks": [
83
+ /* ...other tracks... */
84
+ {
85
+ "clips": [{
86
+ "asset": {
87
+ "type": "audio",
88
+ "src": "https://shotstack-assets.s3.amazonaws.com/music/unminus/palmtrees.mp3",
89
+ "effect": "fadeOut"
90
+ },
91
+ "start": 0,
92
+ "length": "end"
93
+ }]
94
+ }
95
+ ]
87
96
  }
88
97
  }
89
98
  ```
90
99
 
91
- `soundtrack.effect` accepts `fadeIn`, `fadeOut`, or `fadeInFadeOut`.
92
-
93
- An `audio` clip with `length: "end"` is functionally identical to `timeline.soundtrack`.
100
+ `asset.effect` on audio accepts `fadeIn`, `fadeOut`, or `fadeInFadeOut` (same enum the deprecated soundtrack used).
94
101
 
95
102
  ## `timeline.fonts[]` for custom fonts
96
103
 
@@ -127,7 +134,7 @@ See `references/fonts.md` for the full pattern.
127
134
 
128
135
  ## Common track-layout patterns
129
136
 
130
- **Slideshow:** images in one track, soundtrack for music. One image per clip; use `start: "auto"` to chain them.
137
+ **Slideshow:** images in one track, an `audio` asset on a separate track with `length: "end"` for the background music. One image per clip; use `start: "auto"` to chain them.
131
138
 
132
139
  **Voiceover with captions:** captions in track[0], audio in track[1] (with `alias` for the captions to reference), video/image in track[2].
133
140
 
@@ -61,7 +61,7 @@ You used a font name that isn't in the built-in list and didn't load it via `tim
61
61
 
62
62
  A `rich-caption` clip without `width`, `height`, and `fit: "none"` defaults to filling the entire output.
63
63
 
64
- **Fix:** use one of the five named presets in `references/rich-caption.md` (Nico, Kai, Kapow, Lovely Little Lychee, Rizz) which include the right dimensions, or set `width`/`height`/`fit: "none"` explicitly on your clip.
64
+ **Fix:** use one of the five named presets in `references/caption.md` (Nico, Kai, Kapow, Lovely Little Lychee, Rizz) which include the right dimensions, or set `width`/`height`/`fit: "none"` explicitly on your clip.
65
65
 
66
66
  ## Timeline renders but layers are wrong
67
67