forge
Turn a one-line idea into a branch with tested, reviewed, committed code. The brainstorm-to-commit pipeline for Claude Code.
A Claude Code plugin that turns a brief into a cinematic launch video, an investor pitch deck, or a feature walkthrough — with live FLIP morph transitions, audio bus, scene SFX, and a dev scrubber wired the first time.
Turn a one-line idea into a branch with tested, reviewed, committed code. The brainstorm-to-commit pipeline for Claude Code.
FAQ
cinemorph is a Claude Code plugin with 1 hand-picked skill for marketing work, indexed on Flowy. Install it with the command on its page. It includes morph-deck. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
$ npx -y skills add LucasDuys/cinemorph --agent claude-code
Repo: LucasDuys/cinemorph
A Claude Code plugin that turns a brief into a cinematic launch video, an investor pitch deck, or a feature walkthrough — with live FLIP morph transitions, audio bus, scene SFX, and a dev scrubber wired the first time.
↑ 30-second product film generated by /cinemorph new --from-example launch-cinematic-30s. Click to play the full MP4.
Quick start · Commands · How it works · Examples · GitHub Pages site
Cinemorph is a Claude Code plugin (/cinemorph) that composes a Vite + React deck where persistent elements morph cleanly between stages via Framer Motion's shared-layout (LayoutGroup + layoutId) FLIP transitions. The deck is the artifact: run it live in Chrome, click through with arrow keys, or export to one of three production targets.
| Output | What it produces | When to use |
|---|---|---|
| Live React deck | Vite dev server, hot reload, ?dev=1 timeline scrubber | The projector. Pitches, demos, all-hands. |
| MP4 (Playwright + ffmpeg) | 30-second to 5-minute cinematic film with audio bus, voiceover, SFX, smear cuts | Launch trailers, social, embeddable on a landing page. |
| PPTX with native Morph | Editable PowerPoint with Microsoft Morph transitions between slides | Stakeholder handoff to teams that don't ship from a browser. |
Everything you see in the hero film above is one stages.ts + one data.ts plus a primitive registry. The composer wrote both files, the scaffold rendered them, Playwright recorded the result, and ffmpeg muxed the audio bed + voiceover + SFX cues.
# 1. Install the plugin into Claude Code
git clone https://github.com/LucasDuys/cinemorph.git
cp -r cinemorph/plugin ~/.claude/plugins/cinemorph
# 2. Restart Claude Code, then in a chat:
/cinemorph new --from-example launch-cinematic-30s --out my-launch-video
# 3. Run it
cd my-launch-video
bun install && bun run dev # → http://localhost:5173
# ?dev=1 for the timeline scrubber
Three more things you can do in one command:
# Investor pitch from a brief
/cinemorph new --theme stacklink-dark --prompt "Series A pitch: problem, solution, traction, team, ask"
# Feature walkthrough from a starter
/cinemorph new --from-example feature-demo --out ./changelog-q2
# Export the active deck to MP4 + PPTX + speaker notes
/cinemorph export --all
Auth. Cinemorph spawns the
claudeCLI binary on yourPATHand uses your Claude Code subscription. NoANTHROPIC_API_KEYneeded.
One master RAF clock drives every animation. Phases are non-overlapping windows with 350 ms cross-fade smear cuts at boundaries. The audio bus mixes a music bed, a voiceover, and a curated SFX library. Whooshes ride only real scene transitions; tiles bounce in with aeBounce easing.
00:01 Logo pop | 00:08 Hyper-zoom + sources | 00:13 "every tool. one brain." |
|---|---|---|
![]() | ![]() | ![]() |
00:18 Onboarding card lands | 00:22 Agent constellation | 00:28 Outro + URL chime |
|---|---|---|
![]() | ![]() | ![]() |
▶ Watch the full 30s MP4 (14 MB, 4K source · 3840×2160 @ 30fps)
The stacklink-roundone-pitch example renders five click-through stages with shared-layout morphs. Same engine, different example. Bundle is identical: stages.ts + data.ts + tokens.ts.
| 1. Hook | 2. Problem | 3. Solution |
|---|---|---|
![]() | ![]() | ![]() |
| 4. Differentiation | 5. Team & Ask |
|---|---|
![]() | ![]() |
| Command | What it does |
|---|---|
/cinemorph new "<brief>" [flags] | Generate a fresh deck. Asks clarifying questions when inputs are insufficient. |
/cinemorph iterate "<change>" | Modify the active deck (last-touched in cwd or --deck <path>). |
/cinemorph render | Open the live deck via bun run dev. |
/cinemorph pptx | Export to dist/<name>.pptx with native PowerPoint Morph transitions. |
/cinemorph video | Export to dist/<name>.mp4 via headless Playwright recording + ffmpeg mux. |
/cinemorph export --all | Run pptx + video + notes.md in one shot. |
/cinemorph reference add <path> --name <name> | Register an existing deck as a style reference. |
/morph-deck continues to work as a v1.0 alias.
/cinemorph new--from-example <name> Start from a bundled deck (see Examples)
--theme <name> stacklink-dark | bunq-mint-light | linear-light | minimal-mono | playful-poster
--tokens <path> Load tokens.json or DESIGN.md
--reference <image> Extract a 5-color palette from a screenshot
--prompt "<text>" Free-form brief or style description
--out <path> Where to write the new deck (default: ./<slug>)
Inputs apply in priority order — --theme < --tokens < --reference < --prompt. Later layers win on fields they provide. Missing fields trigger a clarifying question (the composer asks instead of guessing).
brief + flags
│
▼
┌───────────────┐
│ token merger │ --theme --tokens --reference --prompt (priority order)
└──────┬────────┘
│ tokens.ts
▼
┌───────────────────────┐
│ composer (Claude CLI) │ emits stages.ts + data.ts as JSON
└──────┬────────────────┘
│
▼
┌───────────────────────────────────────────┐
│ scaffold renderer │
│ Vite + React 18 + Tailwind + motion/react│
└──────┬────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ live deck → PPTX with Morph → MP4 (Playwright+ffmpeg) │
└──────────────────────────────────────────────────────────────┘
A <LayoutGroup> from motion/react wraps every persistent element on the canvas. Each primitive (wordmark, search bar, kpi tile, connector chip, agent card, …) carries a stable layoutId across stages. Framer Motion's shared-layout (FLIP) algorithm computes the layout-to-layout delta automatically — no keyframes, no per-property animate props, no easing math.
// stages.ts (excerpt — written by the composer)
export const STAGES: Stage[] = [
{
id: 'hook',
elements: {
wordmark: { pos: { left: '50%', top: '50%', width: '20%' }, shape: 'wordmark' },
slack: { pos: { left: '12%', top: '24%' }, shape: 'connectorChip' },
drive: { pos: { left: '88%', top: '24%' }, shape: 'connectorChip' },
},
},
{
id: 'reveal',
elements: {
wordmark: { pos: { left: '50%', top: '14%', width: '12%' }, shape: 'wordmark' },
slack: { pos: { left: '20%', top: '60%' }, shape: 'connectorChip' },
drive: { pos: { left: '80%', top: '60%' }, shape: 'connectorChip' },
cylinder: { pos: { left: '50%', top: '50%' }, shape: 'cylinder' },
},
},
];
When the deck advances from hook → reveal, the wordmark shrinks and slides to the top. The Slack and Drive chips drift outward and down. The cylinder fades in. All in one synchronized 700 ms transition. No code per element.
For 30-second-style films, the composer enforces the principles in plugin/docs/cinematic-launch-video-lessons.md. Every rule there was earned by shipping the hero film above and getting each detail wrong before getting it right:
elapsedMs. Phases are non-overlapping windows; 350 ms cross-fade smear cuts at boundaries.aeBounce easing for any element that lands with weight (Dan Ebberts' AE bounce ported to TypeScript).stoppedSfxRef: Set<number> ensures each cue's stopAtMs runs exactly once. Without it, when multiple cues share an audio file via the pool, the first cue's stop check re-fires every frame and pauses every later cue. This was the single most painful bug in the build.-ss seek-mode trap — input-seek (-ss before -i) when trimming with afade; output-seek can produce silent files that pass duration checks.?dev=1 so a reviewer can give you precise timestamp feedback during iteration.Generate any of these with /cinemorph new --from-example <name>:
| Example | Description |
|---|---|
launch-cinematic-30s | The canonical 30-second film shown above. RAF-clock driven, audio bus wired, dev scrubber, autoplay gate. |
stacklink-roundone-pitch | The 5-slide investor pitch shown above. |
pitch-5slide | Generic investor deck (Problem, Solution, Traction, Team, Ask). |
feature-demo | 4–6-slide feature walkthrough. |
kpi-dashboard-tour | Live-data dashboard tour with morphing kpi tiles. |
case-study | Customer success story format. |
manifesto | Vision / principles statement deck. |
team-intro | Team introduction with morphing pillar cards. |
release-notes | Engineering release-notes deck. |
roadmap | Quarterly roadmap with morphing milestone tiles. |
retro-storyboard | Retrospective / post-mortem storyboard. |
custom-element | Reference for adding your own primitive. |
Each example ships its own README.md, brief.md, stages.ts, data.ts, and tokens.ts — read them as documentation by example.
Five built-in themes cover most needs:
| Theme | Mood |
|---|---|
stacklink-dark | Near-black canvas, monochromatic, EU-enterprise restraint |
bunq-mint-light | Mint green + white, fintech, modern |
linear-light | Slate + blue, minimal, technical |
minimal-mono | Black + white + grays, typographic, editorial |
playful-poster | Vibrant multi-color, creative, event-driven |
Override with your own tokens:
/cinemorph new --tokens ./my-tokens.json --prompt "Q1 product all-hands"
// my-tokens.json
{
"background": "#09090F",
"foreground": "#FAFAFA",
"mutedForeground": "#A1A1AA",
"border": "#27272A",
"fontDisplay": "Space Grotesk, Inter, sans-serif",
"fontBody": "Inter, sans-serif",
"fontMono": "JetBrains Mono, monospace"
}
Or extract a palette from a brand screenshot:
/cinemorph new --reference ./brand-screenshot.png --prompt "Series B pitch"
Wordmark · KPI · Pillar · Quote · ConnectorChip (Slack, GitHub, Notion, Linear, Confluence, Jira, OneDrive, Teams, Salesforce, Drive) · Card · Logo · Image · Diagram · Icon · Chart · MorphChart · OrbitGroup · PipelineGroup · FooterStrip · StatGroup
Drop a .tsx into src/deck/elements/custom/:
// src/deck/elements/custom/MyChart.tsx — file name auto-derives the id `myChart`
export default function MyChart({ data }: { data: number[] }) { /* ... */ }
Use it in stages.ts:
elements: {
myChart: { pos: { left: '10%', top: '10%', width: '60%', height: '40%' }, shape: 'chart' }
}
See plugin/examples/custom-element/ for the full pattern.
cinemorph/
├── plugin/ # The installed Claude plugin
│ ├── plugin.json # Manifest (name, version, entry command)
│ ├── README.md # Plugin-internal docs
│ ├── skills/cinemorph/SKILL.md # Skill definition
│ ├── commands/ # /cinemorph slash command surfaces
│ ├── agents/morph-composer.md # Composer system prompt
│ ├── docs/
│ │ ├── cinematic-launch-video-lessons.md # Canonical reference for video output
│ │ └── composer-live.md
│ ├── examples/ # 12 starter decks (--from-example sources)
│ ├── scripts/ # Router, composer harness, exporters, verifier
│ ├── primitives/ # 16 built-in shape components
│ └── themes/ # 5 bundled theme JSON files
├── scaffold-template/ # What `new` clones into your output directory
├── assets/demos/ # README hero (video, gif, storyboard)
└── site/ # GitHub Pages source (built into docs/)
bun test # all plugin + scaffold tests
bun test plugin # plugin only
Acceptance test against the bundled stacklink reference: plugin/scripts/__tests__/acceptance-stacklink.test.cjs.
MIT. See LICENSE.
.forge/
collab/
.gitignore
.gitignore
assets/
demos/
launch-video-preview.gif
launch-video.mp4
pitch-deck/
01-hook.png
02-problem.png
03-solution.png
04-differentiation.png
05-team-ask.png
storyboard/
frame-01s.png
frame-02s.png
frame-04s.png
frame-06s.png
frame-08s.png
frame-11s.png
frame-13s.png
frame-14s.png
frame-16s.png
frame-18s.png
frame-20s.png
frame-22s.png
frame-23s.png
frame-26s.png
frame-27s.png
frame-28s.png
conftest.py
docs/
.nojekyll
index.html
README.md
script.js
styles.css
plugin/
__init__.py
__tests__/
e2e/
test_export_all.mjs
test_pptx_morph.py
test_video_pipeline.mjs
palette-extractor.test.cjs
scaffold.test.cjs
token-merger.test.cjs
agents/
morph-composer.md
commands/
export.md
morph-deck.md
pptx.md
video.md
docs/
cinematic-launch-video-lessons.md
composer-live.md
examples/
case-study/
brief.md
data.ts
README.md
stages.ts
tokens.ts
cinemorph-about-30s/
brief.md
data.ts
README.md
stages.ts
tokens.ts
custom-element/
MyChart.tsx
README.md
feature-demo/
brief.md
data.ts
README.md
stages.ts
tokens.ts
kpi-dashboard-tour/
brief.md
data.ts
README.md
stages.ts
tokens.ts
launch-cinematic-30s/
brief.md
data.ts
README.md
stages.ts
tokens.ts
manifesto/
brief.md
data.ts
README.md
stages.ts
tokens.ts
pitch-5slide/
brief.md
data.ts
README.md
stages.ts
tokens.ts
release-notes/
brief.md
data.ts
README.md
stages.ts
tokens.ts
retro-storyboard/
brief.md
data.ts
README.md
stages.ts
tokens.ts
roadmap/
brief.md
data.ts
README.md
stages.ts
tokens.ts
stacklink-roundone-pitch/
brief.md
data.ts
README.md
stages.ts
tokens.ts
team-intro/
brief.md
data.ts
README.md
stages.ts
tokens.ts
generators/
__init__.py
__pycache__/
build_pptx.cpython-313.pyc
__tests__/
build_pptx.test.py
deck_source.test.mjs
dwell.test.mjs
export_all.test.mjs
ffmpeg_convert.test.mjs
notes_md.test.mjs
preview_server.test.mjs
process_hygiene.test.mjs
test_element3d_pptx.py
test_notes_md.py
test_webgl_capture.mjs
build_pptx.py
conftest.py
export_all.mjs
lib/
__init__.py
__pycache__/
deck_source.cpython-313.pyc
dist_dir.cpython-313.pyc
__tests__/
__init__.py
deck_source.test.py
dist_dir.test.mjs
dist_dir.test.py
test_fonts.py
test_layout.py
test_morph_xml.py
test_speaker_notes.py
deck_source.mjs
deck_source.py
dist_dir.mjs
dist_dir.py
dwell.mjs
ffmpeg_convert.mjs
fonts.py
fps_monitor.mjs
layout.py
morph_xml.py
notes_md.mjs
notes_md.py
preview_server.mjs
process_hygiene.mjs
recorder.mjs
slide_builder.py
speaker_notes.py
stage_capture.py
pptx_renderers/
__init__.py
__tests__/
__init__.py
test_base.py
test_group_renderers.py
test_shape_renderers.py
test_text_renderers.py
_base.py
_colors.py
_custom_placeholder.py
caption.py
card.py
connector_chip.py
element3d.py
footer_strip.py
image.py
kpi.py
logo.py
orbit_group.py
pillar.py
pipeline_group.py
quote.py
stat_group.py
wordmark.py
record_deck.mjs
package.json
plugin.json
primitives/
__tests__/
Element3D.test.tsx
manifest.test.cjs
_internal/
Element3DInner.tsx
Card.tsx
Chart.tsx
ConnectorChip.tsx
connectors/
confluence.tsx
drive.tsx
github.tsx
index.ts
jira.tsx
linear.tsx
notion.tsx
onedrive.tsx
salesforce.tsx
slack.tsx
teams.tsx
types.ts
Diagram.tsx
Element3D.tsx
Element3DOverlay.tsx
FooterStrip.tsx
Icon.tsx
Image.tsx
index.ts
KPI.tsx
Logo.tsx
MorphChart.tsx
OrbitGroup.tsx
Pillar.tsx
PipelineGroup.tsx
presets3d/
__tests__/
Lattice3D.test.tsx
OrbitPoints3D.test.tsx
index.ts
Lattice3D.tsx
OrbitPoints3D.tsx
Quote.tsx
StatGroup.tsx
Wordmark.tsx
README.md
scripts/
__tests__/
acceptance-phase2.test.mjs
acceptance-stacklink.test.cjs
clarify.test.cjs
compare.test.cjs
diff-applier.test.cjs
dsl-parser.test.cjs
examples-build.test.cjs
from-example.test.cjs
iterate.test.cjs
palette-extractor.test.cjs
primitive-manifest.test.cjs
qa-cost.test.cjs
qa-prompt.test.cjs
qa-runner.test.cjs
reference-registry.test.cjs
render-stages.test.mjs
router.test.cjs
token-merger.test.cjs
verify-loop.test.cjs
clarify.cjs
compare.cjs
composer.cjs
diff-applier.cjs
dsl-parser.cjs
from-example.cjs
install-hook.cjs
iterate.cjs
palette-extractor.cjs
primitive-manifest.cjs
qa-prompt.cjs
qa-runner.cjs
reference-registry.cjs
render-stages.mjs
router.cjs
token-merger.cjs
tokens-emitter.cjs
verify-build.cjs
verify-loop.cjs
verify-render.cjs
skills/
morph-deck/
SKILL.md
themes/
__tests__/
themes.schema.test.cjs
bunq-mint-light.json
linear-light.json
minimal-mono.json
playful-poster.json
stacklink-dark.json
README.md
scaffold-template/
__tests__/
scaffold-files.test.cjs
.gitignore
bun.lock
index.html
package.json
postcss.config.js
scripts/
__tests__/
lint-layout.test.cjs
sync-notes.test.cjs
lint-layout.cjs
sync-notes.cjs
src/
App.tsx
deck/
__tests__/
Canvas.test.tsx
Caption.test.tsx
custom-loader.test.ts
pace.test.ts
stages.schema.test.ts
tokens.test.ts
Canvas.tsx
Caption.tsx
components/
OverlapDebugOverlay.tsx
Deck.tsx
elements/
elements.tsx
custom/
.gitkeep
customRegistry.ts
index.ts
loader.ts
frames.tsx
hooks/
__tests__/
useOverlapResolver.test.tsx
safeZones.ts
useOverlapResolver.ts
pace.ts
stages.ts
StepIndicator.tsx
tokens.ts
index.css
main.tsx
tailwind.config.ts
tsconfig.json
vite.config.ts© 2026 Flowy · Free and open source
Built for Claude Code · Not affiliated with Anthropic