Skip to content
Productivity
Skill

/animation

Author animated technical explainer diagrams as .anim.json files for Nimbalyst's Animation editor. Use when the user wants to animate a diagram, show how a system/protocol/algorithm behaves over time, build a motion explainer, or turn a static architecture diagram into something

From plugin
nimbalyst
1.7k9 skills3 agents49 commands
Install
$ npx -y skills add nimbalyst/nimbalyst --skill animation --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/animation

Context preview

The summary Claude sees to decide when to auto-load this skill.

Author animated technical explainer diagrams as .anim.json files for Nimbalyst's Animation editor. Use when the user wants to animate a diagram, show how a system/protocol/algorithm behaves over time, build a motion explainer, or turn a static architecture diagram into something

SKILL.md

animation.SKILL.md
name: animation
description: Author animated technical explainer diagrams as .anim.json files for Nimbalyst's Animation editor. Use when the user wants to animate a diagram, show how a system/protocol/algorithm behaves over time, build a motion explainer, or turn a static architecture diagram into something that plays.

Animation - step-based explainer diagrams

`.anim.json` files open in Nimbalyst's Animation editor: a named scene plus an ordered list of steps that assign states to the scene's parts. You write plain JSON. Any agent can author or edit one with `Write` and `Edit` -- there is no binary format and no tool call required.

When to use this

  • Explaining how a system behaves **over time**: a request crossing a network, a consensus round, a cache filling, a build pipeline, a queue draining.
  • Turning a static architecture diagram into something that plays.
  • Showing a failure and a recovery: the retry, the rollback, the rejected review.

**Do not use it** when a static diagram says the same thing. If nothing changes between the first frame and the last, you want Excalidraw or a Mermaid block, not an animation.

The mental model

Three rules drive every decision in this format:

1. **The document says what is true when, never how to tween.** There are no keyframes, easing curves, or property tracks. You assign a *state* to a part, and CSS transitions interpolate. Adding motion means naming a state, not scripting a timeline. 2. **States are cumulative.** A step asserts only what changes; every part it does not mention keeps whatever the previous step left it in. Write deltas. **To turn something off you must explicitly set it back** -- it will not decay on its own. 3. **Ids are names, not handles.** `store`, `title-card`, `queueTask01`. You will reference them constantly in `set` blocks; make them readable.

Times are **integer milliseconds**. Never frame indices, never floats.

Document structure

{
  "version": 1,
  "stage": { "width": 1200, "height": 640, "fps": 25 },
  "parts": { "<id>": { "type": "node" | "edge" | "label" | "shape", ... } },
  "steps": [ { "id": "...", "duration": 800, "caption": "...", "set": { ... } } ]
}

stage

| Field | Notes | | --- | --- | | `width`, `height` | Clamped to 16..8192. The stage scales to fit the pane, so these set the aspect ratio and the coordinate system, not the pixel size. | | `fps` | Only affects frame snapping and the readout. Use 25 unless you have a reason. Whole-millisecond frame rates: 10, 20, 25, 50. | | `background` | Optional override. Omit it and the stage uses the theme surface, which is what you want -- the scene then follows the user's light/dark theme. |

1200x640 is a good default. Landscape, room for a header row and a bottom rail.

parts

Part ids are the keys. All four types share `label`, `tone`, and `state` (their *baseline*, before any step runs).

**`node`** -- the workhorse. A titled card with an optional subtitle and key/value rows.

{ "type": "node", "label": "Object store", "x": 740, "y": 118, "w": 240, "h": 176,
  "subtitle": "SHA -> BYTES",
  "rows": [ { "key": "f7a9", "value": "commit  182 B" }, { "key": "e816" } ] }
  • `label` is **uppercased automatically**. Write `"Merge gate"`, it renders `MERGE GATE`. Falls back to the id.
  • `subtitle` is a small mono line under the header. Keep it short and caps-ish; it is where model names, worktrees, and units go.
  • `rows` render as boxed key/value pairs. `value` is optional. Key is left-aligned, value right-aligned.
  • **A row that would spill past the bottom is silently dropped.** Size the node to its rows (see Geometry).

**`edge`** -- a line between two parts, optionally carrying packets.

{ "type": "edge", "from": "client", "to": "store", "text": "GET <sha>", "packets": 4 }
  • `from`/`to` are part ids. Drawn centre-to-centre and trimmed to the box borders, so stacked and side-by-side both look right.
  • **A dangling `from`/`to` renders nothing at all** -- it looks like a broken renderer, not a broken document. Check your ids.
  • `packets` is how many squares travel the line while it is flowing (default 3). Set `0` for an edge that means a *relationship* rather than traffic. One trip takes 1.6s.
  • `text` draws a caption at the midpoint **on an opaque background plate** roughly `max(40, len × 7.6 + 16)` px wide. It will punch a hole through anything behind it. Only put `text` on an edge whose gap is wider than the plate.

**`label`** -- free-standing text.

{ "type": "label", "x": 56, "y": 48, "text": "COMMIT DAG", "align": "start", "caps": true }
  • `align`: `start` | `middle` | `end` (the anchor, at `x`).
  • `caps: true` gives the faint, tracked-out micro-caption style used for section headings.
  • **There is no font-size control.** Every label is 12px. Do not try to build a large title; build hierarchy with `caps`, tone, and position instead.

**`shape`** -- a plain rect or circle, with optional centered text.

{ "type": "shape", "shape": "rect", "x": 89, "y": 438, "w": 40, "h": 18, "tone": "accent" }

Shapes are how you show **quantity**, because text never changes (see Hard constraints). A grid of small shapes that go `hidden` one group at a time is a queue draining, a battery discharging, a work list being claimed.

**`html`** -- freeform markup, for the things the primitives above cannot express: real typography, a type scale, flow layout, a UI that has to look like a real product rather than like a diagram of it.

The markup comes from one of two places:

{ "type": "html", "x": 55, "y": 108, "w": 1090, "h": 534,
  "htmlFile": "./partials/app-window.html",
  "vars": { "title": "acme-api", "branch": "main" } }
  • **`htmlFile`** is a path to a `.html` file next to the document. Relative only; `..` is allowed, absolute is refused.
  • **`html`** is markup inline. Right for a few lines, wrong for a widget.

`vars` fills `{{name}}` placeholders in whichever source won.

Read more
Ships withnimbalyst

Nimbalyst - The open-source visual workspace for Claude Code, Codex, and OpenCode. Run multiple coding agents in parallel, edit their work visually in markdown, mockups, and diagrams, and track tasks. Free, MIT-licensed desktop app for macOS, Windows, Linux, with mobile companion for iOS and Android.

Get the whole plugin

Other skills on nimbalyst.