Skip to content
Agent Memory
Skill

/figure

Draw an animated figure (boxes, arrows, moving data) as one self-contained SVG for a GitHub README, PR, issue or blog post. Use when a change or an explanation needs a diagram — how a request flows, what a background job does, what a feature changed — or when the user asks for a

From plugin
hindsight
60k18 skills

Claude Code

$ npx -y skills add vectorize-io/hindsight --skill figure --agent claude-code

SKILL.md

figure.SKILL.md
name: figure
description: Draw an animated figure (boxes, arrows, moving data) as one self-contained SVG for a GitHub README, PR, issue or blog post. Use when a change or an explanation needs a diagram — how a request flows, what a background job does, what a feature changed — or when the user asks for a diagram, figure, animation or "show it visually". The docs site's own pages use the interactive player instead (see step 4).
user_invocable: true

Figure

One animated SVG, no scripts, no upload: it renders and plays anywhere markdown does — GitHub README, PR and issue comments, blog posts, Notion. Sharp at any size, and it follows the reader's light or dark theme.

Figures are [Giotto](https://github.com/nicoloboschi/giotto) diagrams: one JSON document, the same format the docs site's interactive figures use (`hindsight-docs/figures/*.json`).

**You write the diagram JSON — never SVG.** One command renders it. No build, no browser.

1. Write the diagram

**Do not save it as a file in the repo.** It is an input, not a deliverable — pipe it in (step 2), and the rendered SVG keeps a copy of it for you.

{
  "title": "Retain",
  "speed": 2000,
  "elements": [
    { "id": "root", "type": "group", "children": ["agent", "api", "bank"], "layout": { "direction": "row", "gap": 48 } },
    { "id": "agent", "type": "rectangle", "content": [{ "type": "title", "text": "Your AI Agent" }] },
    { "id": "api", "type": "group", "label": { "title": "Hindsight API" }, "children": ["retain"], "layout": { "direction": "column", "gap": 24 } },
    { "id": "retain", "type": "rectangle", "content": [{ "type": "title", "text": "Retain" }, { "type": "subtitle", "text": "LLM extraction" }] },
    { "id": "bank", "type": "group", "label": { "title": "Memory Bank" }, "children": ["facts", "obs"], "layout": { "direction": "column", "gap": 28 } },
    { "id": "facts", "type": "cylinder", "content": [{ "type": "title", "text": "Facts" }, { "type": "subtitle", "text": "world · experience" }] },
    { "id": "obs", "type": "cylinder", "content": [{ "type": "title", "text": "Observations" }] },
    { "id": "call", "type": "arrow", "route": "curved", "start": { "id": "agent" }, "end": { "id": "retain" }, "label": { "text": "retain()" } },
    { "id": "store", "type": "arrow", "route": "curved", "start": { "id": "retain" }, "end": { "id": "facts" }, "label": { "text": "extract" } },
    { "id": "consolidate", "type": "arrow", "route": "curved", "start": { "id": "facts" }, "end": { "id": "obs" }, "label": { "text": "consolidate" }, "quiet": true }
  ],
  "scenes": [
    {
      "label": "retain()",
      "beats": [
        { "edges": { "edge": "call", "data": "“Alice joined Google in March”" }, "say": "Your agent sends what happened." },
        {
          "edges": "store",
          "show": { "facts": [{ "tag": "world", "tone": "blue", "text": "Alice joined Google", "meta": "Mar 2026", "mark": "new" }] },
          "say": "An LLM pulls out the facts."
        },
        {
          "edges": "consolidate",
          "ms": 2600,
          "show": { "obs": [{ "text": "Alice works at Google", "meta": "2 sources" }] },
          "say": "The worker merges them into one belief."
        }
      ]
    }
  ]
}

**Elements** — a flat list. A `group` lists its `children` by id and lays them out (`layout: { direction: "row" | "column", gap, align }`); a `label: { title }` draws a frame around it. Children line up at the top/left unless the layout says otherwise: use `align: "center"` in rows and `align: "stretch"` in columns (equal-width boxes), as the docs figures do. `rectangle` boxes are the things that _do_ something; `cylinder` is data at rest; `diamond` is a decision. A box's `content` is blocks: `title`, `subtitle`, `text`, `list`, `chips`, `code`. Give every element a stable `id`.

**Arrows** — `{ type: "arrow", start: { id }, end: { id }, label?: { text }, route: "curved", around?, quiet? }`; the ends name a box _or a group_. `around: "above" | "below"` arcs over the boxes in between; `quiet: true` draws the arrow only while a scene uses it (for long arrows that would cut across).

**Scenes and beats** — each scene is one story the figure tells; the SVG plays them in a loop. A beat is one moment: `edges` (an arrow id, `{ edge, back, data }` for a reverse hop or a data chip, or an array to run several at once), `say` (the caption), `show` (fills the card inside a box until the scene ends), `light` (highlight boxes for that beat; on the scene, for the whole scene), `ms` (how long the beat lasts).

**Card rows** — `{ tag?, tone?, text, meta?, mark?, mono? }`. `tone` is `blue | purple | green | orange | red | gray`. Use `tag` for the kind of thing (`world`, `user`, `page`), `meta` for a detail, and `mark` for what happened to it (`new`, `✓`, `cited`, `↻`). `**bold**` and `` `code` `` work in any text.

The full format is the `FORMAT` text in `node_modules/giotto/lib/edit.js`. The 13 figures in `hindsight-docs/figures/` are working examples — the fastest start is copying the closest one.

Keep it honest and specific: real example data beats placeholders, and every claim in a label, card or caption must match what the code actually does — check the code, don't assume.

2. Render it — from stdin, so nothing is left on disk

npx giotto export - path/to/out.svg <<'DOC'
{ "title": …, "elements": […], "scenes": […] }
DOC

`giotto` comes from the docs site's dependencies (`npm install` at the repo root). The quoted `<<'DOC'` heredoc passes the JSON through untouched, and the only file produced is the SVG. Layout and scene warnings print on stderr: fix them. A reference to an element that doesn't exist (an arrow end, a group child, a box a scene fills) is an error: the export fails and writes nothing.

Other forms:

npx giotto export hindsight-docs/figures/retain.json out.svg   # a docs figure, as an SVG
npx giotto export doc.json out.svg --theme dark --static       # one still frame, dark
n
Read more
@vectorize-io
Ships withhindsight

Hindsight: Agent Memory That Learns

Stars on GitHub

Momentum

stars in total
60.2k
Star history of vectorize-io/hindsight on GitHub, a chart by star-history.com

Other skills on hindsight.

code-review

code-review

Review changed code against project standards. Checks for missing tests, dead code, type safety, lint issues, and coding…

hs-release

hs-release

Cut a core Hindsight release (vX.Y.Z) and open the changelog + blog PR. Use when asked to cut/start a release, bump the version,…

ship-it

ship-it

Take a PR from review to merged — run the repo's code-review skill on it in a loop (review, fix, re-review) until nothing is left…

triage

triage

Triage a GitHub issue or a reported problem — check it is real and not by design (code, git history, PRs, Hindsight memory), find…

hindsight-memory

hindsight-memory

Long-term memory for the agent via Hindsight. Use to recall relevant past context before answering, retain durable facts as you…

More skills from other plugins.

agent-cost-report

agent-cost-report

Believable agent cost report for any period, default the last 7 full days PT, not counting today. Measured tokens from Claude…

@thedotmack@thedotmackInstall Skill
mempalace

mempalace

Install, configure, and operate MemPalace, including a private local palace, a shared-brain hub, or a client joining an existing…

mempalace11d60k
@mempalace@mempalaceInstall Skill
mempalace

mempalace

Install, configure, and operate MemPalace, including a private local palace, a shared-brain hub, or a client joining an existing…

mempalace11d60k
@milla-jovovich@milla-jovovichInstall Skill

Questions about figure.

Which coding agents can use figure?
figure installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.