
examples/merge_sorted.py: the merge is simulated in Python, then each step becomes keyframes.
Key features¶
- The scene is a pure function of time.
state(t)resolves every property att. Nothing accumulates between frames, so every frame renders independently and in parallel, and a scrub to anytis exact. - Pydantic models are the schema. JSON is the product contract; the Python API is sugar over the same
models.
buttery schemaprints the JSON schema an agent can build against. - Properties are expressions, not values. Tweens, keyframes,
sin(6 * T), and references to other objects' properties (ring.x = dot.ref.x) form a dependency DAG, so edges follow nodes for free. Shorthand strings like"dot.r + 0.5"parse into the same tree, noeval. - Built for agents.
validate/state/preview/renderas a CLI, a Python API, and an MCP server. Every call returns{"ok": true, ...}or a structured error list, never a bare stack trace. A Claude Code skill is included. - Explainer primitives.
circle rect line text group, and acodeblock that syntax-highlights Python and lets spans select by token, line, or character range. - Validation up front. Structural checks from pydantic (unknown fields, arity, colors) plus semantic checks: unique ids, references resolve, no dependency cycles.
- Real motion blur. A skia-python renderer samples sub-frames across a configurable shutter, uses every
core, and writes an
.mp4through ffmpeg or a PNG sequence without it.
Thirty seconds of buttery¶
from buttery import *
dot = Circle("dot", r=0.3, fill="coral")
dot.x = tween(-3, 3, at=0, dur=1.5, ease="out_cubic")
dot.y = 0.2 * sin(6 * T)
ring = Circle("ring", fill=None, stroke="white")
ring.x = dot.ref.x
ring.r = dot.ref.r + 0.5
scene = Scene(duration=3).add(dot, ring, Text("label", content="Hello", y=-1.6))
scene.render("out.mp4")
The same scene as JSON, which is what an agent writes:
{
"duration": 3,
"objects": [
{"id": "dot", "type": "circle", "r": 0.3, "fill": "coral",
"x": {"op": "tween", "keys": [[0, -3], [1.5, 3]], "ease": "out_cubic"},
"y": "0.2 * sin(6 * t)"},
{"id": "ring", "type": "circle", "fill": null, "stroke": "white", "x": "dot.x", "r": "dot.r + 0.5"},
{"id": "label", "type": "text", "content": "Hello", "y": -1.6}
]
}
Where to go next¶
- Install — pip, uv, ffmpeg, and running from a clone.
- Python — the authoring API: objects, expressions, tweens, references.
- Scenes — the JSON format and the full reference of primitives, ops, and eases.
- Agents — the CLI, the MCP server, and the Claude Code skill.
- Examples — every example with the prompt that produced it.
- Build your own — reconstruct the core in about 200 lines and see why it is shaped this way.
Architecture¶
Agent tool surface validate / state / preview / render (tools.py, cli.py, mcp_server.py)
Authoring Python sugar <-> JSON (objects.py, expr.py, parse.py)
Core Scene, primitives, expression DAG (scene.py, evaluate.py)
Renderer skia-python, motion blur via sub-frames (render.py)
Not in v1¶
Equations/LaTeX, 3D or cameras, GUI, audio, plugins, manim parity.


