@devmotion/cli
v0.8.0
Published
HTML-first, agent-friendly video tooling. Write HTML. Render video.
Maintainers
Readme
@devmotion/cli
HTML-first, agent-friendly video tooling. Write HTML. Render video.
DevMotion turns a directory of HTML files into an animated MP4. Every element
with data-dm-* attributes becomes a layer on the timeline. The Studio
(visual editor) and the CLI render share the exact same engine — what you see
in preview is what you get in the MP4.
npx @devmotion/cli init my-video
cd my-video
devmotion preview # open the editor in your browser
devmotion render # produce ./output.mp4Install
npm i -g @devmotion/cli
# or use it without installing
npx @devmotion/cli <command>Requirements
Only Node.js ≥ 20. Everything else (ffmpeg, Playwright Chromium) is installed automatically:
@ffmpeg-installer/ffmpegships a platform-specific ffmpeg binary as a regular dependency — nobrew,apt, orwingetneeded.- A
postinstallscript downloads Playwright Chromium (~150 MB, one-time). Skip it withDEVMOTION_SKIP_POSTINSTALL=1if you don't intend to render (preview still works).
Run devmotion doctor to verify both are wired up.
Commands
| Command | Purpose |
| ----------------------------------- | ---------------------------------------------------------- |
| devmotion init <name> | Scaffold a new project (devmotion.json + scenes/) |
| devmotion preview [--port 5173] | Open the Studio in the browser, hot-reloads on file change |
| devmotion render [--output X.mp4] | Render to MP4 (auto-spawns Studio if not running) |
| devmotion add-scene <name> | Append a new scene, --with gsap/lottie/bare |
| devmotion mcp | Run the local MCP server over stdio |
| devmotion mcp --print-config | Print a stdio MCP config snippet |
| devmotion doctor | Check ffmpeg & Playwright are installed |
Project shape
my-video/
├── devmotion.json # project config (size, fps, scenes)
├── scenes/
│ ├── intro.html # one HTML file per scene
│ └── outro.html
└── assets/ # images, videos, fonts, lottie JSONdevmotion.json
{
"version": 1,
"name": "my-video",
"width": 1920,
"height": 1080,
"fps": 30,
"duration": 10,
"background": { "type": "solid", "color": "#0a0a0a" },
"scenes": [{ "id": "intro", "file": "scenes/intro.html", "start": 0, "duration": 10 }]
}Scene HTML — data-dm-* protocol
Every element annotated with data-dm-* becomes a layer:
<div
data-dm-id="title"
data-dm-enter="fade-in"
data-dm-enter-time="0.5"
data-dm-duration="0.8"
data-dm-easing="ease-out"
data-dm-keyframe-opacity="0:0@ease-out; 0.5:1@ease-out; 9:1; 10:0@ease-in"
style="color: white; font-size: 48px"
>
Hello DevMotion
</div>| Attribute | Description |
| ------------------------ | --------------------------------------------------- |
| data-dm-id | Unique layer id (referenced by mutations) |
| data-dm-enter | Entry preset (fade-in, slide-in-left…) |
| data-dm-exit | Exit preset |
| data-dm-enter-time | Start time (seconds) |
| data-dm-exit-time | End time (seconds) |
| data-dm-duration | Preset duration |
| data-dm-easing | Easing function |
| data-dm-keyframe-* | Per-property keyframes: "time:value@strategy" |
| data-dm-word-separator | Optional separator for word-reveal text keyframes |
| data-dm-grid-increment | Grid step for snap-grid quantized keyframes |
| data-dm-track | Timeline track (z-order) |
| data-dm-locked | Lock layer from edits |
| data-dm-hidden | Hide layer |
Keyframe strategies map to interpolation families automatically:
- Continuous easing:
linear,ease-out,ease-in-out,ease-out-quad, etc. - Discrete jumps:
step-start,step-end,step-mid - Quantized values:
integer,snap-grid(setdata-dm-grid-increment) - Text reveals for
props.content:char-reveal,word-reveal
<dm-text
data-dm-id="headline"
transition-effects="fade,slide-up,blur"
transition-duration="350"
transition-easing="ease-in-quad"
slide-distance="2.7"
blur-amount="0.78"
data-dm-keyframe-props-content="0:@char-reveal; 1.4:Welcome to DevMotion@char-reveal"
>
Welcome to DevMotion
</dm-text>For dm-text, transition-effects is a comma-separated list applied to each
new character/word as it appears. Useful effects include fade, blur,
scale, slide-up, slide-down, slide-left, and slide-right.
Premium <dm-*> elements
For richer visuals, use the built-in custom elements:
dm-phone, dm-laptop, dm-browser, dm-terminal, dm-captions,
dm-code, dm-video, dm-audio, dm-text, dm-image, dm-button,
dm-icon, dm-shape, dm-html, dm-mouse, dm-group.
<dm-phone
data-dm-id="demo"
data-dm-enter="slide-in-right"
data-dm-enter-time="1.5"
src="./assets/screen.mp4"
></dm-phone>Animation framework support
Scenes can include <script> blocks driving GSAP, Lottie, or any custom
animation library. DevMotion auto-detects the library, pauses its internal
clock, and drives it frame-by-frame from the timeline.
| Framework | Detected via | How it's driven |
| ------------------ | ---------------------------- | -------------------------------------------- |
| GSAP | window.gsap.globalTimeline | globalTimeline.seek(t, false) |
| Lottie / bodymovin | window.lottie | goToAndStop(t * 1000, false) per animation |
Detection is automatic — your scene HTML stays idiomatic, no DevMotion hooks or boilerplate. Multiple frameworks coexist on the same scene (e.g. GSAP for layout + Lottie for a logo).
Scaffold a scene with a framework template:
devmotion add-scene intro --with gsap # GSAP CDN + sample tween
devmotion add-scene logo --with lottie # bodymovin player + sample load
devmotion add-scene blank --with bare # empty bodyNeed support for another framework? Adapters live in
src/lib/layers/components/HtmlLayer.svelte
(FRAMEWORK_ADAPTERS) — a new adapter is ~10 lines and applies to every
project automatically once shipped.
MCP — let an agent edit your project
devmotion mcp runs a local MCP server over stdio. Agents (Claude Code,
Cursor, Windsurf, …) spawn it inside your project directory to create/edit/remove
layers, configure the project, group layers, and apply animation presets —
every mutation writes back to your HTML files surgically (preserving formatting,
comments, and <script> blocks). It does not require devmotion preview,
network access, an account, or an API key.
devmotion mcp --print-config # print the JSON config snippet to paste into your agentThe CLI MCP and the SaaS MCP share the same mutations.ts code path, so an
agent that knows how to drive one knows how to drive the other.
Install the Agent Skill and MCP configuration for Claude Code, Codex, or both:
npx @devmotion/cli setup
# Non-interactive:
npx @devmotion/cli setup --agent both --scope globalGlobal skills are installed to ~/.claude/skills/devmotion/SKILL.md and
~/.agents/skills/devmotion/SKILL.md. Use --scope project for repository-local
configuration. The skill prefers the type-safe MCP operations over editing scene
HTML by hand.
Two ways to use DevMotion
| | CLI / OSS (this package) | SaaS (devmotion.app) |
| ----------- | ------------------------------------------ | ------------------------ |
| Source | Local filesystem (devmotion.json + HTML) | Cloud database |
| Editor | devmotion preview (browser) | Hosted Studio |
| Render | Local ffmpeg + Playwright | Hosted GPU farm |
| Auth | None — all local | Account + plans |
| Agent (MCP) | Local stdio (devmotion mcp) | Remote HTTP |
The OSS path is meant for agents, devs, CI pipelines, and offline work. The SaaS path is the same engine with managed infrastructure.
License
Apache-2.0. See LICENSE.
