| name | remix-script |
| description | Write the ad SCRIPT for a remix — take the brand details (a brand-context pack and/or a source ad's remix payload) plus the user's creative prompt, and produce a structured, render-ready script in the **format the source actually is** — podcast-skit, iMessage thread, sung music video, single-host UGC, animated explainer, etc. In remix mode the skill **watches the source video first** (via `/watch`), reads `source-sample.json.formatProfile`, and **routes to the matching script shape and production template — it does NOT default to `podcast-script`**. Only `podcast-skit-fabricated` has a shipped scaffolder today; every other format is hand-authored against the source's actual scene shape. The skill then asks the user format-aware clarifying questions (angle, references, format-specific knobs, must-include / must-avoid), writes the lines (or bubbles / lyrics / VO beats), emits a structured `storyboard.json` (per-scene stills + optional rendered keyframe paths) the consuming app reads to **preview keyframes** with the user before sign-off, validates (template path only), and hands the script.json to the matching production template (`create-podcast-skit-ad`, `create-imessage-video-ad`, …). Use when the user says "write the script", "remix the script", or needs a script before generating an ad. No API keys — the agent writes the lines; scripts only scaffold + validate. |
remix-script
Turn brand details + a creative prompt into a render-ready ad script.
Template-driven: you pick a script format from templates/ (the first is
podcast-script), the scaffolder lays out the correct scene structure, and you
(the agent) write the lines. The output is a script.json the matching
production template renders.
Two modes:
- Fresh — brand details + prompt → a new script from scratch.
- Remix — a source ad's remix payload (from the
remix-ad / library flow) → inherit its format + beat arc (NOT its literal scene count), then write the new brand's script with as many scenes as that brand needs.
When to use
- "Write the script for [brand] / this idea."
- "Remix this ad's script for [other brand]." (works for any format —
podcast-skit, iMessage thread, sung music video, single-host UGC,
animated explainer.)
- Any step that needs a structured script before generation (this is
the script stage of the remix pipeline, extracted as its own skill).
Do NOT use to: research the brand (use brand-research), or render
the ad (hand the finished script.json to the format-matching
production template — create-podcast-skit-ad,
create-imessage-video-ad, etc. — see step 9's route table).
Inputs
- Brand details (one or both):
- a brand-context pack (
brand-research/*.md — voice, audience, what-to-never-say, claims) from the brand-research skill, and/or
- a source sample payload (
source-sample.json from remix-ad's fetch_sample.py) for remix mode.
- User prompt — the creative direction / angle.
formatProfile — comes from source-sample.json in remix mode;
asked from the user in fresh mode. There is no default format.
The skill never picks podcast-script to be safe — if the source
is iMessage, the output is iMessage (hand-authored). See step 3's
route table.
Templates
A "template" here means a scaffolder + validator pair for one
formatProfile. Templates live in templates/<name>.json (a _meta
block with scene count, word caps, intonation legend, guardrails).
Only one template is shipped today — and that does not mean every
remix routes to it. Most formats are hand-authored (see step 5
Path B). The full set of formats this skill handles is in step 3's
route table.
podcast-script (only shipped template) — two-host fabricated
podcast skit (HER + HIM), 20-24 alternating scenes, intonation
legend, ≤10 words/line, ≤3 words/caption, themed-set mismatch as
the joke. Renders via create-podcast-skit-ad. Scene shape:
{scene, who, time, still, caption, text}. Used only when the
source formatProfile is podcast-skit-fabricated (or fresh mode
with the user explicitly picking this format).
To add a template for another format, drop a new <name>.json here
following the same _meta.rules shape, plus a matching scaffolder
clause in scripts/new_script.py and validator clause in
scripts/validate_script.py.
Setup
No API keys, no heavy deps — the agent writes the copy; the scripts only scaffold and validate.
pip install -r requirements.txt
Workflow
-
Watch the source FIRST (remix mode).
In remix mode you are rewriting somebody's ad. Don't trust
extracted_script alone — it's a transcript, not the ad. The pacing,
sight gags, on-screen text, where the brand surfaces, and the tone
often only land once you've seen it. Run the /watch skill on the
source video before writing any lines:
jq -r .media_url ./remix/source-sample.json
Read the frames /watch returns. Note: archetype (skit / single-host /
sung / explainer), set + blocking, where the brand logo / pack lands,
what the on-screen text says vs. what's spoken, the actual hook beat.
These observations belong in the storyboard preview at step 7 — don't
throw them away. The format you see here is also what drives step 3.
Skip this step in fresh mode (no source video). Also skip if the
user has already provided their own brief storyboard for the source.
-
Gather brand details.
Completeness-check before asking. Slug the target brand
(lowercase, dashes), then ls clients/ case-insensitively —
clients/hume-health/ and clients/Hume-health/ are the same brand;
normalize.
Then run brand-research's verify gate against the brand root:
python ../brand-research/scripts/verify_pack.py --brand-dir clients/<slug>
- Exit 0 (
PASS) — the pack is complete. Read every file in
clients/<slug>/brand-research/. If clients/<slug>/concept-brief.md
exists, treat its concepts as the starting menu the user picks from
in step 4 (clarifying questions). Proceed to step 3.
- Non-zero exit — the pack is missing or incomplete (no folder, stub
TBDs, missing headers, manifest gaps, etc.). Do not write the
script with partial info, and do not ask the user. Invoke the
brand-research skill against the same --brand-dir. It is
step-idempotent: every phase that's already complete is skipped, and
only the missing pieces run. When finally returns
, resume here at step 3.
Decision rules
- The template's
_meta.rules are binding. Don't exceed the word/caption caps or the scene range.
- Remix preserves the format + arc, not the scene count — for the
flexible-count formats (
podcast-skit-fabricated, single-host-ugc,
animated-explainer-villain). The archetype (two-host skit, single
narrator, villain-explainer) and the beat arc (hook → mechanism →
payoff) carry from the source; the new ad's scene count flexes with
the new brand's copy density.
- For
formatProfile: music-video-sung: scene count and per-scene
timing are LOCKED to the source — lyric meter sets timing, not copy
density. Mirror the source 1:1. The arc is verse → pre-chorus → chorus → outro (or whatever the source declares), not hook → mechanism → payoff. Flexing scene count would desync lyrics from
the music.
- For
formatProfile: music-video-sung: technical / acronym / Latinate
brand terms (GABA, L-theanine, FDA, GLP-1) go in on-screen hyperframes,
NEVER sung lyrics. ElevenLabs Music vocal pronunciation is unreliable
on multi-syllable Latinate words; lead with the brand-promise / emotional
layer in lyrics, deliver technical claims via burned-in type.
- Voice is the brand's, not the source's. Match the brand-context pack's voice + never-say list, even when remixing.
- Brand-pack-current-SKU wins over the user's one-liner. If the
user's brief mentions a product variant that the brand pack flags as
EOL / replaced (e.g. user says "can on nightstand" but
01-company-overview.md
says cans are discontinued), use the current SKU and flag the swap to
the user. No question needed unless they explicitly override.
- No acronyms in
text — spell out or rephrase.
- Lock duration to rendered VO later —
duration_target_sec is advisory; the production template re-times after TTS.
- One template = one format. Add a new
templates/<name>.json rather than overloading podcast-script.
Output
./working/script.json — validated, render-ready, in the chosen template's shape.
For podcast-script: {title, duration_target_sec, aspect_ratio, intonation_legend, voices{HER,HIM}, set_description, scenes[]}.
./working/storyboard.json — structured per-scene still descriptions
- optional
frame paths. The consuming app reads this directly to
render the storyboard UI. Shape:
{ scriptRef, scenes: [{scene, still, frame, note}] }.
./working/storyboard-frames/T01.png … TN.png — optional, rendered
only when the user opts in at step 7 and an image-gen atom is wired.
Failure modes
- Source has no
recipe.shots → can't inherit beats; pass --scenes N and write fresh.
- validate_script.py flags an acronym → spell it out or rephrase the line.
- Caption >3 words → it's a caption, not the line; compress to the punch.
- Same speaker twice → intentional double-beats are rare; default to strict alternation.