Turn any source file — or any git diff — into a cinematic, syntax-highlighted video. One CLI command. Zero video editor.
npx codemotion render app.js --theme dracula↓ this is what that command outputs ↓
https://github.com/user-attachments/assets/55826b34-da22-4a20-89d3-298a3f4c0cae
You ship something you're proud of. You go to show it off — and all you've got is a flat screenshot or a boring, laggy screen recording. Meanwhile every other "cool tool" launch on X/LinkedIn has that smooth, cinematic typing animation that makes code look like it matters.
codemotion render app.js --theme dracula
codemotion diff app.js --from HEAD~1 --to HEAD --theme tokyo-nightThat's it. No After Effects, no manual screen recording, no editing timeline. You get a polished .mp4/.gif in seconds, ready to drop straight into a README, a tweet, or a LinkedIn post.
| 🖋️ Typewriter engine | Code appears like it's being live-typed — syntax-correct from character #1, no flicker, no re-tokenizing broken code mid-animation. |
| 7 built-in cinema themes | dracula · one-dark-pro · github-dark · nord · monokai · catppuccin-mocha · tokyo-night |
| Git Diff Animator | Point it at a commit. Get back a red/green animated diff reveal, fully syntax-highlighted, line by line. |
| Cinematic camera | Subtle breathing zoom/drift on the editor window + entrance fade + auto-scroll that follows the action — nothing ever clips off-screen. |
| One command, done | No timeline. No export settings hell. render or diff in, .mp4/.gif out. |
git clone <this-repo>
cd codemotion
npm install
npm link # unlocks the global `codemotion` commandFirst run:
@remotion/rendererdownloads a headless Chromium binary — needs a real internet connection, won't work inside network-locked sandboxes/CI without extra setup.Older Mac? Recent Remotion builds require macOS 15 (Sequoia)+. If you're on an older machine, this repo's
package.jsonis already pinned to4.0.215, a version that predates that requirement — justnpm installas-is and you're covered. Full details in Troubleshooting.
codemotion render <file> [options]| Flag | What it does | Default |
|---|---|---|
-t, --theme <theme> |
dracula | one-dark-pro | github-dark | nord | monokai | catppuccin-mocha | tokyo-night |
dracula |
-f, --fps <fps> |
Frames per second | 60 |
-s, --speed <chars/sec> |
Typing speed | 28 |
-o, --out <path> |
Output .mp4 or .gif |
out/output.mp4 |
-w, --width / --height |
Video resolution | 1920x1080 |
codemotion render examples/hello.js --theme dracula --out out/demo.mp4codemotion diff <file> [options]| Flag | What it does | Default |
|---|---|---|
--from <ref> |
Diff starting ref | HEAD~1 |
--to <ref> |
Diff ending ref | HEAD |
--staged |
Animate staged changes instead of a ref range | off |
-t, --theme <theme> |
Same theme list as above | dracula |
-l, --lines-per-second |
Line reveal speed | 2.5 |
-o, --out <path> |
Output .mp4 or .gif |
out/diff.mp4 |
codemotion diff src/index.js --from HEAD~1 --to HEAD --theme github-dark
codemotion diff src/index.js --staged --theme tokyo-nightnpm run studioOpens Remotion Studio — scrub the timeline, tweak the composition, hot-reload changes instantly.
source file / git diff
│
▼
┌───────────────────┐ Highlight ONCE, correctly — full Shiki pass,
│ highlighter.js / │ never re-tokenized on broken/partial code.
│ diffHighlighter.js│ Output: flat { char, color } array.
└─────────┬─────────┘
▼
┌───────────────────┐ Each video frame just reveals the first N
│ Remotion component │ characters/lines of the pre-computed array.
│ (React → frames) │ Color is always right — computed once, upfront.
└─────────┬─────────┘
▼
┌───────────────────┐ Headless Chromium renders every frame,
│ @remotion/renderer│ ffmpeg stitches them into .mp4 / .gif.
└───────────────────┘
The key design decision: most typewriter-video tools re-highlight code on every frame as it's being "typed" — which means for most of the animation, the code is syntactically broken (an unclosed bracket, a half-written string), so the highlighter guesses wrong and colors flicker. CodeMotion highlights the finished code once, then just reveals characters of that already-correct result. Zero flicker, by construction.
Both render and diff share one render pipeline (renderComposition() in src/cli.js) and one theme system (remotion/themes.js) — the diff animator isn't a bolt-on, it's built on the exact same foundation.
codemotion/
├── src/
│ ├── cli.js # commander CLI — `render` and `diff` commands
│ ├── highlighter.js # file → per-character highlighted array
│ ├── diffParser.js # raw `git diff` text → typed line array
│ └── diffHighlighter.js # typed lines → per-character highlighted lines
├── remotion/
│ ├── index.jsx # registers both compositions
│ ├── themes.js # shared theme/color definitions
│ ├── TypewriterComposition.jsx
│ └── DiffComposition.jsx
└── examples/hello.js # sample file to test-render immediately
Remotion requires macOS 15 (Sequoia) or later
Recent Remotion releases need a newer native compositor binary. On older Macs, pin to a version that predates the requirement:
npm install remotion@4.0.215 @remotion/cli@4.0.215 @remotion/bundler@4.0.215 @remotion/renderer@4.0.215
rm -rf node_modules package-lock.json && npm installnpm link fails with EACCES
Your global npm folder isn't owned by your user. Either sudo npm link, or (cleaner) redirect npm's global prefix to your home folder:
mkdir ~/.npm-global && npm config set prefix '~/.npm-global'
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.zshrc && source ~/.zshrcnpm warns about esbuild's install script not being approved
npm 11.16+ requires explicit approval for dependency install scripts. Approve everything for this project once:
npm approve-scripts --all
npm installcodemotion diff says "No diff found"
Make sure the file is inside an actual git repo with at least two commits, and that the path is relative to where you're running the command (or the repo root). --from HEAD~1 needs a previous commit to compare against.
- v0.1 — Typewriter engine
- v0.2 — 7 themes, camera drift/breathing, auto-scroll polish
- v0.3 — Git Diff Animator, syntax-highlighted, red/green line reveal
- v0.4 — Optional mechanical key-click sound synced to reveal frames
- v0.5 — 3D-perspective diff mode (once v0.3 has real-world mileage)
Got an idea? Open an issue — this is early and every bit of direction helps.
- Remotion, not raw ffmpeg scripting — the video is a React component, so every visual idea (camera moves, easing, new themes) is CSS/React, not hand-calculated ffmpeg filter graphs.
- Shiki, not Prism.js — ships real VS Code themes pixel-for-pixel, not an approximation.
Issues and PRs welcome. If you're adding a theme, drop it in remotion/themes.js with bg, window, accent, added, removed — that's the whole contract.
MIT — use it, fork it, ship videos with it.
Built by Faysal / DieBack Theatre.
If this saved you from opening a screen recorder, a ⭐ helps other people find it.