Marcus Johansson published a Claude Code skill called drupal-tutorial-video. You point it at a Drupal module and it produces a narrated 1920×1080 MP4 of the setup: a real browser, a visible cursor, text typed character by character, an ElevenLabs voice-over, a caption bar across the bottom, all concatenated into one video. I watched the output and had two thoughts at once. First: this is great. Second: why is this only for Drupal?
What Marcus built
The clever part of the original is how it makes the cursor look human. It runs a headless browser inside the ddev web container on a virtual display, and it splits the work between two tools. One is agent-browser, the brain. It reads the page’s accessibility tree and hands back the on-screen coordinates of an element, but its clicks are synthetic and invisible.
The other is xdotool, the hands. It moves the real X11 pointer to those coordinates in small steps, clicks, and types with a per-keystroke delay. Because the pointer is real, ffmpeg captures it. What moves on screen is exactly what clicks.
It has a second good idea baked in: it records one beat at a time, a sentence of narration and its matching action, and it length-fits each beat’s video to its narration so the words never drift out of sync with the picture. Terminal commands it won’t record at all; those become still “command cards” instead. And it’s Drupal all the way down. It reads .info.yml files and config forms to derive the real setup steps, and pre-seeds Drupal’s AJAX forms with drush so they behave on camera.
A great foundation and example, but different than my needs
My job is different. I make short training videos about AI tooling. How to add an MCP server in Claude Code, how to use one in Claude Desktop, etc. And for that, Marcus’s skill was the wrong shape in three specific ways:
- It refuses to record terminals. But Claude Code is a terminal. The thing I most need to show is the exact thing it turns into a static card.
- It records the browser only inside a ddev Linux container. Claude Desktop is a native macOS app. It can’t live in that container.
- It’s Drupal-specific end to end: the reads, the pre-seeding, the assumptions.
So I did what you do when a tool is 80% right: I kept the ideas and rebuilt the shape. The result is two skills.
screencast-storyboard is the authoring half. You tell it what the demo should cover; it reads the tool’s real README, install command, and config, drafts a storyboard, and then stops at an approval gate.
screencast-tutorial-video is the production half, and it runs natively on the macOS host with no container. The core insight I took from Marcus is that you don’t need one recording rig. You need the right engine per surface:
- Terminal → a VHS
.tapefile. Declarative typing, deterministic, and it re-renders in seconds. - Native app (Claude Desktop) → ffmpeg still-motion: a screenshot with an optional zoom and a highlight box.
- Browser → Playwright to locate and drive, recorded at 1080p.
- Abstract command → a command card, same as the original.
I also expanded the option to use ElevenLabs or OpenAI for the voice-over.
Using presets for theming
Once it worked, I wanted the next video to start where this one left off. I wanted to be able to define the same voice, same pronunciation, same intro card without re-deriving any of it.
So the skill loads a preset: a small file of house defaults (engine, voice, tone, resolution) plus a brand-notes doc for the parts that can’t be an environment variable, like the pronunciation lexicon and the intro/outro pattern.
Point it at a different preset and you get a different client’s or team’s style. There’s a short guide in the repo for writing your own.
See it in action
Here is the demo video, produced end to end by the skills themselves:
Credits and code
Thanks to Marcus (ivanboring) for the original drupal-tutorial-video. I tried a few months ago to build a skill like this and failed spectacularly.
The skill is on GitHub, MIT-licensed, and works on a stock macOS setup: github.com/kanopi/screencast-skills.