Programmatic video from Lua. No browser. No React scaffold.
One .lua file → headless LÖVE → ffmpeg → mp4.
GitHub ·
Verification ·
Agent skill ·
npx skills add shinyobjectz/cadence
Cadence is a seek-not-playback motion framework: compositions are pure functions of time. Agents author .lua files; the renderer evaluates any frame in any order; verification runs in milliseconds before you ever encode.
git clone https://github.com/shinyobjectz/cadence.git && cd cadence
cd desktop && pnpm install && cd ..
# environment check
bin/cadence doctor
# instant compile (wasmoon, ~30ms)
cd evals/projects/launch-spot
../../bin/cadence verify comps/launch.lua --wasm-only
# render
../../bin/cadence render comps/launch.lua -o out.mp4Install the agent skill (Cursor, Claude Code, Codex, Copilot, …):
npx skills add shinyobjectz/cadence| Command | What it does |
|---|---|
cadence verify comp.lua --json |
Compile → lint → check pipeline |
cadence verify … --wasm-only |
Instant tier-0 compile feedback |
cadence doctor |
Probe love, ffmpeg, wasmoon, project layout |
cadence feedback comp.lua |
Agent-readable summary + next steps |
cadence lint / check |
Static + pixel verification (--json) |
cadence render |
Offline encode to mp4 |
All verification commands emit cadence.result/v1 JSON — structured findings agents can parse without reading stack traces.
bin/cadence-vision is an MCP server (registered in .mcp.json) that shows a
comp, clip or image to any vision or video model in the shape it reads best:
per-model profiles, keyframes, labeled contact sheets, numbered marks bound to
the comp's own node ids, scene text, diffs, and Depth Anything 3 depth and
multi-view geometry with rendered top/iso views. bin/vision-setup builds its
venv; bin/cadence-vision call TOOL k=v runs any tool from the shell.
Design and measurements: docs/VISION.md.
local e = require("cadence")
return e.comp {
width = 1080, height = 1920, duration = 6, fps = 30,
background = "#0B0D12",
scene = function(s)
local title = s:text { x = 540, y = 960, text = "cadence", size = 120,
color = "#5EEAD4", anchor = "center", opacity = 0 }
s:script(function(t)
t:tween(title, 0.8, { opacity = 1, size = 140 }, "backOut")
end)
end,
}- Deterministic by construction — no clocks, no I/O in comps; RNG seeded
- Agent-first — lint/check/verify JSON, skill on skills.sh
- ~10MB engine — vendored LÖVE fork, not headless Chrome
- Three hosts, one API — native encode, wasmoon preview, Rust helpers
Frames are painted by cadence-scene (vello_cpu + parley): one rasterizer for
text, shapes, images, html, vector, masks, blends, shadows, colour effects, the
fx chain and video, with no GPU readback. World (wgpu), perspective and the
GLSL escape hatches (shadertoy, worley, s:draw) render through love into
image slots inside the same frame. CADENCE_SCENE=0 selects the old love
canvas path. Details, coverage and measurements: docs/SCENE.md.
bin/golden capture|compare holds per-frame hashes across renderer changes.
| Path | Purpose |
|---|---|
bin/cadence |
CLI entry (render, verify, doctor, …) |
lib/cadence/ |
Host-free authoring API |
runtime/ |
LÖVE offline host (scene.lua = bridge to the rasterizer) |
scene/ |
cadence-scene: the vello_cpu + parley rasterizer |
desktop/ |
Tauri + React editor (optional) |
skills/cadence/ |
Official agent skill |
evals/ |
Public visual suite |
This project was formerly ellua. The Lua module alias require("ellua") remains for compatibility; new work should use cadence naming. The archived repo: github.com/shinyobjectz/ellua.
MIT — see LICENSE if present, otherwise check repo root.


