Skills motion-canvas-agent
Agent tooling for Motion Canvas — seek, screenshot, scene graph inspection, settings control, and rendering via HTTP API. Requires a browser with the editor open.
install
source · Clone the upstream repo
git clone https://github.com/VideoZero/skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/VideoZero/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/motion-canvas-agent" ~/.claude/skills/videozero-skills-motion-canvas-agent && rm -rf "$T"
manifest:
motion-canvas-agent/SKILL.mdsource content
Motion Canvas Agent Plugin
Full programmatic control of a running Motion Canvas editor via HTTP. Seek to any frame, capture screenshots, inspect the scene graph, change resolution/fps/background, and trigger rendering — all without browser automation.
Architecture
Agent (curl/script) ──HTTP──▶ Vite Server (agent-plugin.ts) ──HMR WS──▶ Browser (agent-client.ts) │ │ ▼ ▼ screenshots/ Player + Renderer (PNG files) + ProjectMetadata
Setup
1. Copy plugin files into your project
→ project rootassets/agent-plugin.ts
→assets/agent-client.tssrc/
2. vite.config.ts
import {defineConfig} from 'vite'; import motionCanvas from '@motion-canvas/vite-plugin'; import {agentPlugin} from './agent-plugin'; export default defineConfig({ plugins: [ motionCanvas(), agentPlugin({screenshotDir: './screenshots'}), ], });
3. project.ts
import {makeProject} from '@motion-canvas/core'; import {agentClient} from './agent-client'; export default makeProject({ plugins: [agentClient()], scenes: [...], });
4. Start + open browser
npm start # Open http://localhost:9000 in a browser
HTTP API Reference
Base URL:
http://localhost:9000/__agent
Playback Control
| Method | Endpoint | Body | Response |
|---|---|---|---|
| | — | |
| | | |
| | — | |
| | — | |
| | — | |
| | — | |
Screenshots
| Method | Endpoint | Body | Response |
|---|---|---|---|
| | | |
| | — | |
Settings
| Method | Endpoint | Body | Response |
|---|---|---|---|
| | — | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
Rendering
| Method | Endpoint | Body | Response |
|---|---|---|---|
| | | |
| | — | |
Scene Info
| Method | Endpoint | Body | Response |
|---|---|---|---|
| | — | |
| | — | (recursive node tree) |
| | — | |
Errors
| Method | Endpoint | Body | Response |
|---|---|---|---|
| | — | |
| | — | |
Scene Graph Format
GET /__agent/scene-graph returns a recursive tree:
{ "scene": "my-scene", "graph": { "type": "View2D", "key": "my-scene/View2D[1]", "position": {"x": 960, "y": 540}, "size": {"width": 1920, "height": 1080}, "children": [ { "type": "Rect", "position": {"x": 0, "y": 0}, "size": {"width": 400, "height": 300}, "fill": "#1E293B", "children": [ { "type": "Txt", "text": "Hello World" } ] } ] } }
Each node includes:
type, key, position, size, opacity (if not 1), fill, text (if applicable), and children.
AI Agent Workflow
# 1. Check connection curl -s localhost:9000/__agent/status # 2. Set resolution curl -s -X POST localhost:9000/__agent/settings/size \ -H "Content-Type: application/json" -d '{"width": 1920, "height": 1080}' # 3. Seek to a frame curl -s -X POST localhost:9000/__agent/seek \ -H "Content-Type: application/json" -d '{"frame": 60}' # 4. Screenshot curl -s -X POST localhost:9000/__agent/screenshot \ -H "Content-Type: application/json" -d '{"name": "check-1"}' # → Read ./screenshots/check-1.png # 5. Inspect scene graph curl -s localhost:9000/__agent/scene-graph # 6. Check which scene we're in curl -s localhost:9000/__agent/scenes # 7. Check errors curl -s localhost:9000/__agent/errors # 8. Change background curl -s -X POST localhost:9000/__agent/settings/background \ -H "Content-Type: application/json" -d '{"color": "#000000"}' # 9. Trigger render curl -s -X POST localhost:9000/__agent/render
Security
- Localhost only: The agent API runs on the Vite dev server which binds to localhost by default. Do not expose it to the network (avoid
in production)--host 0.0.0.0 - Screenshot paths: The screenshot name is sanitized — path separators and dots are stripped, and the resolved path is verified to stay inside the configured
screenshotDir - Scene graph text: Text content extracted from the scene graph is sanitized (control characters stripped, truncated to 100 chars). Treat scene graph data as untrusted when processing it
How It Works
- Runtime plugin (
) usesagentClient()
,Plugin.player()
, andPlugin.renderer()
callbacks to capture the Player, Renderer, and Project instancesPlugin.project() - Player provides seek, frame stepping, playback control, current scene, duration
- ProjectMetadata provides
(background, range, size),shared
(fps, scale), andpreview
(fps, scale, exporter) settings viarendering
/.get().set() - Renderer provides
andrender(settings)
for exportabort() - Scene graph is traversed via
recursively, serializing type, position, size, fill, text, opacityscene.getView().peekChildren() - Communication uses Vite's HMR WebSocket
Files
| File | Copy to | Purpose |
|---|---|---|
| Project root | Vite plugin — HTTP endpoints + WS relay |
| | Runtime plugin — Player/Renderer/Project control + canvas capture |