@cueframe/skills 0.1.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/.agents/plugins/marketplace.json +12 -0
- package/.claude-plugin/marketplace.json +6 -0
- package/.claude-plugin/plugin.json +15 -0
- package/.codex-plugin/plugin.json +30 -0
- package/.cursor-plugin/plugin.json +1 -0
- package/.mcp.json +1 -0
- package/AGENTS.md +20 -0
- package/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +111 -0
- package/assets/icon.svg +16 -0
- package/assets/logo-400.png +0 -0
- package/gemini-extension.json +1 -0
- package/glama.json +1 -0
- package/hooks/hooks.json +7 -0
- package/hooks/session-inject.md +15 -0
- package/hooks/session-start.sh +6 -0
- package/llms-install.md +47 -0
- package/mcp.json +1 -0
- package/package.json +57 -0
- package/plugin.json +46 -0
- package/rules/cueframe.mdc +19 -0
- package/skills/add-music-bed/SKILL.md +100 -0
- package/skills/add-music-bed/agents/openai.yaml +6 -0
- package/skills/add-music-bed/assets/icon.svg +16 -0
- package/skills/brand-reel/SKILL.md +100 -0
- package/skills/brand-reel/agents/openai.yaml +6 -0
- package/skills/brand-reel/assets/icon.svg +16 -0
- package/skills/clip-a-talking-head/SKILL.md +101 -0
- package/skills/clip-a-talking-head/agents/openai.yaml +6 -0
- package/skills/clip-a-talking-head/assets/icon.svg +16 -0
- package/skills/composing-video/SKILL.md +702 -0
- package/skills/composing-video/agents/openai.yaml +6 -0
- package/skills/composing-video/assets/icon.svg +16 -0
- package/skills/cueframe-brand-demo/SKILL.md +257 -0
- package/skills/cueframe-brand-demo/agents/openai.yaml +6 -0
- package/skills/cueframe-brand-demo/assets/icon.svg +16 -0
- package/skills/cueframe-cli/SKILL.md +265 -0
- package/skills/cueframe-cli/agents/openai.yaml +6 -0
- package/skills/cueframe-cli/assets/icon.svg +16 -0
- package/skills/cueframe-component-authoring/SKILL.md +179 -0
- package/skills/cueframe-component-authoring/agents/openai.yaml +6 -0
- package/skills/cueframe-component-authoring/assets/icon.svg +16 -0
- package/skills/cueframe-compose-loop/SKILL.md +114 -0
- package/skills/cueframe-compose-loop/agents/openai.yaml +6 -0
- package/skills/cueframe-compose-loop/assets/icon.svg +16 -0
- package/skills/cueframe-compose-loop/references/preview-workflow.md +37 -0
- package/skills/cueframe-connect/SKILL.md +45 -0
- package/skills/cueframe-connect/agents/openai.yaml +6 -0
- package/skills/cueframe-connect/assets/icon.svg +16 -0
- package/skills/cueframe-product-video/SKILL.md +293 -0
- package/skills/cueframe-product-video/agents/openai.yaml +6 -0
- package/skills/cueframe-product-video/assets/icon.svg +16 -0
- package/skills/cueframe-scene-shot/SKILL.md +68 -0
- package/skills/cueframe-scene-shot/agents/openai.yaml +6 -0
- package/skills/cueframe-scene-shot/assets/icon.svg +16 -0
- package/skills/cueframe-storyboard/SKILL.md +104 -0
- package/skills/cueframe-storyboard/agents/openai.yaml +6 -0
- package/skills/cueframe-storyboard/assets/icon.svg +16 -0
- package/skills/every-format-from-one-edit/SKILL.md +87 -0
- package/skills/every-format-from-one-edit/agents/openai.yaml +6 -0
- package/skills/every-format-from-one-edit/assets/icon.svg +16 -0
- package/skills/extracting-brand-kits/SKILL.md +159 -0
- package/skills/extracting-brand-kits/agents/openai.yaml +6 -0
- package/skills/extracting-brand-kits/assets/icon.svg +16 -0
- package/skills/launch-video/SKILL.md +93 -0
- package/skills/launch-video/agents/openai.yaml +6 -0
- package/skills/launch-video/assets/icon.svg +16 -0
- package/skills/make-a-social-reel/SKILL.md +105 -0
- package/skills/make-a-social-reel/agents/openai.yaml +6 -0
- package/skills/make-a-social-reel/assets/icon.svg +16 -0
- package/skills/rebrand-a-video/SKILL.md +95 -0
- package/skills/rebrand-a-video/agents/openai.yaml +6 -0
- package/skills/rebrand-a-video/assets/icon.svg +16 -0
- package/skills/video-craft-standards/SKILL.md +128 -0
- package/skills/video-craft-standards/agents/openai.yaml +6 -0
- package/skills/video-craft-standards/assets/icon.svg +16 -0
- package/skills-dir.d.ts +1 -0
- package/skills-dir.js +2 -0
- package/skills.sh.json +1 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Composing Video: craft for CueFrame"
|
|
3
|
+
short_description: "Use when an agent is asked to make ANY video with CueFrame — a product launch…"
|
|
4
|
+
icon_small: "./assets/icon.svg"
|
|
5
|
+
icon_large: "./assets/icon.svg"
|
|
6
|
+
default_prompt: "Use $composing-video when an agent is asked to make ANY video with CueFrame — a product launch, announcement, promo, teaser, social clip, reel, short, explainer, animated explainer, concept video, product/dev-tool demo, walkthrough, or founder/talking-head piece."
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<clipPath id="cf-favicon-clip"><circle cx="128" cy="128" r="118"/></clipPath>
|
|
3
|
+
<circle cx="128" cy="128" r="118" fill="#f7c948"/>
|
|
4
|
+
<g clip-path="url(#cf-favicon-clip)">
|
|
5
|
+
<path d="M88 128Q160 40 300-40" fill="none" stroke="#160f08" stroke-width="5"/>
|
|
6
|
+
<path d="M88 128Q170 60 310 20" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
7
|
+
<path d="M88 128Q180 80 316 70" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
8
|
+
<path d="M88 128Q186 110 320 110" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
9
|
+
<path d="M88 128Q186 146 320 146" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
10
|
+
<path d="M88 128Q180 176 316 186" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
11
|
+
<path d="M88 128Q170 196 310 236" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
12
|
+
<path d="M88 128Q160 216 300 296" fill="none" stroke="#160f08" stroke-width="5"/>
|
|
13
|
+
</g>
|
|
14
|
+
<circle cx="88" cy="128" r="20" fill="#160f08"/>
|
|
15
|
+
<circle cx="88" cy="128" r="8" fill="#f7c948"/>
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cueframe-brand-demo
|
|
3
|
+
description: Use when turning a local app into a brand-consistent product demo with CueFrame — extract the brand straight from the repo (colors/fonts/logo/motion), capture a Playwright walkthrough of the running app, and author a branded, auto-zoomed demo whose intro/outro/logo/colors/fonts/motion are frozen by CueFrame's engine — e.g. "make an on-brand demo of my app", "record my localhost and produce a branded launch video". This is the end-to-end brand pipeline over the CueFrame curated tools.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# CueFrame — Brand demo recipe
|
|
7
|
+
|
|
8
|
+
> **Kit truth over MCP (current limits):** kit CONTENTS are not yet inspectable over MCP (`get_profile` lists names only), so `$brand:` tokens resolve blind — verify resolved fonts/colors with a `preview_frame` still, and when the kit conflicts with an explicit client spec, the spec wins (hardcode it and note the conflict). Bind kits by the SERVER id from `get_profile` (slug binding is unreliable — it can silently bind nothing); always confirm via the project response `brandKitId`.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
A **use-case recipe** that runs end-to-end from inside the user's own project
|
|
12
|
+
folder. You (Claude) already see their code and their running app — that's the
|
|
13
|
+
unfair advantage. This skill turns that context into a brand-consistent product
|
|
14
|
+
video: pull the brand from the repo, capture the app, and author a demo whose
|
|
15
|
+
**brand identity is enforced by the engine**, not re-typed per clip.
|
|
16
|
+
|
|
17
|
+
Two things make this different from `cueframe-product-video`:
|
|
18
|
+
|
|
19
|
+
1. **The brand is real engine state.** A `brandKit` (created with
|
|
20
|
+
`create_brand_kit`) carries colors / fonts / spacing / sizing / motion / logo
|
|
21
|
+
/ intro / outro / watermark. A composition references it by `brandKitId`;
|
|
22
|
+
**render freezes it** — intro/outro bumpers are auto-prepended/appended, and
|
|
23
|
+
every overlay that binds a `$brand:` token resolves against the kit. Edit the
|
|
24
|
+
kit, re-render, the whole video re-themes. You don't hand-paint brand colors
|
|
25
|
+
onto each clip.
|
|
26
|
+
2. **Drive CueFrame directly.** Brand consistency is a first-class CueFrame
|
|
27
|
+
capability now. Don't reach for an external generator to "make it look
|
|
28
|
+
branded"; author the intent against the brand kit and let render
|
|
29
|
+
materialize it.
|
|
30
|
+
|
|
31
|
+
Drive the primitives with the `cueframe-cli` skill and converge with
|
|
32
|
+
`cueframe-compose-loop`; this tells you *what brand-demo to author*.
|
|
33
|
+
|
|
34
|
+
Use the compose-loop [preview workflow](../cueframe-compose-loop/references/preview-workflow.md)
|
|
35
|
+
for iteration. Check brand/layout with stills and motion with `preview_clip`; a small revision
|
|
36
|
+
does not require rerunning the Director or exporting the whole film. The pipeline below is for
|
|
37
|
+
a new finished demo; choose the self-driven loop when the user has not asked for Director authoring.
|
|
38
|
+
|
|
39
|
+
## The pipeline
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
extract brand (repo + live UI) → create_brand_kit
|
|
43
|
+
→ capture (screen-capture client: Playwright walkthrough of localhost → MP4) → import_media
|
|
44
|
+
→ get_media_context (faces + transcript)
|
|
45
|
+
→ apply_composition (edit plan + brand template, refs brandKitId + $brand:)
|
|
46
|
+
→ compose { fromComposition:true } → wait_job kind:compose
|
|
47
|
+
→ create_render → wait_job kind:render → branded MP4
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 1. Extract the brand → `create_brand_kit`
|
|
51
|
+
|
|
52
|
+
You are running in the user's project. Read the brand out of the codebase
|
|
53
|
+
instead of asking for it:
|
|
54
|
+
|
|
55
|
+
- **Colors** — `tailwind.config.*` `theme.extend.colors`, CSS custom properties
|
|
56
|
+
(`:root { --primary … }`), a `design.md` / tokens file, or the rendered UI.
|
|
57
|
+
- **Fonts** — `@font-face` / `next/font` / `<link>` declarations, the Tailwind
|
|
58
|
+
`fontFamily` map, and which family is headings vs body.
|
|
59
|
+
- **Logo** — `public/`/`assets/` SVG/PNG; host it at a public https URL (or
|
|
60
|
+
`import_media` it and use the resulting URL) so render can fetch it.
|
|
61
|
+
- **Spacing / sizing / radius** — the Tailwind scale, `--radius`, base font sizes.
|
|
62
|
+
- **Voice** — README / landing copy → a one-paragraph `voiceGuidelines`.
|
|
63
|
+
|
|
64
|
+
Synthesize and call `create_brand_kit`. The accepted shape (Phase 1 — the kit now
|
|
65
|
+
carries full brand identity, not just colors/fonts):
|
|
66
|
+
|
|
67
|
+
```jsonc
|
|
68
|
+
{
|
|
69
|
+
"kitId": "acme", // caller-chosen stable id (re-POST upserts in place)
|
|
70
|
+
"name": "Acme",
|
|
71
|
+
"tagline": "Ship faster",
|
|
72
|
+
"colors": { // REQUIRED — all five
|
|
73
|
+
"primary": "#4F46E5", "secondary": "#0EA5E9", "accent": "#22C55E",
|
|
74
|
+
"background": "#0B0B0F", "text": "#FAFAFA"
|
|
75
|
+
},
|
|
76
|
+
"headingFont": { "fontFamily": "Geist", "fontWeight": 700 },
|
|
77
|
+
"bodyFont": { "fontFamily": "Inter", "fontWeight": 400 },
|
|
78
|
+
"voiceGuidelines": "Confident, plain-spoken, no hype.",
|
|
79
|
+
"motion": { "duration": 0.4, "easing": "ease-out", "entrance": "stagger-up", "staggerMs": 60 },
|
|
80
|
+
"logo": { "src": "https://…/logo.svg", "placement": "br", "sizePct": 8 },
|
|
81
|
+
"intro": { "kind": "card", "title": "Acme", "subtitle": "Ship faster", "durationMs": 1500 },
|
|
82
|
+
"outro": { "kind": "card", "title": "acme.dev", "durationMs": 2000 },
|
|
83
|
+
"watermark": { "src": "https://…/mark.svg", "opacity": 0.6, "placement": "br" },
|
|
84
|
+
"spacing": { "base": 16, "lg": 32, "sm": 8 },
|
|
85
|
+
"sizing": { "fontSizeHeading": 64, "fontSizeBody": 28, "borderRadius": 12 }
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`colors{primary,secondary,accent,background,text}`, `headingFont`, `bodyFont`,
|
|
90
|
+
`name`, `kitId` are required; everything else is optional. The response returns the
|
|
91
|
+
kit `id` — that's the `brandKitId` you'll reference. **Show the founder the
|
|
92
|
+
synthesized kit and let them override** before composing; the kit is the brand
|
|
93
|
+
contract for every clip.
|
|
94
|
+
|
|
95
|
+
## 2. Capture → one clean MP4
|
|
96
|
+
|
|
97
|
+
Record a walkthrough of the **running local app** with an external screen-capture
|
|
98
|
+
client: a headed Playwright script drives `localhost` while a native screen
|
|
99
|
+
recorder captures it, and you get one
|
|
100
|
+
CFR / faststart MP4 plus the cursor/click events (timed viewport coordinates —
|
|
101
|
+
the focus points the auto-zoom follows; see `cueframe-product-video` §1–2). Use
|
|
102
|
+
your codebase knowledge to script the walkthrough: open the real flows that
|
|
103
|
+
matter, click the features worth showing, pause on results.
|
|
104
|
+
|
|
105
|
+
Get the recording into CueFrame with `import_media` (public https URL) — it's
|
|
106
|
+
async; poll `list_media` for `processingStatus:"ready"` (or register
|
|
107
|
+
`create_webhook` on `media.completed`). Keep the click points; you'll map them onto
|
|
108
|
+
the rendered duration for the zoom.
|
|
109
|
+
|
|
110
|
+
## 3. Context → `get_media_context`
|
|
111
|
+
|
|
112
|
+
`get_media_context` returns **faces** (subject roster + `speakingShare`, for any
|
|
113
|
+
talking-head/presenter beat) and the **transcript** (per-word `start`/`end` for
|
|
114
|
+
caption timing). Combine it with what you already know from the code — you can
|
|
115
|
+
script and interpret the demo better than transcript-alone, because you know what
|
|
116
|
+
each screen *is*.
|
|
117
|
+
|
|
118
|
+
## 4. Author the seed composition → `apply_composition`
|
|
119
|
+
|
|
120
|
+
Author the edit plan **and** the brand template in one composition, then reference
|
|
121
|
+
the kit by `brandKitId`. Two layers:
|
|
122
|
+
|
|
123
|
+
**a. The edit plan** (same craft as `cueframe-product-video`): the screen
|
|
124
|
+
recording on a video track carrying `reframe` punch-ins from the click points
|
|
125
|
+
(`autoZoom` output — `frame-center` in the gaps, `point` over each click),
|
|
126
|
+
optional speed, and transcript-timed `captions`.
|
|
127
|
+
|
|
128
|
+
**b. The brand template** — overlays that bind `$brand:` tokens so they resolve
|
|
129
|
+
against the kit at render:
|
|
130
|
+
|
|
131
|
+
| Goal | how |
|
|
132
|
+
|---|---|
|
|
133
|
+
| intro / outro card | **automatic** — the kit's `intro`/`outro` are prepended/appended at render. Don't author bumper clips. |
|
|
134
|
+
| logo bug | **automatic** — the kit's `logo` is painted as a corner mark at render (placement/size from the kit; it lifts above the caption band). Don't author a logo overlay. |
|
|
135
|
+
| lower-third / title | `lower-third` or `heroText` overlay, colors/fonts bound to `$brand:` tokens |
|
|
136
|
+
| captions | top-level `captions` — themed by the kit's `captionProfile` + `syncCaptions` (don't bind `$brand:` in `captions.style`; captions resolve through the profile, not token refs) |
|
|
137
|
+
| motion identity | overlays inherit `$brand:motion.*`; the kit's entrance/timing drive the feel |
|
|
138
|
+
|
|
139
|
+
The `$brand:` vocabulary (the frozen token paths render resolves) — bind these,
|
|
140
|
+
never hardcode brand hexes/fonts:
|
|
141
|
+
|
|
142
|
+
- **colors** — `$brand:colors.{background,surface,card,text,textMuted,textOnMedia,border,accent,accentMuted,textOnAccent,textOnSurface}`.
|
|
143
|
+
Text **over footage** → `$brand:colors.textOnMedia` (the legible-over-video slot).
|
|
144
|
+
- **fonts** — `$brand:fonts.heading.family`, `$brand:fonts.body.family`, `$brand:fonts.caption.family`.
|
|
145
|
+
- **motion** — `$brand:motion.{duration,easing,entrance,staggerMs,exitMs}`.
|
|
146
|
+
- **spacing / sizing** — `$brand:spacing.{base,lg,sm}`, `$brand:sizing.{fontSizeHeading,fontSizeBody,fontSizeLabel,borderRadius}`.
|
|
147
|
+
|
|
148
|
+
An unset brand-driven slot on a text overlay auto-binds to its token (you don't
|
|
149
|
+
have to spell out every one); spell out the ones you care about. A `$brand:` ref
|
|
150
|
+
that doesn't resolve is **loud** in render logs and a contrast-critical text color
|
|
151
|
+
falls to a legible neutral — it never silently ships an off-brand frame.
|
|
152
|
+
|
|
153
|
+
Set `brandKitId` at the top of the composition. `apply_composition` with
|
|
154
|
+
`dry_run:true` validates the batch without persisting — validate before you
|
|
155
|
+
compose.
|
|
156
|
+
|
|
157
|
+
### Worked example — branded seed composition (16:9)
|
|
158
|
+
|
|
159
|
+
`brandKitId` ties the kit in; the intro/outro/logo come from the kit
|
|
160
|
+
automatically (NOT authored here); the `lower-third` binds `$brand:` tokens and
|
|
161
|
+
the `captions` are themed by the kit's `captionProfile`. Swap `<…>` for real ids;
|
|
162
|
+
durations are illustrative — match your source.
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"v": 1,
|
|
167
|
+
"format": { "aspectRatio": "16:9", "fps": 30 },
|
|
168
|
+
"brandKitId": "<brandKitId>",
|
|
169
|
+
"tracks": [
|
|
170
|
+
{
|
|
171
|
+
"id": "v-screen", "kind": "video", "contents": [
|
|
172
|
+
{
|
|
173
|
+
"id": "rec", "startTime": 0, "duration": 12,
|
|
174
|
+
"source": {
|
|
175
|
+
"kind": "media", "mediaId": "<screenMediaId>",
|
|
176
|
+
"reframe": { "segments": [
|
|
177
|
+
{ "startSec": 0, "endSec": 2, "focus": { "mode": "frame-center" }, "zoom": 1 },
|
|
178
|
+
{ "startSec": 2, "endSec": 5, "focus": { "mode": "point", "x": 0.28, "y": 0.42 }, "zoom": 0.6, "ease": { "in": 0.4, "out": 0.4 } },
|
|
179
|
+
{ "startSec": 5, "endSec": 7, "focus": { "mode": "frame-center" }, "zoom": 1, "ease": { "in": 0.4, "out": 0.4 } },
|
|
180
|
+
{ "startSec": 7, "endSec": 10, "focus": { "mode": "point", "x": 0.72, "y": 0.66 }, "zoom": 0.55, "ease": { "in": 0.4, "out": 0.4 } },
|
|
181
|
+
{ "startSec": 10, "endSec": 12, "focus": { "mode": "frame-center" }, "zoom": 1, "ease": { "in": 0.4, "out": 0.4 } }
|
|
182
|
+
] }
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"id": "ov", "kind": "overlay", "contents": [
|
|
189
|
+
{
|
|
190
|
+
"id": "title", "startTime": 1, "duration": 3.5,
|
|
191
|
+
"source": {
|
|
192
|
+
"kind": "overlay", "primitiveId": "lower-third",
|
|
193
|
+
"params": {
|
|
194
|
+
"text": "One-command deploys", "subtitle": "Acme", "variant": "modern",
|
|
195
|
+
"tokens": {
|
|
196
|
+
"textColor": "$brand:colors.textOnMedia",
|
|
197
|
+
"accentColor": "$brand:colors.accent",
|
|
198
|
+
"fontFamily": "$brand:fonts.heading.family"
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
],
|
|
206
|
+
"captions": {
|
|
207
|
+
"segments": [
|
|
208
|
+
{ "words": [
|
|
209
|
+
{ "text": "Ship", "startMs": 0, "endMs": 360 },
|
|
210
|
+
{ "text": "in", "startMs": 360, "endMs": 520 },
|
|
211
|
+
{ "text": "one", "startMs": 520, "endMs": 760, "emphasis": true },
|
|
212
|
+
{ "text": "command", "startMs": 760, "endMs": 1300 }
|
|
213
|
+
] }
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## 5. Refine + judge → `compose { fromComposition: true }`
|
|
220
|
+
|
|
221
|
+
Hand the seed to the Director: `compose` with `{ fromComposition: true }`
|
|
222
|
+
authors an ensemble of candidates from your seed, runs the **server-side judge —
|
|
223
|
+
including the brand axis** (on-brand color/type/voice cohesion), and saves the
|
|
224
|
+
winner. Returns a `composeJobId`; `wait_job` `kind:"compose"` (or a webhook on
|
|
225
|
+
`compose.completed`). The result carries the winner's composite score — verification
|
|
226
|
+
is built in. Pass your brief as `editorialIntent` so editorial is graded against
|
|
227
|
+
what you meant. (To self-drive the loop instead, see `cueframe-compose-loop`.)
|
|
228
|
+
|
|
229
|
+
## 6. Render → branded MP4
|
|
230
|
+
|
|
231
|
+
`create_render` → `wait_job` `kind:"render"` (or a webhook on `render.completed`)
|
|
232
|
+
for the download URL. The output is brand-frozen: the kit's **intro/outro** bumper
|
|
233
|
+
the video, the **logo** bug sits in its corner, **motion** drives the overlay
|
|
234
|
+
entrances, and every `$brand:` color/font is resolved. Verify the output (sample
|
|
235
|
+
frames) before declaring done.
|
|
236
|
+
|
|
237
|
+
## Notes / honesty
|
|
238
|
+
|
|
239
|
+
- **The brand kit is the source of truth — edit it, re-render, re-theme.** Brand
|
|
240
|
+
values are resolved at render from the `brandKitId`-referenced kit, so a
|
|
241
|
+
`create_brand_kit` upsert (same `kitId`) re-themes every existing composition
|
|
242
|
+
that points at it. Don't bake brand hexes/fonts into clips.
|
|
243
|
+
- **Intro / outro / logo are NOT clips you author** — they live on the kit and
|
|
244
|
+
the engine places them at render (intro prepended, outro appended, logo painted
|
|
245
|
+
as a corner mark). A srcless/absent bumper or logo reserves/draws nothing (soft)
|
|
246
|
+
— it's just skipped, never an error.
|
|
247
|
+
- **`watermark` is accepted by `create_brand_kit` and persisted, but render does
|
|
248
|
+
NOT yet auto-composite the kit's watermark asset** (the only watermark painted
|
|
249
|
+
today is CueFrame's product mark). Set it for forward-compat, but custom
|
|
250
|
+
watermarks are not composited into the output yet — don't promise one.
|
|
251
|
+
- **Drive CueFrame directly.** Everything downstream of the capture — the brand,
|
|
252
|
+
the compose, the render — is CueFrame. Reach for an external generator only for
|
|
253
|
+
footage CueFrame genuinely can't produce — not to "make it look branded,"
|
|
254
|
+
which is the engine's job now.
|
|
255
|
+
- This recipe lives in a skill on purpose: the engine stays use-case-free; the
|
|
256
|
+
product opinions (what to extract, which overlays, how to brand) live here and
|
|
257
|
+
ship via `npx -y cueframe@0.5 install`.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "CueFrame — Brand demo recipe"
|
|
3
|
+
short_description: "Use when turning a local app into a brand-consistent product demo with…"
|
|
4
|
+
icon_small: "./assets/icon.svg"
|
|
5
|
+
icon_large: "./assets/icon.svg"
|
|
6
|
+
default_prompt: "Use $cueframe-brand-demo when turning a local app into a brand-consistent product demo with CueFrame — extract the brand straight from the repo (colors/fonts/logo/motion), capture a Playwright walkthrough of the running app, and author a branded, auto-zoomed demo whose intro/outro/logo/colors/fonts/motion are frozen by CueFrame's engine — e.g. \"make an on-brand demo of my app\", \"record my localhost and produce a branded launch video\"."
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<clipPath id="cf-favicon-clip"><circle cx="128" cy="128" r="118"/></clipPath>
|
|
3
|
+
<circle cx="128" cy="128" r="118" fill="#f7c948"/>
|
|
4
|
+
<g clip-path="url(#cf-favicon-clip)">
|
|
5
|
+
<path d="M88 128Q160 40 300-40" fill="none" stroke="#160f08" stroke-width="5"/>
|
|
6
|
+
<path d="M88 128Q170 60 310 20" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
7
|
+
<path d="M88 128Q180 80 316 70" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
8
|
+
<path d="M88 128Q186 110 320 110" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
9
|
+
<path d="M88 128Q186 146 320 146" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
10
|
+
<path d="M88 128Q180 176 316 186" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
11
|
+
<path d="M88 128Q170 196 310 236" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
12
|
+
<path d="M88 128Q160 216 300 296" fill="none" stroke="#160f08" stroke-width="5"/>
|
|
13
|
+
</g>
|
|
14
|
+
<circle cx="88" cy="128" r="20" fill="#160f08"/>
|
|
15
|
+
<circle cx="88" cy="128" r="8" fill="#f7c948"/>
|
|
16
|
+
</svg>
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cueframe-cli
|
|
3
|
+
description: Use when editing, clipping, or rendering video via the CueFrame CLI — e.g. "make a 9:16 short from this podcast", "pull the best moments out of this MP4", "render a clip", or any task that calls the `cueframe` binary. Also use when comparing CueFrame against direct-ffmpeg approaches.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# CueFrame CLI
|
|
7
|
+
|
|
8
|
+
## MCP is the primary surface — read this before using the CLI
|
|
9
|
+
|
|
10
|
+
**If you are an agent that can call tools, connect to CueFrame's MCP server instead of shelling
|
|
11
|
+
out to this CLI.** MCP is the supported, maintained integration surface: it hides transport and
|
|
12
|
+
contract details, its tools are generated from the same OpenAPI SSOT the CLI is, and it is where
|
|
13
|
+
new capability lands first. The `cueframe-connect` skill owns the setup for every host
|
|
14
|
+
(Claude Code, Claude/ChatGPT connectors, Cursor/Codex/VS Code/Windsurf/Zed, and the
|
|
15
|
+
no-account pay-per-call path) — load it rather than copying a connection command from here.
|
|
16
|
+
|
|
17
|
+
**Use this CLI when MCP is not available to you:** a terminal or CI job with no MCP host, a
|
|
18
|
+
scripted batch, or a human at a shell. It is a first-class path, not a deprecated one — but it is
|
|
19
|
+
the *second* thing to reach for.
|
|
20
|
+
|
|
21
|
+
**Do not hand-roll `curl` against `/v1`.** Raw REST is the fallback beneath the fallback: it is
|
|
22
|
+
where undocumented contract edges bite (components' runtime params were discovered that way), and
|
|
23
|
+
both MCP and this CLI exist so you do not have to.
|
|
24
|
+
|
|
25
|
+
## Overview
|
|
26
|
+
|
|
27
|
+
The `cueframe` CLI drives the CueFrame platform from the terminal. Optimized for agents — every command supports `--json` (NDJSON event stream) and the binary self-describes via `npx -y cueframe@0.5 describe --json`.
|
|
28
|
+
|
|
29
|
+
**Run it as `npx -y cueframe@0.5 …` — every command in this skill is written that way, and
|
|
30
|
+
that form is executable verbatim.** There is no `cueframe` on your PATH unless you put it
|
|
31
|
+
there: `npx -y cueframe@0.5 install` wires the MCP server and drops these skills, but npx
|
|
32
|
+
unpacks to an ephemeral cache, so it installs no binary. `npx` re-resolves the current
|
|
33
|
+
version on each call (~0.5s warm, ~5s cold), which also means these commands never go
|
|
34
|
+
stale. If you are running many in a row and want to skip that, `npm i -g cueframe` once
|
|
35
|
+
and drop the `npx -y ` prefix — but it needs a user-writable npm prefix (a default Linux
|
|
36
|
+
install fails `EACCES` on `/usr/local/lib/node_modules`), so it is an optimization, not
|
|
37
|
+
the documented path.
|
|
38
|
+
|
|
39
|
+
**The framework is three verbs:** `upload` (register media) → `composition put` (author the timeline) → `render` (→ MP4). The `Composition` is the contract — render takes the saved composition, nothing else. Everything domain-specific (AI clip suggestions, FCPXML/Premiere export) is a **use-case on-ramp** layered on top, not part of the core.
|
|
40
|
+
|
|
41
|
+
**Core principle — discover, don't guess.** Never author a composition from the
|
|
42
|
+
examples below alone. The live contract is `npx -y cueframe@0.5 schema composition` (prints
|
|
43
|
+
the real wire schema the server enforces); confirm any draft with
|
|
44
|
+
`npx -y cueframe@0.5 composition validate -b @file.json` BEFORE you render. Validation is
|
|
45
|
+
free and instant; a render is neither. The examples here are orientation — the
|
|
46
|
+
schema is the source of truth.
|
|
47
|
+
|
|
48
|
+
**Core principle:** once you are ON this path, drive everything through `cueframe` — never `curl` the v1 API around it, which invalidates the work and hides CLI bugs. (Choosing MCP over the CLI in the first place is not "going around it"; see the banner above.)
|
|
49
|
+
|
|
50
|
+
## Framework workflow (upload → compose → render)
|
|
51
|
+
|
|
52
|
+
The general path for any agent. Author the timeline yourself and render it — no
|
|
53
|
+
clip suggestion required.
|
|
54
|
+
|
|
55
|
+
For iteration, use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md).
|
|
56
|
+
Validate first, then use `preview_card` / `preview_component` for isolated graphics,
|
|
57
|
+
`preview_frame` for composition stills, or `preview_clip` for a motion window. Use the available
|
|
58
|
+
MCP tools or the CLI's `api` escape hatch with the live request contract. Full `render` is for
|
|
59
|
+
delivery, not checking each edit. CLI validation does not replace visual evidence.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# 0. Always use --json for agent-driven runs (NDJSON to stdout, no spinners).
|
|
63
|
+
# Commands run against production; auth is stored in ~/.cueframe/auth.json.
|
|
64
|
+
|
|
65
|
+
# 1. Register media (one or many — mixed video / image / audio).
|
|
66
|
+
npx -y cueframe@0.5 upload "/path/to/source.mp4" --json # → mediaItemId (process_complete)
|
|
67
|
+
|
|
68
|
+
# 2. Create a project (sets aspect/format).
|
|
69
|
+
npx -y cueframe@0.5 project create -n "promo" -a 9:16 --json # → projectId
|
|
70
|
+
|
|
71
|
+
# 3. Author the composition: tracks of clips (per-clip reframe/trim), optional
|
|
72
|
+
# captions (captions.segments), brandKitId. The composition is the SSOT.
|
|
73
|
+
# Discover the live schema, then validate the draft BEFORE saving/rendering:
|
|
74
|
+
npx -y cueframe@0.5 schema composition # → live wire schema
|
|
75
|
+
npx -y cueframe@0.5 composition validate -b @composition.json # → ✓ valid | per-field errors (no render)
|
|
76
|
+
npx -y cueframe@0.5 composition put <projectId> -b @composition.json # ETag auto
|
|
77
|
+
|
|
78
|
+
# 4. Render the saved composition to MP4. SSE-watches + downloads when done.
|
|
79
|
+
npx -y cueframe@0.5 render <projectId> -o ./out.mp4 --json
|
|
80
|
+
# → render_queued → render_progress* → render_complete
|
|
81
|
+
#
|
|
82
|
+
# `render` takes ONLY a projectId and renders the SAVED composition (tracks +
|
|
83
|
+
# captions). A clip suggestion is NOT required. Same project → same MP4 (idempotent).
|
|
84
|
+
# Captions: render reads composition.captions — put caption words there to caption
|
|
85
|
+
# a hand-authored composition; if absent, the clip is rendered without captions.
|
|
86
|
+
|
|
87
|
+
# Reattach to an in-flight render later (e.g. after disconnect):
|
|
88
|
+
npx -y cueframe@0.5 render watch <renderId> -p <projectId> -o ./out.mp4 --json
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Anatomy of a composition.json
|
|
92
|
+
|
|
93
|
+
This section orients you to the shape; the authoritative contract is
|
|
94
|
+
`npx -y cueframe@0.5 schema composition` (the live wire schema) — run it when a field is
|
|
95
|
+
unclear, and `npx -y cueframe@0.5 composition validate -b @file.json` to check a draft.
|
|
96
|
+
|
|
97
|
+
`composition put` takes the **bare** `Composition` object (no wrapper; the CLI POSTs
|
|
98
|
+
the `@file` verbatim and handles the ETag). Minimal valid shape:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"v": 1,
|
|
103
|
+
"format": { "aspectRatio": "9:16", "fps": 30 },
|
|
104
|
+
"tracks": [
|
|
105
|
+
{ "id": "v1", "kind": "video", "contents": [
|
|
106
|
+
{ "id": "c1", "startTime": 0, "duration": 10, "source": { "kind": "media", "mediaId": "<mediaId>" } }
|
|
107
|
+
] }
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
- **Required**: `v: 1`, `format.aspectRatio` (`16:9` | `9:16` | `1:1` | `4:5`), `tracks`.
|
|
113
|
+
- Tracks hold **`contents`** (not `clips`); each clip wraps a `source`. A clip's
|
|
114
|
+
`source.kind` must match the track `kind`: `media` → `video`/`image`/`audio`,
|
|
115
|
+
`overlay` → `overlay`, `effect` → `effect`.
|
|
116
|
+
- `source.kind`s: `media` (`mediaId` + optional `trim`/`reframe`/`volume`), `overlay`
|
|
117
|
+
(`primitiveId` + `params` + optional `zPlane`), `effect` (`primitiveId` + `params`).
|
|
118
|
+
- Times are **seconds** (`startTime`/`duration`/`trim`, and `reframe` `startSec`/`endSec`);
|
|
119
|
+
caption word times are **milliseconds**. `region`/`fit` (PiP/inset) are clip-level.
|
|
120
|
+
- Clips on one track can't overlap — simultaneous layers go on separate tracks.
|
|
121
|
+
- Optional top-level: `captions` (`segments[].words[]`), `brandKitId`, `markers`.
|
|
122
|
+
|
|
123
|
+
For full per-video-type examples (auto-zoom demo, PiP, split-screen, captions,
|
|
124
|
+
behind-subject title), see the `cueframe-product-video` skill.
|
|
125
|
+
|
|
126
|
+
## Render resolves expensive intents automatically — author, don't pre-bake
|
|
127
|
+
|
|
128
|
+
You author *intent* on the composition; `render` materializes the expensive
|
|
129
|
+
artifacts it implies. Nothing to pre-bake, no compose step required:
|
|
130
|
+
|
|
131
|
+
- An overlay with `"zPlane":"behind-subject"` → the person **matte** is baked
|
|
132
|
+
on-miss and the text is placed behind the speaker (shoulder-band anchor +
|
|
133
|
+
occlusion handled). Author it and render — it just works.
|
|
134
|
+
- A clip whose `reframe.focus` is `{mode:"face",faceId}` / `{mode:"active-speaker"}`
|
|
135
|
+
/ `{mode:"all-faces"}` → **subject detection** runs on-miss so the crop tracks the
|
|
136
|
+
real person. (`{mode:"point"}` / `{mode:"frame-center"}` need no detection.)
|
|
137
|
+
|
|
138
|
+
During this the SSE `render_progress` phases read
|
|
139
|
+
`resolving → baking-matte | detecting → rendering → complete` — the first behind/face
|
|
140
|
+
render of a source pays a one-time bake (cached after; re-renders are fast).
|
|
141
|
+
|
|
142
|
+
### Render error codes (fail-loud — render never ships a wrong frame silently)
|
|
143
|
+
|
|
144
|
+
| `code` | meaning | fix |
|
|
145
|
+
|---|---|---|
|
|
146
|
+
| `media_not_found` | a referenced `mediaId` doesn't exist or isn't your org's | reference media you uploaded |
|
|
147
|
+
| `media_not_ready` | the media has no file yet (still uploading/generating) | wait for `upload`'s `process_complete` |
|
|
148
|
+
| `source_dims_unknown` | a `reframe` clip's source has no width/height/fps yet | let the source finish processing before authoring a reframe |
|
|
149
|
+
| `content_anchor` | a clip's trim frames *different* footage than its captions show (wrong-footage) | align the trim window to the captioned moment |
|
|
150
|
+
| `behind_split_unsupported` | one media used under two *different* behind-subject windows | one behind window per media (split into separate clips/media) |
|
|
151
|
+
| `BehindMatteUnresolved` / `TrajectoryUnresolved` | the matte/detection bake produced no result for a behind/face clip | the source may have no detectable person; retry, or drop the behind/face intent |
|
|
152
|
+
|
|
153
|
+
## Clip-suggestion on-ramp ("podcast → short clip")
|
|
154
|
+
|
|
155
|
+
ONE use-case layered on the framework: the AI clip-finder picks a moment and
|
|
156
|
+
**authors a composition for you** (trim + speaker framing + captions sliced from
|
|
157
|
+
the transcript). Use it when you want CueFrame to choose the clip; otherwise author
|
|
158
|
+
the composition yourself (above).
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# 1. Upload + chain the AI clip pass.
|
|
162
|
+
npx -y cueframe@0.5 upload "/path/to/source.mp4" --analyze --json # mediaItemId + suggestions
|
|
163
|
+
# (or run it explicitly: npx -y cueframe@0.5 analyze <mediaItemId> --wait --json)
|
|
164
|
+
|
|
165
|
+
# 2. List clip suggestions (publicId sug_…, title, startMs/endMs, score).
|
|
166
|
+
npx -y cueframe@0.5 clips <mediaItemId> --json
|
|
167
|
+
|
|
168
|
+
# 3. Create a project AND author its composition from the chosen suggestion.
|
|
169
|
+
npx -y cueframe@0.5 project create -n "paul-klein-shorts" -a 9:16 --from-suggestion <sug_…> --json
|
|
170
|
+
# (or, on an existing project: npx -y cueframe@0.5 composition from-suggestion <projectId> -s <sug_…>)
|
|
171
|
+
|
|
172
|
+
# 4. Render — same framework verb as above.
|
|
173
|
+
npx -y cueframe@0.5 render <projectId> -o ./out.mp4 --json
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Both flows converge on `composition put` → `render`; the on-ramp just authors the
|
|
177
|
+
composition from a suggestion instead of you hand-writing it.
|
|
178
|
+
|
|
179
|
+
Pipe `--json` output through `jq -c 'select(.event=="…")'` to grab specific lifecycle events.
|
|
180
|
+
|
|
181
|
+
## Component authoring — fork a built-in primitive or scaffold your own
|
|
182
|
+
|
|
183
|
+
Own the motion-graphics components you render (shadcn-style): fork a built-in CueFrame
|
|
184
|
+
primitive as editable source, customize it, and render it on CueFrame — or scaffold a blank
|
|
185
|
+
one. The source lives in your repo under version control; CueFrame bakes it to a transparent
|
|
186
|
+
video and composites it (the shared renderer never runs your code).
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# 1. Scaffold a workspace (writes cueframe.json + cueframe/components/). Idempotent.
|
|
190
|
+
npx -y cueframe@0.5 init --json
|
|
191
|
+
|
|
192
|
+
# 2a. Scaffold a component in cueframe/components/<id>/ as owned, editable source.
|
|
193
|
+
npx -y cueframe@0.5 new component my-badge --json
|
|
194
|
+
|
|
195
|
+
# 2b. …or FORK a built-in: discover ids from the catalog (npx -y cueframe@0.5 api GET /v1/components),
|
|
196
|
+
# fetch that primitive's source with the `get_component_source` tool, and paste it into
|
|
197
|
+
# cueframe/components/my-badge/index.tsx as your starting point.
|
|
198
|
+
|
|
199
|
+
# 3. Edit cueframe/components/<id>/ — it's standard Remotion. The component is mounted
|
|
200
|
+
# ({ durationInFrames, params, assets, render }) at render; declare its v2 manifest.
|
|
201
|
+
|
|
202
|
+
# 4. Publish to CueFrame so it can render (uploads index.tsx as the component's tsxSource).
|
|
203
|
+
npx -y cueframe@0.5 push my-badge --json # one component
|
|
204
|
+
npx -y cueframe@0.5 sync --json # every component in the workspace
|
|
205
|
+
|
|
206
|
+
# 5. Reference the component id in your composition as a {kind:'component', componentId, props}
|
|
207
|
+
# clip, then render with the same verb. Preview a single component first via the MCP
|
|
208
|
+
# preview_component loop.
|
|
209
|
+
npx -y cueframe@0.5 render <projectId> -o ./out.mp4 --json
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Quick reference
|
|
213
|
+
|
|
214
|
+
| Need to… | Command |
|
|
215
|
+
|---|---|
|
|
216
|
+
| See every command + flags | `npx -y cueframe@0.5 describe --json` |
|
|
217
|
+
| Install/refresh managed skills | `npx -y cueframe@0.5 install` (shared `~/.agents/skills` and Claude `~/.claude/skills`; locally changed or untracked packages are preserved and reported) |
|
|
218
|
+
| List projects | `npx -y cueframe@0.5 list -n 50` |
|
|
219
|
+
| List your media | `npx -y cueframe@0.5 clips` (no mediaId arg) |
|
|
220
|
+
| Discover the live composition schema | `npx -y cueframe@0.5 schema composition` |
|
|
221
|
+
| Validate a draft (no save, no render) | `npx -y cueframe@0.5 composition validate -b @plan.json` |
|
|
222
|
+
| Read composition + ETag | `npx -y cueframe@0.5 composition get <projectId> --json` |
|
|
223
|
+
| Write composition | `npx -y cueframe@0.5 composition put <projectId> -b @plan.json` (ETag auto) |
|
|
224
|
+
| Export to Final Cut | `npx -y cueframe@0.5 export fcpxml <projectId> -s <sug> --wait -o cut.zip` |
|
|
225
|
+
| Export to Premiere | `npx -y cueframe@0.5 export premiere <projectId> -s <sug> --wait -o cut.zip` |
|
|
226
|
+
| Anything not wrapped | `npx -y cueframe@0.5 api GET /v1/... -i` (escape hatch, like `gh api`) |
|
|
227
|
+
| Validate a composition without mutating | `npx -y cueframe@0.5 composition validate -b @plan.json` |
|
|
228
|
+
|
|
229
|
+
## Auth
|
|
230
|
+
|
|
231
|
+
Commands run against production. Authenticate once:
|
|
232
|
+
|
|
233
|
+
- `npx -y cueframe@0.5 login` — OAuth device flow (laptops).
|
|
234
|
+
- `npx -y cueframe@0.5 auth <cf_live_… key>` — save a static API key (CI / headless).
|
|
235
|
+
|
|
236
|
+
Creds are stored in `~/.cueframe/auth.json`; the key can also come from the `CUEFRAME_API_KEY` env var.
|
|
237
|
+
|
|
238
|
+
## NDJSON event shape
|
|
239
|
+
|
|
240
|
+
Every `--json` line:
|
|
241
|
+
```json
|
|
242
|
+
{"_":0,"schemaVersion":"v1","ts":1779250551614,"event":"<verb>_<phase>", ...payload}
|
|
243
|
+
```
|
|
244
|
+
Phase lifecycle: `<verb>_prepare` → `<verb>_ready` → `<verb>_progress` (0+) → `<verb>_complete` | `error`. The `_:0` field is a pino formatter placeholder — ignore it.
|
|
245
|
+
|
|
246
|
+
Errors come as `{"event":"error", "phase":"<step>", "message":"...", "code":"...", "exitCode":N}` *and* a non-zero process exit. Read both.
|
|
247
|
+
|
|
248
|
+
## Common mistakes
|
|
249
|
+
|
|
250
|
+
| Mistake | Reality |
|
|
251
|
+
|---|---|
|
|
252
|
+
| Reaching for `curl …/v1/...` because the CLI didn't have a command | Use `npx -y cueframe@0.5 api METHOD /v1/...` — same auth, same JSON pipeline. |
|
|
253
|
+
| Polling for render completion with a sleep loop | `npx -y cueframe@0.5 render` already SSE-watches and exits when done. Use `render watch <id>` to reattach. |
|
|
254
|
+
| Skipping `--json` and trying to parse human output | Human output is for humans. Agents always use `--json`. |
|
|
255
|
+
| Hand-editing the composition without an ETag | `composition put` GETs the ETag for you; `from-suggestion` rebuilds from a clip. Don't hand-craft unless you have to. |
|
|
256
|
+
| Calling `npx -y cueframe@0.5 render <projectId> <suggestionId>` (old two-positional shape) | `render` takes ONLY a projectId; commander rejects the extra arg. It renders the SAVED composition — author it first via `composition put` (hand-author) or `project create --from-suggestion <sug>` (clip-finder on-ramp). |
|
|
257
|
+
| Assuming `render` needs a clip suggestion / that captions only come from a suggestion | No — `render` renders the saved composition directly; a suggestion is optional. Captions come from `composition.captions` (author them in the `put` JSON). The clip-suggestion on-ramp just fills those captions for you by slicing the transcript at author time. |
|
|
258
|
+
|
|
259
|
+
## When this skill applies (routing)
|
|
260
|
+
|
|
261
|
+
Route on **intent, not operation**. This is the path whenever the task is *creating a video* — captioning, reframing or keeping a subject framed, finding the best moment, composing or branding clips, rendering to a target aspect/format. A mechanical verb ("trim", "concat") *inside* a creative goal ("…into a captioned 9:16 short") is still this skill — CueFrame does the trim too. If a task is part mechanical and part creative, it's this skill. When unsure whether a video task needs CueFrame, it does — author it here; validate cost-free with `--dry-run` first.
|
|
262
|
+
|
|
263
|
+
Drop to raw `ffmpeg` only for a **single mechanical operation with zero creative or perceptual intent** — losslessly concatenating two finished files, transcoding a codec, extracting an audio track. That one carve-out aside, reach for `cueframe`.
|
|
264
|
+
|
|
265
|
+
Not this skill at all: inspecting internal backend state (that has its own operator tooling); changing the CLI's own source (that's CLI development, not usage).
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "CueFrame CLI"
|
|
3
|
+
short_description: "Use when editing, clipping, or rendering video via the CueFrame CLI — e.g.…"
|
|
4
|
+
icon_small: "./assets/icon.svg"
|
|
5
|
+
icon_large: "./assets/icon.svg"
|
|
6
|
+
default_prompt: "Use $cueframe-cli when editing, clipping, or rendering video via the CueFrame CLI — e.g. \"make a 9:16 short from this podcast\", \"pull the best moments out of this MP4\", \"render a clip\", or any task that calls the `cueframe` binary."
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<svg viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<clipPath id="cf-favicon-clip"><circle cx="128" cy="128" r="118"/></clipPath>
|
|
3
|
+
<circle cx="128" cy="128" r="118" fill="#f7c948"/>
|
|
4
|
+
<g clip-path="url(#cf-favicon-clip)">
|
|
5
|
+
<path d="M88 128Q160 40 300-40" fill="none" stroke="#160f08" stroke-width="5"/>
|
|
6
|
+
<path d="M88 128Q170 60 310 20" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
7
|
+
<path d="M88 128Q180 80 316 70" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
8
|
+
<path d="M88 128Q186 110 320 110" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
9
|
+
<path d="M88 128Q186 146 320 146" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
10
|
+
<path d="M88 128Q180 176 316 186" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
11
|
+
<path d="M88 128Q170 196 310 236" fill="none" stroke="#160f08" stroke-width="4.5"/>
|
|
12
|
+
<path d="M88 128Q160 216 300 296" fill="none" stroke="#160f08" stroke-width="5"/>
|
|
13
|
+
</g>
|
|
14
|
+
<circle cx="88" cy="128" r="20" fill="#160f08"/>
|
|
15
|
+
<circle cx="88" cy="128" r="8" fill="#f7c948"/>
|
|
16
|
+
</svg>
|