cueframe 0.4.3 → 0.4.5
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 +41 -1
- package/dist/analyze-243KHBHH.js +2 -0
- package/dist/chunk-MCQRX24V.js +2 -0
- package/dist/chunk-YKPEHNKM.js +12 -0
- package/dist/cueframe.js +109 -40
- package/{skills → dist/skills}/add-music-bed/SKILL.md +6 -16
- package/{skills → dist/skills}/brand-reel/SKILL.md +6 -16
- package/{skills → dist/skills}/clip-a-talking-head/SKILL.md +12 -17
- package/{skills → dist/skills}/composing-video/SKILL.md +20 -8
- package/{skills → dist/skills}/cueframe-brand-demo/SKILL.md +5 -0
- package/{skills → dist/skills}/cueframe-cli/SKILL.md +26 -3
- package/dist/skills/cueframe-component-authoring/SKILL.md +167 -0
- package/{skills → dist/skills}/cueframe-compose-loop/SKILL.md +38 -30
- package/dist/skills/cueframe-compose-loop/references/preview-workflow.md +37 -0
- package/dist/skills/cueframe-connect/SKILL.md +45 -0
- package/{skills → dist/skills}/cueframe-product-video/SKILL.md +19 -2
- package/dist/skills/cueframe-scene-shot/SKILL.md +66 -0
- package/{skills → dist/skills}/cueframe-storyboard/SKILL.md +6 -1
- package/{skills → dist/skills}/every-format-from-one-edit/SKILL.md +5 -16
- package/{skills → dist/skills}/extracting-brand-kits/SKILL.md +6 -3
- package/{skills → dist/skills}/launch-video/SKILL.md +5 -16
- package/{skills → dist/skills}/make-a-social-reel/SKILL.md +5 -15
- package/{skills → dist/skills}/rebrand-a-video/SKILL.md +5 -16
- package/{skills → dist/skills}/video-craft-standards/SKILL.md +6 -0
- package/dist/supportedAgents.js +1 -1
- package/package.json +18 -15
- package/dist/analyze-4EGOBMRV.js +0 -2
- package/dist/chunk-3QSA3EBY.js +0 -2
- package/dist/chunk-QKQNZIRI.js +0 -12
- package/skills/_connect.md +0 -12
- package/skills/cueframe-component-authoring/SKILL.md +0 -68
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cueframe-connect
|
|
3
|
+
description: Use when CueFrame is not connected yet, the user asks how to connect or authenticate CueFrame, or another CueFrame skill is about to call a tool and needs the one-time setup path for Claude Code, Claude, ChatGPT, Cursor, Codex, VS Code, Windsurf, Zed, Antigravity CLI, Copilot CLI, or an x402 wallet.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Connect CueFrame
|
|
7
|
+
|
|
8
|
+
Connect only when the first CueFrame tool call is imminent. Setup is a short detour, not a phase;
|
|
9
|
+
resume the user's original task immediately afterward.
|
|
10
|
+
|
|
11
|
+
- **Claude Code:** offer to run
|
|
12
|
+
`claude mcp add --transport http cueframe https://api.cueframe.ai/v1/mcp` — a browser
|
|
13
|
+
opens and the user clicks **Allow**. No API key.
|
|
14
|
+
- **Claude.ai / Claude Desktop:** Settings → Connectors → add a custom connector with
|
|
15
|
+
`https://api.cueframe.ai/v1/mcp`.
|
|
16
|
+
- **Other agents (Cursor, Codex, VS Code, Windsurf, Zed, Antigravity CLI, Copilot CLI, …):**
|
|
17
|
+
run `npx -y cueframe install` — it detects what is on the machine and wires each one.
|
|
18
|
+
- **ChatGPT:** the CLI cannot wire it because there is no local config to write; add
|
|
19
|
+
`https://api.cueframe.ai/v1/mcp` as a custom connector instead.
|
|
20
|
+
- **No account (pay per call):** connect
|
|
21
|
+
`https://api.cueframe.ai/v1/mcp/x402` — no sign-up or API key; priced calls settle
|
|
22
|
+
per call in USDC over x402 from the agent's wallet.
|
|
23
|
+
|
|
24
|
+
Do not ask the user to configure a model provider for CueFrame. This connection exposes CueFrame's
|
|
25
|
+
tools; the host agent keeps using its already-selected CueFrame Gateway, BYOK, or local model.
|
|
26
|
+
|
|
27
|
+
## Then confirm it works, before you plan anything
|
|
28
|
+
|
|
29
|
+
Connected is not the same as working, and finding out at the first *paid* call is the expensive
|
|
30
|
+
way. Two free read-only calls prove the whole path:
|
|
31
|
+
|
|
32
|
+
1. **Discover the surface.** List the tools your host now exposes. You should see the compose loop
|
|
33
|
+
(`new_composition`, `apply_composition`, `validate_composition`, `create_render`) alongside
|
|
34
|
+
discovery reads (`list_catalog`, `list_media`, `get_account`). There are also resources
|
|
35
|
+
(`cueframe://scene-shot` for 3D product shots) and workflow prompts — a flat tool list is not
|
|
36
|
+
the whole surface.
|
|
37
|
+
2. **Smoke-call `get_account`.** It takes no arguments, costs nothing, and answers the questions
|
|
38
|
+
worth knowing before you spend: which org the key is bound to, the plan, per-feature
|
|
39
|
+
entitlements and — the one that matters — `balance`, not `included`. CueFrame is credit-funded,
|
|
40
|
+
so rendering, generation, preview stills, the judge and the Director all draw on ONE shared
|
|
41
|
+
wallet. If `get_account` returns, authentication, routing and scope are all proven.
|
|
42
|
+
|
|
43
|
+
If a later call fails on scope, the error names the exact missing permission (for example
|
|
44
|
+
`billing:read`, which `get_usage` needs and a creative-only key will not have). Mint a key with
|
|
45
|
+
that scope rather than guessing at the surface.
|
|
@@ -8,8 +8,14 @@ description: Use when turning a screen recording (with cursor/click events) into
|
|
|
8
8
|
A **use-case recipe**, not new framework surface. CueFrame's engine only knows
|
|
9
9
|
primitives (`upload` → `composition put` → `render`, the `reframe` viewport, the
|
|
10
10
|
overlay/effect primitives). This skill is the *judgment* on top: how to turn a
|
|
11
|
-
captured walkthrough into a product video that looks good.
|
|
12
|
-
|
|
11
|
+
captured walkthrough into a product video that looks good. This tells you *what*
|
|
12
|
+
to author, not how to transport it.
|
|
13
|
+
|
|
14
|
+
**Drive the primitives over MCP if you can call tools** (`new_composition` /
|
|
15
|
+
`apply_composition` / `validate_composition` / `create_render` — see the
|
|
16
|
+
`cueframe-connect` skill for the one-line setup). The `npx -y cueframe …` commands
|
|
17
|
+
written out below are the same operations for a terminal or CI job with no MCP
|
|
18
|
+
host; see the `cueframe-cli` skill.
|
|
13
19
|
|
|
14
20
|
## The pipeline
|
|
15
21
|
|
|
@@ -68,6 +74,12 @@ product demo:
|
|
|
68
74
|
| device/browser frame | `device-mockup-zoom` / `browser-flow` | overlay |
|
|
69
75
|
| captions (if narrated) | the top-level `captions` field | — |
|
|
70
76
|
| finish/look | `color-grade` + `vignette` | effect |
|
|
77
|
+
| several cells sharing space that should reflow (feature grid, rail + fluid content) | author a component on `FlexLayout` from `@cueframe/animate` (see `cueframe-component-authoring`) | overlay (authored) |
|
|
78
|
+
|
|
79
|
+
Static PiP / split-screen is `region` + `fit` on the clips (EX3 / EX4). Cells that must
|
|
80
|
+
**reflow together** or hold mixed content are one authored component built on `FlexLayout`;
|
|
81
|
+
the catalog `flex-layout` primitive is that same layout, but a bare composition overlay has
|
|
82
|
+
no children, so on its own it draws only the rig outlines.
|
|
71
83
|
|
|
72
84
|
A primitive is the `source` of a clip; the clip wraps it with `id`/`startTime`/`duration`:
|
|
73
85
|
- Overlay clip (on a `kind:"overlay"` track): `{ "id":"t1", "startTime":1, "duration":3, "source":{ "kind":"overlay", "primitiveId":"lower-third", "params":{…}, "zPlane":"front" } }`.
|
|
@@ -77,6 +89,11 @@ Simultaneous overlays go on **separate tracks** — clips on one track can't ove
|
|
|
77
89
|
|
|
78
90
|
## 5. Render
|
|
79
91
|
|
|
92
|
+
First use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md):
|
|
93
|
+
check framing with `preview_frame` and click/zoom timing with an affected-window `preview_clip`.
|
|
94
|
+
For a small revision, verify that change and relevant regressions without exporting the whole film.
|
|
95
|
+
When delivering the finished video:
|
|
96
|
+
|
|
80
97
|
`npx -y cueframe render <projectId> -o out.mp4 --json`. Verify the output (ffprobe +
|
|
81
98
|
sample frames) before declaring done.
|
|
82
99
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cueframe-scene-shot
|
|
3
|
+
description: Author a CueFrame 3D world-object shot as canonical SceneShotSpecV2 JSON. Use for slabs, pages, phones, laptops, captured component or video surfaces, world text, camera motion, studio lighting, focus, and product-shot recipes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# CueFrame scene shots
|
|
7
|
+
|
|
8
|
+
Use `scene.add` and `scene.update` through `apply_composition`. Author the scene JSON; CueFrame owns the generated wrapper, preparation, resource admission, previews, and export.
|
|
9
|
+
|
|
10
|
+
Before authoring, read `cueframe://scene-shot`. It serves the canonical generated `SceneShotSpecV2` schema, exact operation contracts, supported brand tokens, refusal rules, and a copyable nested slab-and-page recipe. Do not infer fields from an older example.
|
|
11
|
+
|
|
12
|
+
## Workflow
|
|
13
|
+
|
|
14
|
+
Use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md)
|
|
15
|
+
for the available hosted/local lane. Inspect affected camera/focus/entrance windows in motion,
|
|
16
|
+
not only keyframes. A scene tweak can finish with preview evidence; export for final delivery.
|
|
17
|
+
|
|
18
|
+
1. Create or open a composition at the target aspect and FPS.
|
|
19
|
+
2. Register every image or video source. Capture-backed component surfaces use an exact component id, source version id, capture frame, layout, and optional bake scale.
|
|
20
|
+
3. Read `cueframe://scene-shot`, copy its `world-objects` recipe, and replace placeholder ids and copy.
|
|
21
|
+
4. Send `apply_composition` with `dry_run: true`. Fix the exact reported field path.
|
|
22
|
+
5. Apply the same batch for real. Preview the first frame, object entrances, focus transitions, and the last frame.
|
|
23
|
+
6. Revise with `scene.update`; do not hand-edit a generated wrapper.
|
|
24
|
+
7. Render only after surfaces report ready and the previews show the intended pixels.
|
|
25
|
+
|
|
26
|
+
## Ownership boundaries
|
|
27
|
+
|
|
28
|
+
The composition owns clip start, duration, ordering, cuts, and transitions. The scene owns objects, camera, environment, backdrop, post effects, constraints, and normalized animation. Scene clips occupy a dedicated full-frame front overlay track. Outer region, position, scale, rotation, fit, clip effects, and internal fades are refused because they would create two transform or timing owners.
|
|
29
|
+
|
|
30
|
+
`referenceSize` must have the same aspect ratio as the composition. Coordinates are reference pixels with origin at frame center, +X right, +Y down, and +Z toward the viewer. Equal-aspect outputs scale uniformly.
|
|
31
|
+
|
|
32
|
+
Animation keyframe `at` is normalized over clip duration. Easing belongs to the keyframe it arrives at. The first keyframe has no easing; each later keyframe supplies `linear`, `hold`, or cubic `bezier` easing. Topology, bindings, text content, fonts, material roles, and object kind remain static within a shot.
|
|
33
|
+
|
|
34
|
+
## Objects and surfaces
|
|
35
|
+
|
|
36
|
+
V2 supports nested `group` layers and canonical `slab`, `page`, `phone`, `laptop`, and `text` layers. Use each object's declared surface slot:
|
|
37
|
+
|
|
38
|
+
- `source: "image"` binds an admitted PNG, JPEG, or WebP through the outer `assets` map.
|
|
39
|
+
- `source: "component"` captures an immutable component source at the declared frame and layout. Omitted `bakeScale` lets preparation select 2× or 3×; an explicit insufficient scale refuses.
|
|
40
|
+
- `source: "video"` binds an admitted media id with frame-addressed start/end facts. Video decoding and committed-frame readiness are sealed before drawing.
|
|
41
|
+
- `source: "color"` supplies an unlit solid surface.
|
|
42
|
+
|
|
43
|
+
Never insert a URL, raw HTML, shader source, or placeholder art into a surface. Every required slot must resolve before capture. UI surfaces and world text are unlit and color-managed; bodies use declared physical material roles. Invisible objects do not write depth.
|
|
44
|
+
|
|
45
|
+
World text participates in camera, depth, occlusion, and focus. Screen text stays fixed above the world result. Both are line-authored with no automatic reflow. Every exact font family, weight, and style used by base or emphasized runs must be admitted.
|
|
46
|
+
|
|
47
|
+
## Lighting and post
|
|
48
|
+
|
|
49
|
+
Choose the generated studio environment for named studio profiles or `{kind:"photographic-studio-v1"}` for the fixed photographic recipe. Arbitrary HDR fields are refused. Backdrops may be transparent, solid, linear, or radial. Focus is per-pixel world depth; sample the actual object face rather than its layer origin when choosing distance and range.
|
|
50
|
+
|
|
51
|
+
Brand tokens are allowed only in schema-declared color and font-family fields. Read the token enums from the resource. A font token resolves the family only; authored weight and style still require exact admitted bytes.
|
|
52
|
+
|
|
53
|
+
## Limits and refusals
|
|
54
|
+
|
|
55
|
+
The contract admits at most 32 layers, 4 devices, 16 distinct image slots, 256 keyframes per channel, and 2048 keyframes per shot. Raw HTML, custom shader properties, imported GLB models, arbitrary external HDR environments, skeletal animation, and physics are unsupported. Unknown keys, duplicate ids, missing bindings, non-finite values, aspect mismatch, budget overflow, and unsupported capabilities fail with a named code and exact path.
|
|
56
|
+
|
|
57
|
+
Composition-level global wrap effects do not reach front-overlay scene clips. Author grain, vignette, focus, backdrop, and environment inside the scene.
|
|
58
|
+
|
|
59
|
+
## Delivery checks
|
|
60
|
+
|
|
61
|
+
- The rendered subject is a real object with a real admitted surface.
|
|
62
|
+
- Every key entrance, reflection sweep, screen update, and focus transition was previewed.
|
|
63
|
+
- Device and slab bodies receive the intended light while UI colors remain unchanged.
|
|
64
|
+
- Text uses the intended admitted face and remains legible.
|
|
65
|
+
- The output aspect matches the authored reference aspect.
|
|
66
|
+
- The final response identifies the composition, render, source provenance, and any intentional unsupported boundary.
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cueframe-storyboard
|
|
3
|
-
description:
|
|
3
|
+
description: >-
|
|
4
|
+
Use BEFORE composing when starting a NEW video from scratch and you need to plan its structure — turning a rough ask ("make a launch video", "30s promo", "an explainer for our API") into a concrete beat flow. Owns the intake + storyboard step: interview the user for the brief, resolve the format from the platform, and lay out the hook→body→cta beats that drive the compose workflow. Triggers on "plan a video", "storyboard", "structure this video", "outline the video", "where do I start", or any new-video ask that has no structure yet. Hand off to composing-video for per-beat craft.
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# CueFrame Storyboard: brief → flow
|
|
7
8
|
|
|
9
|
+
This is a new-video planning workflow. For revisions to an approved plan, preserve its structure
|
|
10
|
+
and use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md)
|
|
11
|
+
to verify the requested change; do not restart intake, Director authoring, or final export by default.
|
|
12
|
+
|
|
8
13
|
> **The bar:** the `video-craft-standards` skill (GET /v1/skills/video-craft-standards) defines DONE for every artifact class — per-class MUST checklists and kill criteria. Read it before composing and score against it before rendering. When this skill and that document disagree, the standards win.
|
|
9
14
|
|
|
10
15
|
|
|
@@ -13,22 +13,7 @@ are made once; the formats are a job, not a re-edit.
|
|
|
13
13
|
## Before you start
|
|
14
14
|
|
|
15
15
|
Confirm which master and which target platforms before setup. When the first tool call
|
|
16
|
-
approaches and CueFrame isn't connected
|
|
17
|
-
|
|
18
|
-
<!-- cueframe:connect -->
|
|
19
|
-
- **Claude Code:** offer to run
|
|
20
|
-
`claude mcp add --transport http cueframe https://api.cueframe.ai/v1/mcp` — a browser
|
|
21
|
-
opens and the user clicks **Allow**. No API key.
|
|
22
|
-
- **Claude.ai / Claude Desktop:** Settings → Connectors → add a custom connector with
|
|
23
|
-
`https://api.cueframe.ai/v1/mcp`.
|
|
24
|
-
- **Other agents (Cursor, Codex, VS Code, Windsurf, Zed, Gemini CLI, Copilot CLI, …):**
|
|
25
|
-
run `npx -y cueframe install` — it detects what is on the machine and wires each one.
|
|
26
|
-
- **ChatGPT:** the CLI cannot wire it (there is no local config to write) — add
|
|
27
|
-
`https://api.cueframe.ai/v1/mcp` as a custom connector instead.
|
|
28
|
-
- **No account at all (pay-per-call):** connect
|
|
29
|
-
`https://api.cueframe.ai/v1/mcp/x402` — no sign-up, no API key; priced calls
|
|
30
|
-
settle per-call in USDC over x402 from the agent's wallet.
|
|
31
|
-
<!-- /cueframe:connect -->
|
|
16
|
+
approaches and CueFrame isn't connected, load **`cueframe-connect`** and follow it once.
|
|
32
17
|
|
|
33
18
|
Then straight to deriving — this whole job is minutes when the master is good.
|
|
34
19
|
|
|
@@ -44,6 +29,10 @@ Then straight to deriving — this whole job is minutes when the master is good.
|
|
|
44
29
|
|
|
45
30
|
## Workflow
|
|
46
31
|
|
|
32
|
+
Use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md)
|
|
33
|
+
for each affected sibling. Check motion as well as layout where the new crop changes visibility.
|
|
34
|
+
A correction to one sibling does not require rendering the master or the other unchanged siblings.
|
|
35
|
+
|
|
47
36
|
1. **Verify the master is actually done.** It passed its class checklist, its audio was
|
|
48
37
|
decided, its render was approved. Deriving from a draft ships the draft's flaws four times.
|
|
49
38
|
2. **Derive each sibling.** `derive_composition` per target aspect — the reframe is
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: extracting-brand-kits
|
|
3
|
-
description:
|
|
3
|
+
description: >-
|
|
4
|
+
Use when the user says "make my video look like THIS" with a reference video, screenshots, or a moodboard — build a CueFrame brand kit FROM that inspiration so every subsequent compose speaks its visual language. Owns the extraction step: sample the reference's graphics-bearing frames, upload them as exemplars, reproduce each recurring motif as an authored graphic verified against the reference, and upsert the kit with the full language payload. Triggers on "match this style", "like this reference", "use this video as inspiration", "extract a brand kit", "moodboard". Hand off to cueframe-storyboard/composing-video once the kit is bound.
|
|
4
5
|
---
|
|
5
6
|
|
|
6
7
|
# Extracting brand kits: reference pixels → a kit the engine honors
|
|
@@ -86,8 +87,10 @@ verify it against the exemplar BY LOOKING:
|
|
|
86
87
|
through `tokens` with `$brand:` refs (e.g. `"line": "$brand:colors.accent"`, referenced in CSS
|
|
87
88
|
as `var(--cf-line)`) so the kit's identity re-themes it. No `<script>`, no `@keyframes` (inert —
|
|
88
89
|
motion is step 5).
|
|
89
|
-
3.
|
|
90
|
-
component) and compare
|
|
90
|
+
3. Preview the isolated card with `preview_card` (or `preview_component` for an authored
|
|
91
|
+
component) and compare against the exemplar side by side. Use `cueframe-compose-loop`'s
|
|
92
|
+
[preview workflow](../cueframe-compose-loop/references/preview-workflow.md) for saved-context
|
|
93
|
+
checks and motion windows. Fix the largest visible
|
|
91
94
|
difference. Repeat — **cap 3 iterations**, keep the best.
|
|
92
95
|
4. Record `diffScore` (your honest 0–1 same-language judgment) and `coverage`:
|
|
93
96
|
`"reproduced"` (≥0.8) or `"approximated"`.
|
|
@@ -12,22 +12,7 @@ doing the real thing, builds under a bed or narration, and lands on a single CTA
|
|
|
12
12
|
## Before you start
|
|
13
13
|
|
|
14
14
|
Nail the payoff sentence and collect the captures before any setup. When the first tool call
|
|
15
|
-
approaches and CueFrame isn't connected
|
|
16
|
-
|
|
17
|
-
<!-- cueframe:connect -->
|
|
18
|
-
- **Claude Code:** offer to run
|
|
19
|
-
`claude mcp add --transport http cueframe https://api.cueframe.ai/v1/mcp` — a browser
|
|
20
|
-
opens and the user clicks **Allow**. No API key.
|
|
21
|
-
- **Claude.ai / Claude Desktop:** Settings → Connectors → add a custom connector with
|
|
22
|
-
`https://api.cueframe.ai/v1/mcp`.
|
|
23
|
-
- **Other agents (Cursor, Codex, VS Code, Windsurf, Zed, Gemini CLI, Copilot CLI, …):**
|
|
24
|
-
run `npx -y cueframe install` — it detects what is on the machine and wires each one.
|
|
25
|
-
- **ChatGPT:** the CLI cannot wire it (there is no local config to write) — add
|
|
26
|
-
`https://api.cueframe.ai/v1/mcp` as a custom connector instead.
|
|
27
|
-
- **No account at all (pay-per-call):** connect
|
|
28
|
-
`https://api.cueframe.ai/v1/mcp/x402` — no sign-up, no API key; priced calls
|
|
29
|
-
settle per-call in USDC over x402 from the agent's wallet.
|
|
30
|
-
<!-- /cueframe:connect -->
|
|
15
|
+
approaches and CueFrame isn't connected, load **`cueframe-connect`** and follow it once.
|
|
31
16
|
|
|
32
17
|
Keep the momentum — the video plan is the hard part, the connection is not.
|
|
33
18
|
|
|
@@ -44,6 +29,10 @@ Keep the momentum — the video plan is the hard part, the connection is not.
|
|
|
44
29
|
|
|
45
30
|
## Workflow
|
|
46
31
|
|
|
32
|
+
Use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md)
|
|
33
|
+
for layout and motion evidence. A follow-up tweak preserves the approved brief; inspect the
|
|
34
|
+
affected window and regressions without automatically rerunning the full-film judge or export.
|
|
35
|
+
|
|
47
36
|
1. **Import the real surface.** `import_media` every capture; wait for ready;
|
|
48
37
|
`get_media_context` for what each recording actually shows (and the transcript, if narrated
|
|
49
38
|
footage exists). Inventory the strongest 3–5 real moments before writing a beat.
|
|
@@ -13,21 +13,7 @@ on a deliberate beat — with a download link, not a "done".
|
|
|
13
13
|
|
|
14
14
|
Don't stall the conversation on setup — get the footage, the hook, and the tone agreed first.
|
|
15
15
|
When the first real tool call is imminent and CueFrame isn't connected:
|
|
16
|
-
|
|
17
|
-
<!-- cueframe:connect -->
|
|
18
|
-
- **Claude Code:** offer to run
|
|
19
|
-
`claude mcp add --transport http cueframe https://api.cueframe.ai/v1/mcp` — a browser
|
|
20
|
-
opens and the user clicks **Allow**. No API key.
|
|
21
|
-
- **Claude.ai / Claude Desktop:** Settings → Connectors → add a custom connector with
|
|
22
|
-
`https://api.cueframe.ai/v1/mcp`.
|
|
23
|
-
- **Other agents (Cursor, Codex, VS Code, Windsurf, Zed, Gemini CLI, Copilot CLI, …):**
|
|
24
|
-
run `npx -y cueframe install` — it detects what is on the machine and wires each one.
|
|
25
|
-
- **ChatGPT:** the CLI cannot wire it (there is no local config to write) — add
|
|
26
|
-
`https://api.cueframe.ai/v1/mcp` as a custom connector instead.
|
|
27
|
-
- **No account at all (pay-per-call):** connect
|
|
28
|
-
`https://api.cueframe.ai/v1/mcp/x402` — no sign-up, no API key; priced calls
|
|
29
|
-
settle per-call in USDC over x402 from the agent's wallet.
|
|
30
|
-
<!-- /cueframe:connect -->
|
|
16
|
+
load **`cueframe-connect`** and follow it once.
|
|
31
17
|
|
|
32
18
|
Thirty seconds, then straight back to the reel — treat it as a detour, never a gate.
|
|
33
19
|
|
|
@@ -42,6 +28,10 @@ Thirty seconds, then straight back to the reel — treat it as a detour, never a
|
|
|
42
28
|
|
|
43
29
|
## Workflow
|
|
44
30
|
|
|
31
|
+
Use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md)
|
|
32
|
+
for layout and motion evidence. A follow-up tweak preserves the approved brief; inspect the
|
|
33
|
+
affected window and regressions without automatically rerunning the full-film judge or export.
|
|
34
|
+
|
|
45
35
|
|
|
46
36
|
0. **Find the claim (before anything else).** Interrogate the brand/material
|
|
47
37
|
for its tension — what it believes that its category doesn't — and write
|
|
@@ -13,22 +13,7 @@ not the whole video.
|
|
|
13
13
|
## Before you start
|
|
14
14
|
|
|
15
15
|
Collect the new brand's facts first — the swap itself is fast. When the first tool call
|
|
16
|
-
approaches and CueFrame isn't connected
|
|
17
|
-
|
|
18
|
-
<!-- cueframe:connect -->
|
|
19
|
-
- **Claude Code:** offer to run
|
|
20
|
-
`claude mcp add --transport http cueframe https://api.cueframe.ai/v1/mcp` — a browser
|
|
21
|
-
opens and the user clicks **Allow**. No API key.
|
|
22
|
-
- **Claude.ai / Claude Desktop:** Settings → Connectors → add a custom connector with
|
|
23
|
-
`https://api.cueframe.ai/v1/mcp`.
|
|
24
|
-
- **Other agents (Cursor, Codex, VS Code, Windsurf, Zed, Gemini CLI, Copilot CLI, …):**
|
|
25
|
-
run `npx -y cueframe install` — it detects what is on the machine and wires each one.
|
|
26
|
-
- **ChatGPT:** the CLI cannot wire it (there is no local config to write) — add
|
|
27
|
-
`https://api.cueframe.ai/v1/mcp` as a custom connector instead.
|
|
28
|
-
- **No account at all (pay-per-call):** connect
|
|
29
|
-
`https://api.cueframe.ai/v1/mcp/x402` — no sign-up, no API key; priced calls
|
|
30
|
-
settle per-call in USDC over x402 from the agent's wallet.
|
|
31
|
-
<!-- /cueframe:connect -->
|
|
16
|
+
approaches and CueFrame isn't connected, load **`cueframe-connect`** and follow it once.
|
|
32
17
|
|
|
33
18
|
Then back to the brand — most of this job is a kit definition and an audit.
|
|
34
19
|
|
|
@@ -46,6 +31,10 @@ Then back to the brand — most of this job is a kit definition and an audit.
|
|
|
46
31
|
|
|
47
32
|
## Workflow
|
|
48
33
|
|
|
34
|
+
Use `cueframe-compose-loop`'s [preview workflow](../cueframe-compose-loop/references/preview-workflow.md)
|
|
35
|
+
for affected graphics and saved-composition checks. Inspect motion if the kit changes timing;
|
|
36
|
+
keep the final re-render separate from previews used to resolve individual styling corrections.
|
|
37
|
+
|
|
49
38
|
1. **Pin the new brand as a kit.** `extract_brand_kit` or `create_brand_kit`; show the kit and
|
|
50
39
|
get sign-off — it is the contract. Then bind it: upsert in place (same kit id) to restyle,
|
|
51
40
|
or point the project at the new kit for a white-label. The kit lives on the PROJECT, not on
|
|
@@ -40,6 +40,12 @@ your one final render.
|
|
|
40
40
|
|
|
41
41
|
## Cross-cutting rules (every artifact)
|
|
42
42
|
|
|
43
|
+
These are final-artifact criteria, not a requirement to re-plan or export after every tweak.
|
|
44
|
+
For scoped corrections and preview selection, use `cueframe-compose-loop`'s
|
|
45
|
+
[preview workflow](../cueframe-compose-loop/references/preview-workflow.md). Inspect continuous
|
|
46
|
+
motion and listen to affected audio, not only stills or judge scores. Keep the user's explicit
|
|
47
|
+
scope and acceptance criteria; approved simulated UI is not evidence of a real product capture.
|
|
48
|
+
|
|
43
49
|
- **MUST** Brand/text graphics are AUTHORED — `kind:"card"` HTML (your
|
|
44
50
|
typography, layout, palette-as-fields) shelled with `applyMotionPreset`,
|
|
45
51
|
or a custom component. Catalog text primitives are for utility only.
|
package/dist/supportedAgents.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import"./chunk-
|
|
2
|
+
import"./chunk-MCQRX24V.js";import{agents as c}from"add-mcp";var o=["claude-code","cursor","codex","vscode","windsurf","zed","antigravity","github-copilot-cli"];function s(e){let t=o.indexOf(e);return t===-1?o.length:t}var a=Object.entries(c).filter(([e,t])=>e!=="gemini-cli"&&(t.supportedTransports??[]).includes("http")).map(([e,t])=>({id:e,label:t.displayName??e})).sort((e,t)=>s(e.id)-s(t.id)||e.id.localeCompare(t.id));function p(e=4){let t=a.map(i=>i.label),n=t.slice(0,e).join(", "),r=t.length-e;return r>0?`${n} \u2014 and ${r} more`:n}export{a as SUPPORTED_AGENTS,p as supportedAgentsSentence};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cueframe",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "Agent-native CLI for CueFrame — author compositions and render video from the terminal (early-access preview).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cueframe",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"remotion"
|
|
14
14
|
],
|
|
15
15
|
"homepage": "https://docs.cueframe.ai",
|
|
16
|
-
"author": "CueFrame Inc.",
|
|
16
|
+
"author": "CueFrame, Inc.",
|
|
17
17
|
"license": "AGPL-3.0-only",
|
|
18
18
|
"type": "module",
|
|
19
19
|
"bin": {
|
|
@@ -22,30 +22,38 @@
|
|
|
22
22
|
"main": "dist/cueframe.js",
|
|
23
23
|
"files": [
|
|
24
24
|
"dist",
|
|
25
|
-
"skills",
|
|
26
25
|
"README.md"
|
|
27
26
|
],
|
|
28
27
|
"engines": {
|
|
29
|
-
"node": ">=
|
|
28
|
+
"node": ">=24"
|
|
30
29
|
},
|
|
31
30
|
"publishConfig": {
|
|
32
31
|
"access": "public"
|
|
33
32
|
},
|
|
34
33
|
"dependencies": {
|
|
35
|
-
"add-mcp": "^
|
|
36
|
-
"better-auth": "1.
|
|
34
|
+
"add-mcp": "^2.4.0",
|
|
35
|
+
"better-auth": "1.6.22",
|
|
37
36
|
"commander": "^13.1.0",
|
|
38
37
|
"open": "^10.1.0",
|
|
39
38
|
"ora": "^8.2.0",
|
|
40
39
|
"pino": "^10.3.1",
|
|
41
40
|
"typescript": "^5.9.3"
|
|
42
41
|
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "node ../../apps/director-agent/scripts/generate-marketplace.mjs && node ../../apps/director-agent/scripts/validate-agent.mjs && tsup && node scripts/copy-agent-skills.mjs",
|
|
44
|
+
"check": "tsc --noEmit",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"prepublishOnly": "npm run build"
|
|
47
|
+
},
|
|
43
48
|
"devDependencies": {
|
|
44
|
-
"@
|
|
49
|
+
"@cueframe/component-runtime": "workspace:*",
|
|
50
|
+
"@cueframe/composition": "workspace:*",
|
|
51
|
+
"@cueframe/sdk": "workspace:*",
|
|
52
|
+
"zod": "^4.5.4",
|
|
53
|
+
"@types/node": "^24.0.0",
|
|
45
54
|
"tsup": "^8.5.1",
|
|
46
55
|
"vitest": "^4.1.2",
|
|
47
|
-
"@cueframe/
|
|
48
|
-
"@cueframe/primitives": "0.1.0"
|
|
56
|
+
"@cueframe/primitives": "workspace:*"
|
|
49
57
|
},
|
|
50
58
|
"repository": {
|
|
51
59
|
"type": "git",
|
|
@@ -54,10 +62,5 @@
|
|
|
54
62
|
},
|
|
55
63
|
"bugs": {
|
|
56
64
|
"url": "https://github.com/cueframe-ai/cueframe/issues"
|
|
57
|
-
},
|
|
58
|
-
"scripts": {
|
|
59
|
-
"build": "tsup",
|
|
60
|
-
"check": "tsc --noEmit",
|
|
61
|
-
"test": "vitest run"
|
|
62
65
|
}
|
|
63
|
-
}
|
|
66
|
+
}
|
package/dist/analyze-4EGOBMRV.js
DELETED
package/dist/chunk-3QSA3EBY.js
DELETED
package/dist/chunk-QKQNZIRI.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import{a as y}from"./chunk-3QSA3EBY.js";var u=class extends Error{status;code;details;requestId;constructor(o,t,n){super(t.message),this.name="ApiError",this.status=o,this.code=t.code,this.details=t.details,this.requestId=n}},P=class extends Error{url;timeoutMs;constructor(o,t){super(`Request timed out after ${t}ms: ${o}`),this.name="TimeoutError",this.url=o,this.timeoutMs=t}},k=class extends Error{url;constructor(o,t){super(`Request failed before a response: ${o}`,{cause:t}),this.name="NetworkError",this.url=o}},l={baseUrl:""};function T(e){return l={timeoutMs:3e4,...e},l}function b(){return l}function Ve(e,o){return/^https?:\/\//.test(o)?o:e.replace(/\/$/,"")+(o.startsWith("/")?o:`/${o}`)}async function j(e,o={}){if(!l.baseUrl)throw new Error("@cueframe/sdk: createClient({baseUrl}) must be called before issuing requests.");let t=l.fetch??fetch,n=Ve(l.baseUrl,e),s=new Headers({accept:"application/json"});for(let[a,f]of Object.entries(l.headers??{}))s.set(a,f);o.headers&&new Headers(o.headers).forEach((a,f)=>s.set(f,a)),l.apiKey&&!s.has("authorization")&&s.set("authorization",`Bearer ${l.apiKey}`);let i=l.timeoutMs??3e4,p=new AbortController,c=setTimeout(()=>p.abort(),i),d=o.signal?AbortSignal.any([o.signal,p.signal]):p.signal;try{let a=await t(n,{...o,headers:s,signal:d}),f={};a.headers.forEach((g,R)=>{f[R.toLowerCase()]=g});let x=null;if(a.status!==204)if((a.headers.get("content-type")??"").includes("application/json"))try{x=await a.json()}catch{x=null}else x=await a.text();return{status:a.status,statusText:a.statusText,headers:f,body:x,requestId:f["x-request-id"]}}catch(a){throw o.signal?.aborted?a:p.signal.aborted?new P(n,i):new k(n,a)}finally{clearTimeout(c)}}async function r(e,o={}){let t=await j(e,o);if(t.status>=400){let n;throw t.body&&typeof t.body=="object"&&"error"in t.body?n=t.body.error??{code:"unknown",message:t.statusText}:n={code:"unknown",message:t.statusText},new u(t.status,n,t.requestId)}if(t.status!==204)return t.body}var He={unauthorized:"The API key is invalid or expired for this target. Run `cueframe login` (or `cueframe auth <api-key>`), and check the key matches the target environment.",forbidden:"The key's scopes don't allow this operation. Create a key with the needed preset (`cueframe keys create --preset ...`) or use a key with wider scopes.",not_found:"No such resource in this org (cross-org access also reads as 404). Check the id, or enumerate with the matching list command/tool.",media_not_ready:"Media is still processing. Wait for the `media.transcribed` webhook or retry after ~30s.",suggestions_already_complete:"Suggestions already exist for this media item. To re-run, call DELETE /v1/media/:id/suggestions first to reset state.",precondition_required:"Fetch the resource with GET first to obtain its ETag, then resend the write with `If-Match: <etag>`. `cueframe composition get` returns one for you.",stale_etag:"Resource was modified since your last GET \u2014 `details.currentEtag` is the value to thread next. Re-GET (or run `cueframe composition get`) and rebase your edits before retrying.",conflict:"ETag mismatch \u2014 the resource was modified since your last GET. Re-fetch and merge before retrying.",media_in_use:"Media is referenced by other resources. See `details.projectIds` and `details.sessionIds` \u2014 remove those references before deleting.",session_in_use:"Session is referenced by a composition. See `details.projectIds` \u2014 remove those references before deleting.",render_not_cancellable:"Render is already in a terminal state (complete / error / cancelled) and cannot be cancelled.",rate_limited:"Rate limit exceeded. Back off using the `retry-after` response header.",invalid_composition:"Composition violates an invariant (see `details`). Common ones: clip_source_track_kind_mismatch, track_clips_overlap, transition_no_predecessor.",clip_not_found:"The clip suggestion publicId doesn't exist in this org. Run `cueframe clips <mediaItemId>` to enumerate valid sug_* ids.",service_unavailable:"The processing pipeline is temporarily unavailable. Retry shortly; if it persists, contact support@cueframe.ai with the requestId.",payment_required:"The request exceeds a billing limit. For generation, the estimated cost is over the per-call ceiling (see `details.estimateUsd` / `details.ceilingUsd`) \u2014 lower the requested duration or raise the ceiling."};function E(e){return e instanceof u?He[e.code]??null:null}async function*Ye(e,o,t){let n=b();if(!n?.baseUrl)throw new Error(`@cueframe/sdk: createClient({baseUrl}) must be called before ${o}.`);let s=n.baseUrl.replace(/\/$/,"")+e,i=new Headers({accept:"text/event-stream",...n.headers??{}});n.apiKey&&!i.has("authorization")&&i.set("authorization",`Bearer ${n.apiKey}`);let c=await(n.fetch??fetch)(s,{method:"GET",headers:i,signal:t.signal});if(!c.ok){let x;try{x=(await c.json()).error??{code:"unknown",message:c.statusText}}catch{x={code:"unknown",message:c.statusText}}throw new u(c.status,x,c.headers.get("x-request-id")??void 0)}if(!c.body)throw new Error("SSE response has no body");let d=c.body.getReader(),a=new TextDecoder("utf-8"),f="";try{for(;;){let{value:x,done:g}=await d.read();if(g)break;f+=a.decode(x,{stream:!0});let R=f.indexOf(`
|
|
3
|
-
|
|
4
|
-
`);for(;R!==-1;){let Ze=f.slice(0,R);f=f.slice(R+2);let M=Qe(Ze);M&&(yield M),R=f.indexOf(`
|
|
5
|
-
|
|
6
|
-
`)}}}finally{try{d.releaseLock()}catch{}}}function Qe(e){if(!e.trim())return null;let o=null,t=[];for(let n of e.split(`
|
|
7
|
-
`)){if(!n||n.startsWith(":"))continue;let s=n.indexOf(":");if(s===-1)continue;let i=n.slice(0,s),p=n.slice(s+1).replace(/^ /,"");i==="event"?o=p:i==="data"&&t.push(p)}return!o||t.length===0?null:{event:o,data:t.join(`
|
|
8
|
-
`)}}async function*Xe(e,o,t={}){let n=`/v1/projects/${encodeURIComponent(e)}/renders/${encodeURIComponent(o)}/stream`;for await(let s of Ye(n,"iterRenderEvents",t)){let i=eo(s);i&&(yield i)}}function eo(e){let{event:o,data:t}=e;if(t===null||o!=="progress"&&o!=="complete"&&o!=="error")return null;let n;try{n=JSON.parse(t)}catch{return null}return{event:o,data:n}}var h={};y(h,{composeFromSuggestion:()=>io,getComposeFromSuggestionUrl:()=>G,getListMediaSuggestionsUrl:()=>U,getResetMediaSuggestionsUrl:()=>$,getSuggestBriefsUrl:()=>L,listMediaSuggestions:()=>ao,resetMediaSuggestions:()=>mo,suggestBriefs:()=>fo});var G=e=>`/v1/projects/${e}/composition/from-suggestion`,io=async(e,o,t)=>r(G(e),{...t,method:"POST",headers:{"Content-Type":"application/json",...t?.headers},body:JSON.stringify(o)}),U=e=>`/v1/media/${e}/suggestions`,ao=async(e,o)=>r(U(e),{...o,method:"GET"}),L=e=>`/v1/media/${e}/suggestions`,fo=async(e,o)=>r(L(e),{...o,method:"POST"}),$=e=>`/v1/media/${e}/suggestions`,mo=async(e,o)=>r($(e),{...o,method:"DELETE"});var D={};y(D,{createComponent:()=>uo,getComponent:()=>lo,getComponentSource:()=>yo,getCreateComponentUrl:()=>J,getGetComponentSourceUrl:()=>z,getGetComponentUrl:()=>W,getListCatalogUrl:()=>_,getUpdateComponentUrl:()=>N,listCatalog:()=>co,updateComponent:()=>xo});var _=e=>{let o=new URLSearchParams;Object.entries(e||{}).forEach(([n,s])=>{s!==void 0&&o.append(n,s===null?"null":s.toString())});let t=o.toString();return t.length>0?`/v1/components?${t}`:"/v1/components"},co=async(e,o)=>r(_(e),{...o,method:"GET"}),J=()=>"/v1/components",uo=async(e,o)=>r(J(),{...o,method:"POST",headers:{"Content-Type":"application/json",...o?.headers},body:JSON.stringify(e)}),N=e=>`/v1/components/${e}`,xo=async(e,o,t)=>r(N(e),{...t,method:"PUT",headers:{"Content-Type":"application/json",...t?.headers},body:JSON.stringify(o)}),W=e=>`/v1/components/${e}`,lo=async(e,o)=>r(W(e),{...o,method:"GET"}),z=e=>`/v1/components/${e}/source`,yo=async(e,o)=>r(z(e),{...o,method:"GET"});var Q={};y(Q,{cancelExport:()=>Io,createFcpxmlExport:()=>Po,createPremiereExport:()=>ko,getCancelExportUrl:()=>Y,getCreateFcpxmlExportUrl:()=>Z,getCreatePremiereExportUrl:()=>V,getExport:()=>vo,getGetExportUrl:()=>H});var Z=e=>`/v1/projects/${e}/exports/fcpxml`,Po=async(e,o,t)=>r(Z(e),{...t,method:"POST",headers:{"Content-Type":"application/json",...t?.headers},body:JSON.stringify(o)}),V=e=>`/v1/projects/${e}/exports/premiere`,ko=async(e,o,t)=>r(V(e),{...t,method:"POST",headers:{"Content-Type":"application/json",...t?.headers},body:JSON.stringify(o)}),H=(e,o)=>`/v1/projects/${e}/exports/${o}`,vo=async(e,o,t)=>r(H(e,o),{...t,method:"GET"}),Y=(e,o)=>`/v1/projects/${e}/exports/${o}/cancel`,Io=async(e,o,t)=>r(Y(e,o),{...t,method:"POST"});var ye={};y(ye,{analyzeTranscript:()=>zo,createMediaUpload:()=>Bo,createUploadToken:()=>wo,deleteMedia:()=>jo,finalizeMedia:()=>Fo,generateMedia:()=>Ao,getAnalyzeTranscriptUrl:()=>le,getCreateMediaUploadUrl:()=>oe,getCreateUploadTokenUrl:()=>ee,getDeleteMediaUrl:()=>pe,getFinalizeMediaUrl:()=>re,getGenerateMediaUrl:()=>ne,getGetMediaContextUrl:()=>fe,getGetMediaPerformanceUrl:()=>xe,getGetMediaTranscriptUrl:()=>ae,getGetMediaUrl:()=>ie,getImportMediaUrl:()=>se,getListMediaFactsUrl:()=>de,getListMediaUrl:()=>te,getMedia:()=>Go,getMediaContext:()=>Lo,getMediaPerformance:()=>Wo,getMediaTranscript:()=>Uo,getPurchaseMediaFactUrl:()=>ue,getSearchLibraryUrl:()=>X,getTriggerMatteBakeUrl:()=>ce,getTriggerSubjectDetectionUrl:()=>me,importMedia:()=>Mo,listMedia:()=>Ko,listMediaFacts:()=>Jo,purchaseMediaFact:()=>No,searchLibrary:()=>Eo,triggerMatteBake:()=>_o,triggerSubjectDetection:()=>$o});var X=e=>{let o=new URLSearchParams;Object.entries(e||{}).forEach(([n,s])=>{s!==void 0&&o.append(n,s===null?"null":s.toString())});let t=o.toString();return t.length>0?`/v1/media/search?${t}`:"/v1/media/search"},Eo=async(e,o)=>r(X(e),{...o,method:"GET"}),ee=()=>"/v1/uploads/token",wo=async(e,o)=>r(ee(),{...o,method:"POST",headers:{"Content-Type":"application/json",...o?.headers},body:JSON.stringify(e)}),oe=()=>"/v1/media",Bo=async(e,o)=>r(oe(),{...o,method:"POST",headers:{"Content-Type":"application/json",...o?.headers},body:JSON.stringify(e)}),te=()=>"/v1/media",Ko=async e=>r(te(),{...e,method:"GET"}),re=e=>`/v1/media/${e}/finalize`,Fo=async(e,o,t)=>r(re(e),{...t,method:"POST",headers:{"Content-Type":"application/json",...t?.headers},body:JSON.stringify(o)}),ne=()=>"/v1/media/generate",Ao=async(e,o)=>r(ne(),{...o,method:"POST",headers:{"Content-Type":"application/json",...o?.headers},body:JSON.stringify(e)}),se=()=>"/v1/media/import",Mo=async(e,o)=>r(se(),{...o,method:"POST",headers:{"Content-Type":"application/json",...o?.headers},body:JSON.stringify(e)}),pe=e=>`/v1/media/${e}`,jo=async(e,o)=>r(pe(e),{...o,method:"DELETE"}),ie=e=>`/v1/media/${e}`,Go=async(e,o)=>r(ie(e),{...o,method:"GET"}),ae=e=>`/v1/media/${e}/transcript`,Uo=async(e,o)=>r(ae(e),{...o,method:"GET"}),fe=e=>`/v1/media/${e}/context`,Lo=async(e,o)=>r(fe(e),{...o,method:"GET"}),me=e=>`/v1/media/${e}/detect-subjects`,$o=async(e,o)=>r(me(e),{...o,method:"POST"}),ce=e=>`/v1/media/${e}/matte`,_o=async(e,o,t)=>r(ce(e),{...t,method:"POST",headers:{"Content-Type":"application/json",...t?.headers},body:JSON.stringify(o)}),de=(e,o)=>{let t=new URLSearchParams;Object.entries(o||{}).forEach(([s,i])=>{i!==void 0&&t.append(s,i===null?"null":i.toString())});let n=t.toString();return n.length>0?`/v1/media/${e}/facts?${n}`:`/v1/media/${e}/facts`},Jo=async(e,o,t)=>r(de(e,o),{...t,method:"GET"}),ue=e=>`/v1/media/${e}/facts`,No=async(e,o,t)=>r(ue(e),{...t,method:"POST",headers:{"Content-Type":"application/json",...t?.headers},body:JSON.stringify(o)}),xe=e=>`/v1/media/${e}/performance`,Wo=async(e,o)=>r(xe(e),{...o,method:"GET"}),le=e=>`/v1/media/${e}/transcript/analyze`,zo=async(e,o,t)=>r(le(e),{...t,method:"POST",headers:{"Content-Type":"application/json",...t?.headers},body:JSON.stringify(o)});var Pe={};y(Pe,{createProject:()=>Zo,deleteProject:()=>Yo,getCreateProjectUrl:()=>Oe,getDeleteProjectUrl:()=>he,getGetProjectContextUrl:()=>Se,getGetProjectUrl:()=>Ce,getListProjectsUrl:()=>Re,getPatchProjectUrl:()=>ge,getProject:()=>Vo,getProjectContext:()=>Qo,listProjects:()=>Do,patchProject:()=>Ho});var Re=()=>"/v1/projects",Do=async e=>r(Re(),{...e,method:"GET"}),Oe=()=>"/v1/projects",Zo=async(e,o)=>r(Oe(),{...o,method:"POST",headers:{"Content-Type":"application/json",...o?.headers},body:JSON.stringify(e)}),Ce=e=>`/v1/projects/${e}`,Vo=async(e,o)=>r(Ce(e),{...o,method:"GET"}),ge=e=>`/v1/projects/${e}`,Ho=async(e,o,t)=>r(ge(e),{...t,method:"PATCH",headers:{"Content-Type":"application/json",...t?.headers},body:JSON.stringify(o)}),he=e=>`/v1/projects/${e}`,Yo=async(e,o)=>r(he(e),{...o,method:"DELETE"}),Se=e=>`/v1/projects/${e}/context`,Qo=async(e,o)=>r(Se(e),{...o,method:"GET"});var Be={};y(Be,{cancelRender:()=>nt,createRender:()=>et,getCancelRenderUrl:()=>Te,getCreateRenderUrl:()=>ke,getGetRenderUrl:()=>qe,getListProjectRendersUrl:()=>ve,getPreviewClipUrl:()=>Ie,getRefreshRenderUrlUrl:()=>Ee,getRender:()=>rt,getRetryRenderUrl:()=>be,getStreamRenderUrl:()=>we,listProjectRenders:()=>ot,previewClip:()=>tt,refreshRenderUrl:()=>pt,retryRender:()=>st,streamRender:()=>it});var ke=e=>`/v1/projects/${e}/renders`,et=async(e,o,t)=>r(ke(e),{...t,method:"POST",headers:{"Content-Type":"application/json",...t?.headers},body:JSON.stringify(o)}),ve=e=>`/v1/projects/${e}/renders`,ot=async(e,o)=>r(ve(e),{...o,method:"GET"}),Ie=e=>`/v1/projects/${e}/preview-clip`,tt=async(e,o,t)=>r(Ie(e),{...t,method:"POST",headers:{"Content-Type":"application/json",...t?.headers},body:JSON.stringify(o)}),qe=(e,o)=>`/v1/projects/${e}/renders/${o}`,rt=async(e,o,t)=>r(qe(e,o),{...t,method:"GET"}),Te=(e,o)=>`/v1/projects/${e}/renders/${o}/cancel`,nt=async(e,o,t)=>r(Te(e,o),{...t,method:"POST"}),be=(e,o)=>`/v1/projects/${e}/renders/${o}/retry`,st=async(e,o,t)=>r(be(e,o),{...t,method:"POST"}),Ee=(e,o)=>`/v1/projects/${e}/renders/${o}/refresh-url`,pt=async(e,o,t)=>r(Ee(e,o),{...t,method:"POST"}),we=(e,o)=>`/v1/projects/${e}/renders/${o}/stream`,it=async(e,o,t)=>r(we(e,o),{...t,method:"GET"});var Ue={};y(Ue,{createSession:()=>ct,deleteSession:()=>ut,getCreateSessionUrl:()=>Fe,getDeleteSessionUrl:()=>Me,getGetMuxJobUrl:()=>Ge,getGetSessionUrl:()=>Ae,getListSessionsUrl:()=>Ke,getMuxJob:()=>lt,getSession:()=>dt,getTriggerMuxJobUrl:()=>je,listSessions:()=>mt,triggerMuxJob:()=>xt});var Ke=()=>"/v1/sessions",mt=async e=>r(Ke(),{...e,method:"GET"}),Fe=()=>"/v1/sessions",ct=async(e,o)=>r(Fe(),{...o,method:"POST",headers:{"Content-Type":"application/json",...o?.headers},body:JSON.stringify(e)}),Ae=e=>`/v1/sessions/${e}`,dt=async(e,o)=>r(Ae(e),{...o,method:"GET"}),Me=e=>`/v1/sessions/${e}`,ut=async(e,o)=>r(Me(e),{...o,method:"DELETE"}),je=e=>`/v1/sessions/${e}/mux-job`,xt=async(e,o)=>r(je(e),{...o,method:"POST"}),Ge=e=>`/v1/sessions/${e}/mux-job`,lt=async(e,o)=>r(Ge(e),{...o,method:"GET"});import{readFileSync as gt,writeFileSync as ht,mkdirSync as St,existsSync as Pt}from"fs";import{join as Le}from"path";import{homedir as kt}from"os";var m={Success:0,UserError:2,ApiClientError:3,ApiServerError:4,NetworkError:5,PaymentRequired:6};function w(e){if(e instanceof u){if(e.status===402)return m.PaymentRequired;if(e.status>=500)return m.ApiServerError;if(e.status>=400)return m.ApiClientError}let o=e?.exitCode;return typeof o=="number"?o:m.NetworkError}function tb(e){return e===402?m.PaymentRequired:e>=500?m.ApiServerError:e>=400?m.ApiClientError:m.Success}function S(e){process.exit(e)}var $e=Le(kt(),".cueframe"),v=Le($e,"auth.json"),O={local:"http://127.0.0.1:3211",dev:"https://api-dev.cueframe.ai",prod:"https://api.cueframe.ai"},vt="prod";function ab(e=vt){return process.env.CUEFRAME_API_URL??O[e]??O.prod}var I=class extends Error{constructor(t,n){super(n);this.code=t;this.name="AuthStoreError"}code;exitCode=m.UserError};function _e(){if(!Pt(v))return{targets:{}};let e=gt(v,"utf-8");try{return JSON.parse(e)}catch{throw new I("auth_config_corrupt",`${v} is corrupt and cannot be parsed. Delete it and re-run \`cueframe login\`.`)}}function It(e){St($e,{recursive:!0,mode:448}),ht(v,JSON.stringify(e,null,2),{mode:384})}function fb(e,o="prod",t){let n=_e(),s=O[o]??O.prod;n.targets[o]={apiKey:e,apiUrl:t??s},It(n)}function Je(e="prod"){let o=process.env.CUEFRAME_API_KEY,t=process.env.CUEFRAME_API_URL;if(o)return{apiKey:o,apiUrl:t??O[e]??O.prod};let s=_e().targets[e];if(!s)throw new I("auth_missing",`No auth configured for target "${e}". Run \`cueframe login --target ${e}\` (browser sign-in) or \`cueframe auth <api-key> --target ${e}\` (CI / headless).`);return s}function Ne(e){let{apiKey:o,apiUrl:t}=Je(e);T({baseUrl:t,apiKey:o})}function q(e){let o=e instanceof u?`${e.message} (${e.code}${e.status?`, ${e.status}`:""})`:e instanceof Error?e.message:String(e),t=E(e);return t?`${o}
|
|
9
|
-
\u2192 ${t}`:o}import qt from"ora";import Tt from"pino";var bt="v1",We=Tt({level:"trace",base:{schemaVersion:bt},messageKey:"event",timestamp:()=>`,"ts":${Date.now()}`,formatters:{level:()=>({_:0})}});function B(e,o){return qt({text:e,isSilent:!!o}).start()}function C(e,o,t={}){e.json&&We.info(t,o)}function Rb(e,o,t){if(e.json){console.log(JSON.stringify(o,null,2));return}t()}function K(e,o,t,n){let s=t instanceof Error?t.message:String(t),i=typeof t?.code=="string"?t.code:void 0,p=t?.status;e.json?We.info({phase:o,message:s,...i?{code:i}:{},...typeof p=="number"?{status:p}:{},exitCode:n},"error"):process.stderr.write(`\u2716 ${o}: ${q(t)}
|
|
10
|
-
`)}function F(e,o,t,n){e.json&&K(e,o,t,n)}function Ob(e,o){o.json||console.log(e)}function Et(e){for(let o=0;o<e.length;o++){let t=e.charCodeAt(o);if(t<=31||t===127)return!0}return!1}function De(e,o,t){e.length===0&&ze(`${o} is empty.`,t),Et(e)&&ze(`${o} contains a control character (newline, tab, or null byte). Identifiers must be plain text \u2014 check for a stray copy-paste artifact.`,t)}function ze(e,o){K(o,"preflight",new Error(e),m.UserError),S(m.UserError)}var wt=5e3,A=300*1e3;async function Tb(e,o){if(De(e,"mediaItemId",o),o.dryRun){C(o,"analyze_dry_run",{mediaItemId:e,target:o.target,wait:!!o.wait,wouldCall:"POST /v1/media/:id/suggestions"}),o.json||console.log(`[dry-run] Would trigger clip analysis for ${e} on ${o.target}.`);return}Ne(o.target),C(o,"analyze_prepare",{mediaItemId:e,target:o.target,wait:!!o.wait});let t=B("Triggering clip analysis\u2026",o.json),n;try{n=await h.suggestBriefs(e),t.succeed(n.workflowId?`Analysis started (workflow: ${n.workflowId})`:`Analysis ${n.alreadyRunning?"already running":"started"}`)}catch(p){t.fail(`Failed to start analysis: ${q(p)}`),F(o,"analyze_prepare",p,w(p)),S(w(p))}if(C(o,"analyze_ready",{mediaItemId:e,workflowId:n.workflowId,alreadyRunning:!!n.alreadyRunning}),!o.wait){o.json||console.log(`
|
|
11
|
-
Run \`cueframe clips ${e}\` to check results.`);return}let s=B("Waiting for analysis to complete\u2026",o.json),i=Date.now();for(;;){await new Promise(p=>setTimeout(p,wt)),Date.now()-i>A&&(s.fail(`Timed out after ${Math.round(A/1e3)}s. Run \`cueframe clips ${e}\` to check later.`),F(o,"analyze_progress",new Error(`Analysis did not complete within ${Math.round(A/1e3)}s`),m.UserError),S(m.UserError));try{let p=await h.listMediaSuggestions(e);if(p.suggestions.length>0){s.succeed(`Analysis complete \u2014 ${p.suggestions.length} clips found`),C(o,"analyze_complete",{mediaItemId:e,durationMs:Date.now()-i,suggestionCount:p.suggestions.length,suggestions:p.suggestions}),o.json||p.suggestions.forEach((d,a)=>{let f=(d.trim.end-d.trim.start).toFixed(1);console.log(`
|
|
12
|
-
${a+1}. ${d.title} (${d.id})`),console.log(` ${d.trim.start.toFixed(1)}s \u2013 ${d.trim.end.toFixed(1)}s (${f}s) score: ${d.score}`),console.log(` ${d.reason}`)});return}let c=Math.round((Date.now()-i)/1e3);s.text=`Waiting for analysis\u2026 (${c}s)`,C(o,"analyze_progress",{mediaItemId:e,elapsedSec:c})}catch{}}}export{u as a,T as b,j as c,r as d,E as e,Xe as f,h as g,D as h,Q as i,ye as j,Pe as k,Be as l,Ue as m,m as n,w as o,tb as p,S as q,ab as r,fb as s,Ne as t,q as u,B as v,C as w,Rb as x,K as y,F as z,Ob as A,De as B,Tb as C};
|
package/skills/_connect.md
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
- **Claude Code:** offer to run
|
|
2
|
-
`claude mcp add --transport http cueframe https://api.cueframe.ai/v1/mcp` — a browser
|
|
3
|
-
opens and the user clicks **Allow**. No API key.
|
|
4
|
-
- **Claude.ai / Claude Desktop:** Settings → Connectors → add a custom connector with
|
|
5
|
-
`https://api.cueframe.ai/v1/mcp`.
|
|
6
|
-
- **Other agents (Cursor, Codex, VS Code, Windsurf, Zed, Gemini CLI, Copilot CLI, …):**
|
|
7
|
-
run `npx -y cueframe install` — it detects what is on the machine and wires each one.
|
|
8
|
-
- **ChatGPT:** the CLI cannot wire it (there is no local config to write) — add
|
|
9
|
-
`https://api.cueframe.ai/v1/mcp` as a custom connector instead.
|
|
10
|
-
- **No account at all (pay-per-call):** connect
|
|
11
|
-
`https://api.cueframe.ai/v1/mcp/x402` — no sign-up, no API key; priced calls
|
|
12
|
-
settle per-call in USDC over x402 from the agent's wallet.
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: cueframe-component-authoring
|
|
3
|
-
description: Use when authoring, forking, or customizing a CueFrame motion-graphics component/primitive/graphic — e.g. "customize the cinematic-title primitive", "make my own animated lower-third", "fork a CueFrame template and edit it", "author a custom graphic and render it". Covers both the MCP agent path (get_component_source → create_component) and the CLI repo path (get_component_source → npx -y cueframe new component → push). Use BEFORE hand-writing a component from scratch — forking a built-in is usually the faster start.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# CueFrame component authoring (fork / customize / own)
|
|
7
|
-
|
|
8
|
-
CueFrame ships 87 built-in motion-graphics **primitives** (titles, lower-thirds, captions,
|
|
9
|
-
effects, transitions, scenes). You can **fork any of them as editable source**, customize it,
|
|
10
|
-
and render it on CueFrame — or author a brand-new component. This is shadcn-for-video: own the
|
|
11
|
-
component code; CueFrame is the reliable engine that renders it.
|
|
12
|
-
|
|
13
|
-
**The two facts that shape everything:**
|
|
14
|
-
- A component is mounted **`({ durationInFrames, params }) => JSX`** at render — `params` is the
|
|
15
|
-
single props bag (your composition clip's params). A forked primitive is auto-wrapped in this
|
|
16
|
-
adapter; a from-scratch component must default-export this shape.
|
|
17
|
-
- The shared renderer **never runs your code**: a component is baked to a transparent (alpha)
|
|
18
|
-
video in an isolated box first, then composited as trusted pixels. So owning/editing source is
|
|
19
|
-
safe, and rendering stays on CueFrame.
|
|
20
|
-
|
|
21
|
-
## Path A — MCP agent (no filesystem; source lives server-side)
|
|
22
|
-
|
|
23
|
-
Single self-contained module per component (`create_component` takes one `tsxSource`).
|
|
24
|
-
|
|
25
|
-
1. **Fork a built-in:** `get_component_source(componentId: "cinematic-title")` → returns the
|
|
26
|
-
primitive's editable single-module `tsxSource` (the named component + the adapter). Discover
|
|
27
|
-
ids from the catalog (`/v1/components`). *(Or author from scratch — skip to step 2.)*
|
|
28
|
-
2. **Author/own it:** edit the `tsxSource`, then `create_component({ componentId, tsxSource, … })`
|
|
29
|
-
to store your customized copy (origin `server-native`; if forked, `ejectedFrom` is stamped).
|
|
30
|
-
3. **Iterate (author→preview→fix):** `preview_component({ componentId, params })` (sessionless; if a cold first call returns 409 box_warming, retry in a few seconds)
|
|
31
|
-
renders ONE still. A 422 `component_does_not_compile` returns the compiler error — read it, fix
|
|
32
|
-
via `update_component` (same id, in place), preview again.
|
|
33
|
-
4. **Render:** add it to a composition as an `alpha-layer` clip (`apply_composition`), then
|
|
34
|
-
`create_render` → `wait_job kind:"render"` for the MP4.
|
|
35
|
-
|
|
36
|
-
## Path B — CLI / coding agent (repo-owned source under git)
|
|
37
|
-
|
|
38
|
-
Source lives in `cueframe/components/<id>/` (the `cueframe.json` workspace); edit locally as
|
|
39
|
-
standard Remotion, push to render.
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
npx -y cueframe init --json # scaffold cueframe.json + cueframe/components/
|
|
43
|
-
npx -y cueframe new component my-badge --json # scaffold a component in the workspace
|
|
44
|
-
# to start from a built-in instead of a blank file: fetch its source with the
|
|
45
|
-
# `get_component_source` tool and paste it into cueframe/components/my-badge/index.tsx
|
|
46
|
-
# …edit cueframe/components/<id>/ in your editor (standard Remotion)…
|
|
47
|
-
npx -y cueframe push my-badge --json # upload index.tsx as the component tsxSource
|
|
48
|
-
# or: npx -y cueframe sync --json # push every component in the workspace
|
|
49
|
-
# reference the component id in your composition, then render:
|
|
50
|
-
npx -y cueframe render <projectId> -o ./out.mp4 --json
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
The CLI writes a 3-file layout (`index.tsx` = renderable module + adapter; `_config.ts` + `config.ts`
|
|
54
|
-
= local workspace metadata). `push` sends `index.tsx` as the single `tsxSource` — the same shape the
|
|
55
|
-
MCP path stores. To preview before a full render, push it and use the MCP `preview_component` loop.
|
|
56
|
-
|
|
57
|
-
## Choosing what to fork
|
|
58
|
-
The catalog (`/v1/components`) gives each primitive's `description` / `useWhen` / `tags` / `mood` /
|
|
59
|
-
`tier` / `useCase` / `examples` (example params) + `propSchema` + its source via `get_component_source`.
|
|
60
|
-
Read the spec + the code to pick a starting point. (Rendered preview thumbnails are a separate
|
|
61
|
-
follow-up — today you choose from prose + params + source, or compose+`preview_frame` to see it.)
|
|
62
|
-
|
|
63
|
-
## Don't
|
|
64
|
-
- Don't expect a forked primitive to use rich named props — it's adapted to `({durationInFrames,
|
|
65
|
-
params})`; read `params` inside.
|
|
66
|
-
- Don't hand-roll a graphic from zero when a built-in is close — fork it (fetch the source with
|
|
67
|
-
`get_component_source`, paste it into a `npx -y cueframe new component` scaffold) and edit.
|
|
68
|
-
- Don't `create_component` a fresh id each fix iteration — `update_component` (same id) is the loop.
|