Drawn from code. Checked by CI.
Your coding agent draws the diagram from your code. Flowfig links each box to a file and a symbol, and fails CI when that code is gone.
npx flowfig initNode 18 or later. Zero runtime dependencies.
| ITEM | BOX | SOURCE | CHECK |
|---|---|---|---|
| 1 | API Server | api.ts#getUser | defined |
| 2 | Cache | cache.ts#getCached#getEntry | definedmissing |
| 3 | Database | db.ts#queryUser | defined |
| 4 | Browser | none | not linked |
NOTES
npx flowfig verify docs/cached-request.svg
0 errors, 0 warnings
docs/cached-request.svg: 3 of 3 boxes defined; edges: 2 found, 0 not found, 0 unsure, 1 not checked1. The commit renames getCached to getEntry. npx flowfig verify docs/cached-request.svg error missing-symbol docs/cached-request.svg: box "cache" -> examples/shop/cache.ts#getCached: symbol not defined 1 error, 0 warnings docs/cached-request.svg: 2 of 3 boxes defined; edges: 1 found, 0 not found, 0 unsure, 2 not checked
2. The agent updates the spec: cache.ts#getEntry. npx flowfig verify docs/cached-request.svg 0 errors, 0 warnings docs/cached-request.svg: 3 of 3 boxes defined; edges: 2 found, 0 not found, 0 unsure, 1 not checked
1. The commit renames getCached to getEntry. npx flowfig verify docs/cached-request.svg error missing-symbol docs/cached-request.svg: box "cache" -> examples/shop/cache.ts#getCached: symbol not defined 1 error, 0 warnings docs/cached-request.svg: 2 of 3 boxes defined; edges: 1 found, 0 not found, 0 unsure, 2 not checked 2. The agent updates the spec: cache.ts#getEntry. verify exits 0.
- TITLE
- Cached request
- DRAWN BY
- coding agent
- CHECKED BY
- flowfig verify
- FILE
- docs/cached-
request.svg - RESULT
- exit 0exit 1
- REV
- 01
- SHEET
- 1 of 8
- DATE
- 2026-10-06
- SCALE
- NTS
SHEET 2 OF 8 · DETAIL
DETAIL B
A renamed function should break a diagram.
Someone renames getCached. The diagram still shows the old name. No check fails, so no one sees the drift. With Flowfig, verify fails with exit code 1 and the pull request shows why.
SPEC, ONE BOX
{ "id": "cache", "label": "Cache", "sub": "in memory", "shape": "store", "width": 200, "source": "examples/shop/cache.ts#getCached" }npx flowfig verify docs/cached-request.svg error missing-symbol docs/cached-request.svg: box "cache" -> examples/shop/cache.ts#getCached: symbol not defined 1 error, 0 warnings docs/cached-request.svg: 2 of 3 boxes defined; edges: 1 found, 0 not found, 0 unsure, 2 not checked
SHEET 3 OF 8 · PROCESS
PROCESS SHEET
Three commands.
The agent writes JSON, not pictures. Flowfig does the layout, checks the spec with 23 rules, and writes one animated SVG with no script.
flowfig initSet up 7 agents in one run: Claude Code, Cursor, GitHub Copilot, Codex and other AGENTS.md agents, Gemini CLI, Windsurf and Kiro.
npx flowfig init --all-agents --dry-runwould create .claude/skills/figure/SKILL.mdwould create CLAUDE.mdwould create .mcp.jsonwould create AGENTS.mdwould create .cursor/rules/flowfig.mdcwould create .cursor/mcp.jsonwould create .github/copilot-instructions.mdwould create .vscode/mcp.jsonwould create GEMINI.mdwould create .gemini/settings.jsonwould create .windsurf/rules/flowfig.mdnote windsurf: add {"command":"npx","args":["flowfig","mcp"]} to the MCP config by handwould create .kiro/steering/flowfig.mdwould create .kiro/settings/mcp.jsonflowfig verifyCheck every linked file, symbol and edge against the code.
npx flowfig verify docs/checkout.svg0 errors, 0 warningsdocs/checkout.svg: 4 of 4 boxes defined; edges: 3 found, 0 not found, 0 unsure, 1 not checkedflowfig diffList what changed between two figures.
npx flowfig diff first.svg first2.svgbox changed: api (label "API" -> "API gateway")edge changed: api->db (label "read the user" -> "select the user")
SHEET 4 OF 8 · REVISIONS
REVISIONS
The pull request shows the drift.
The Action runs verify on every figure in a pull request. For each SVG the PR changes, it comments the old image, the new image and the spec changes. It names each figure whose linked code the PR changes.
# .github/workflows/figures.ymlname: figureson: pull_requestjobs:figures:runs-on: ubuntu-latestpermissions:contents: readpull-requests: writesteps:- uses: actions/checkout@v4with:fetch-depth: 0 # the Action reads the old figure from the base commit- uses: actions/setup-node@v4with:node-version: 22- uses: iamalvisng/flowfig@v0.8.4with:figures: 'docs/**/*.svg' # default **/*.svg| REV | ZONE | DESCRIPTION | APPROVED |
|---|---|---|---|
| 0 | 1 | all | ||
| 1 | 7A | box changed: cache (source "examples/shop/cache.ts#getCached" -> "examples/shop/cache.ts#getEntry") | verify: 3 of 3 boxes defined |
NOTES
| |||
SHEET 5 OF 8 · FORMS
SHEET SET, 5.1 TO 5.6
Six forms. One spec.
A map of the parts. A rail of the messages. Swimlanes for a process. A timeline for a roadmap. A lifecycle for a state machine. Each one plays in a GitHub README and follows the reader's light or dark mode.
- TITLE
- A browser loads a user through an API from a database.
- FORM
- Map
- OPTION
- the default
- SHEET
- 5.1 of 5.6
- TITLE
- An order checkout: the map of the parts, and a rail of the messages under it.
- FORM
- Map and rail
- OPTION
- rail: true
- SHEET
- 5.2 of 5.6
- TITLE
- The checkout messages as a rail, without the map.
- FORM
- Rail
- OPTION
- rail: "only"
- SHEET
- 5.3 of 5.6
- TITLE
- The refund process across Customer, Support and Finance.
- FORM
- Swimlanes
- OPTION
- lanes: true
- SHEET
- 5.4 of 5.6
- TITLE
- A Q4 roadmap with three tracks, milestones and a today line.
- FORM
- Timeline
- OPTION
- timeline: true
- SHEET
- 5.5 of 5.6
- TITLE
- An order status lifecycle with a start dot and two end rings.
- FORM
- Lifecycle
- OPTION
- mark: "start" and "end"
- SHEET
- 5.6 of 5.6
SHEET 6 OF 8 · SPECIFICATION
SPECIFICATION
Checked before it is drawn.
| ITEM | CHARACTERISTIC | VALUE | NOTE |
|---|---|---|---|
| 1 | Rules | 23 | in flowfig check |
| 2 | Errors | 11 | stop the render |
| 3 | Warnings | 12 | --strict makes them errors |
check finds ids that point nowhere, text wider than its box, edges through boxes, overlapping labels and low contrast. A render runs the same check and writes nothing on an error.
INSPECTION RECORD
npx flowfig check docs/checkout.svg0 errors, 0 warningsfigure: 5 boxes, 3 groups, 4 edges, 2 steps, 6 messagesLIMIT Edge checks cover TypeScript, JavaScript, Python, Go, Java, C# and Rust. Other languages keep the name check for boxes.
SHEET 7 OF 8 · CONNECTORS
CONNECTOR SCHEDULE
Any coding agent.
init writes the Flowfig guide where your agent reads it. flowfig mcp serves docs, check, render, verify and diff over stdio for an agent with no shell. render writes the file and returns the check lines, so no SVG text goes through the model.
npx flowfig init --all-agents --dry-run- Claude Code.claude/skills/figure/SKILL.mdCLAUDE.md.mcp.json
- Codex and other AGENTS.md agentsAGENTS.md
- Cursor.cursor/rules/flowfig.mdc.cursor/mcp.json
- GitHub Copilot.github/copilot-instructions.md.vscode/mcp.json
- Gemini CLIGEMINI.md.gemini/settings.json
- Windsurf.windsurf/rules/flowfig.mdMCP: add {"command":"npx","args":["flowfig","mcp"]} to the MCP config by hand
- Kiro.kiro/steering/flowfig.md.kiro/settings/mcp.json
TERMINAL BLOCK, MCP
{ "mcpServers": { "flowfig": { "command": "npx", "args": ["flowfig", "mcp"] } } }SHEET 8 OF 8 · ASSEMBLY
ASSEMBLY C
The same figure in your app.
The React player adds tabs for each step, pause, 2x speed and full screen. A hover on a box shows its source. Under reduced motion it shows the last beat and does not move.
import { Flow, type FlowProps } from 'flowfig';
import spec from './first.json';
export const LoadUser = () => <Flow {...(spec as FlowProps)} />;React 18 or later is a peer dependency. The CLI and flowfig/svg do not need React.
SIGN-OFF
One command. Then ask your agent.
| NO. | STEP | COMMAND | RESULT | Copy |
|---|---|---|---|---|
| 1 | Set up | npx flowfig init | ||
| 2 | Ask | /figure how does login work | ||
| 3 | Check | npx flowfig verify docs/login.svg | exit 0 |
The agent ends its reply with npx flowfig open <path>. Run it to see the animation.