Claude Code can make videos: it records the app, narrates with ElevenLabs, and syncs audio to video automatically
I'm a solo builder. I needed a 2-minute product demo for ClinTrialFinder — a free tool I built that matches cancer patients to clinical trials. I can fumble through OBS and iMovie, but I'm not proficient — and Claude Code does it faster. So I asked Claude Code — an agentic coding tool — to make it. And it did: a narrated walkthrough where the voiceover lands exactly on the on-screen action. I never opened a screen recorder. I never opened a video editor. I never manually lined up a single caption to a single frame. Here's the video it produced . This post is about the three things the agent did to make it — because I think that combination is new. 1. It recorded the app — no screen recording Instead of me screen-capturing a session by hand, the agent wrote a Playwright script that drives the real, live web app : it opens the site, fills out the 10-step patient wizard with a synthetic case, submits, and records the finished results page — all headless, straight to video. That means no manual take, no re-shooting when I fumble a click, no "oops the mouse jittered." The recording is code , so it's deterministic and repeatable. When the product changes, the agent re-runs the script and out comes a fresh clip. It even injected a fake cursor that glides between elements, because a headless recording has no real mouse pointer. 2. It generated the narration — no microphone I didn't record a voiceover. The agent wrote the narration script, then called the ElevenLabs text-to-speech API to synthesize it in a clean, consistent voice. If I want to change a line, it edits the text and regenerates that clip in seconds — no re-recording, no "let me find a quiet room," no matching my tone across takes. // the agent calls ElevenLabs per narration phrase const res = await fetch ( `https://api.elevenlabs.io/v1/text-to-speech/ ${ VOICE } ` , { method : ' POST ' , headers : { ' xi-api-key ' : KEY , ' Content-Type ' : ' application/json ' }, body : JSON . stringify ({ text , model_id : '