cd /news/ai-agents/how-i-created-a-claude-plugin-to-cre… · home topics ai-agents article
[ARTICLE · art-132674] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

How I created a Claude plugin to Create Demo Videos

A developer built a Claude plugin that automates the creation of demo videos, combining Node scripts, a Remotion template, and a small MCP server to handle narration, avatar generation, screen capture, and rendering. The tool uses a two-pass approach—an unrecorded rehearsal where Claude drives the app via MCP tools to produce a verified action script, followed by a deterministic runner that records with eased cursor motion—to eliminate dead air. It integrates fal.ai and ElevenLabs APIs for voices and sound effects, with all video state stored in a single demo.json manifest.

by read7 min views1 publishedSep 17, 2026

tldr; I asked Claude Fable (in plan mode) to screen record and create cool demo videos for my projects. It worked and now I never have to open a video editor again.

The plugin has Node scripts plus a Remotion template plus a small MCP server.

scripts/
  doctor.mjs          preflight: keys, ffmpeg, Chromium, macOS permissions
  plan.mjs            demo.json manifest + a cost estimate before anything is spent
  gen/tts.mjs         narration (fal.ai or ElevenLabs), word timestamps
  gen/presenter.mjs   the on-camera avatar, lip-synced to that narration
  gen/broll.mjs       image-to-video b-roll
  gen/sfx.mjs         ElevenLabs sound effects: whoosh, pop, riser
  capture/web-*.mjs   Playwright capture with a drawn cursor
  capture/mac-*.mjs   real screen recording + cliclick input
  capture/cli-*.mjs   a staged Terminal window, retimed to the voice
  edit/retime.mjs     stretch a raw take to the narration length
  edit/composite.mjs  layered meme cold opens (slow-mo, cutouts, freeze frame)
  render/render.mjs   Remotion
  qa.mjs              frame dumps, secret scan, PySceneDetect pacing check

The scripts call the fal.ai API****and also ElevenLabs (optional) for voices. You bring your own API keys.

Everything for a video lives in one demo.json. If state only exists in Claude's context, it's gone on the next run, so every script reads and writes the manifest. Artifacts are cached by a hash of their inputs. Change one line of narration and one audio file regenerates, not the video.

The first version recorded Claude while it explored the app. It was too slow, you would get three seconds of nothing, a click, three seconds of nothing.

The fix was two passes. In the rehearsal, Claude drives the app through MCP tools (screenshot, decide, act, screenshot) and nothing is recorded. The output is an action script with verified selectors and coordinates. Then a deterministic runner performs that script with eased cursor motion and human typing cadence while recording. No model in the loop, so no dead air.

node scripts/capture/web-perform.mjs \
  --actions demo/launch/actions/create.json \
  --out demo/launch/clips/create.mp4 \
  --target-duration 12.1 \
  --timestamps demo/launch/audio/create.words.json

Narration is generated before anything is captured. Once a line is spoken you know exactly how long it is, so the capture can be paced to land on it, instead of cutting footage to fit a voiceover afterwards. With word-level timestamps a click can be pinned to the exact word that describes it.

The same audio drives the presenter. The avatar is animated to the narration file that plays over the screen segments, so the narrator and the person on camera are audibly one person. It's one voice for the whole video, and that rule never bends.

Claude tried doing the edits in ffmpeg. I asked him if there was a better way, and he said Yes.

Claude decided ffmpeg should do trimming, cropping and loudness, and Remotion does everything else. The template uses TransitionSeries with fade, wipe and slide. Transitions overlap the scenes they join, which means the finished video is shorter than the sum of its scenes. Claude said he spent a lot of tokens on fixes for that: get things wrong and the last scene is truncated. So he made a helper compute the overlap for both the metadata and the render. (whatever that means)

Narration is laid out on an absolute timeline rather than inside each scene, for the same reason. Visuals may overlap in a transition. Two voices overlapping is instantly audible.

The capture event log goes into the render as props, so Remotion knows where every click landed and can zoom the frame toward it. Captions come from the word timestamps. None of the components do file I/O; a build-props step validates every artifact exists on disk and inlines the data, so a missing clip is a clear error and not a black rectangle. Claude really is smart.

Claude kept failing, until I had him use PySceneDetect to measure reference videos. Analyze example Shorts and you get numbers: 17 to 24 shots in 28 to 37 seconds, a cut every 1.3 to 1.7 seconds, the hook cutting away from the face within a second, nothing held longer than 2.5 seconds. Those numbers became the listicle style's rules. The manifest validator now warns when a shot holds too long.

The same trick built the dynamic tutorial style. One reference tutorial: 48 shots in 268 seconds, about 40% full-frame face, 40% tall side panel, 20% corner card, every move a 0.2s ease-out. Now "more like this" means a style with a beat sheet.

And qa.mjs runs PySceneDetect over the finished render to check the rhythm actually landed:

pacing: 21 shots, 1.48s average — inside the 1.3-1.7s target

I didn't want a stock AI face. So I gave Claude a selfie and asked it to make a presenter out of me.

Me: Make an AI influencer of me, cool hair, clear skin, just better looking version of me.

Claude: Understood, fixing your jawline.

Me: ☠️

The workflow is still.mjs, which generates or edits a still through fal.ai's image models. A still costs cents, a video costs dollars, so you iterate on the image until it's right and only then animate it. The face is generated once and stored on the manifest. Regenerating it per scene gives you a subtly different person in every shot, which is far creepier than a slightly static one.

Animation is one step: image plus narration audio into a talking-head model (Kling is default since it handles input audio). Claude tried the other way, generate a video of a person and lip-sync it after, and it fights itself. Claude Fable told me it didn't look good, so I trusted him. If it was Claude Opus I wouldn't trust a word he said.

After a few videos published on TikTok the avatar needed new clothes. Every video showing the same shirt in the same room looks like one video posted repeatedly, so there's a wardrobe.json of looks, each generated and approved by me.

As I tried different video types and examples for Claude to mimic the capabilities grew. Nine named styles so far. Five wide, for YouTube, a landing page or a README: launch, anchor, tutorial, dynamic, explainer. Four vertical, for Shorts, Reels and TikTok: listicle, cohost, flashcard, glide. A style seeds the format, presenter mode, caption style and transition policy. Anything it sets can be overridden per scene.

A Short is not the demo re-rendered at 9:16. It's its own 15 to 45 second cut in a sibling shorts.json that shares the project's clips, audio and cache. Screen captures are reframed for free. Narration lines kept verbatim are cache hits.

Each Short also renders a typographic hook card as frame 0, held half a second and wiped away. Vertical platforms grab an early frame as the thumbnail and when posting through an API I couldn't override it, so frame 0 has I wanted to start with a banner overlay.

It can film web apps through Playwright, native Mac apps through real screen recording, and terminal programs in a staged Terminal window. That last one means it can demo a Claude Code plugin from inside a live claude session, which is how the plugin's own videos were made.

I've seen a lot of startups sell subscriptions where you can generate a set number of videos for product promotion. The problem with those cloud services is they don't know your codebase, they can't drive your app, and the branding/colors and all assets would need to be handed off to their cloud agent before anything can even be started. Claude Code running on your Mac on the other hand has none of those problems - you have a concept for a demo video and Claude has all the tools needed to shoot a demo, understand what is actually being demonstrated and to stay on brand.

The other things is video generation is expensive. I'd have to markup the cost - usually I need to pay $1.50 in Fal/Eleven API costs to create a minute long video, so anything I charge per video would need to be over that. Then handle customer support, people who don't like how the video turned out and other problems and it seemed like too much of a hassle.

So it's free on github - you of course still need to pay Fal for credits to generate video. If you want to try it, the project is a Claude Code plugin, a Codex plugin and an npx skills skill. Each host reads a different manifest, and agents without an MCP client reach the rehearsal server through a shell script.

The code is MIT and it's all here: github.com/mrieck/demoday-claude-plugin. If you find it useful, give the github repo a star.

── more in #ai-agents 4 stories · sorted by recency
── more on @claude 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/how-i-created-a-clau…] indexed:0 read:7min 2026-09-17 ·