From code-canvas
Use when the user asks to create, view, update, or interact with a design canvas, or when working on architecture/design tasks in a project with .code-canvas/
How this skill is triggered — by the user, by Claude, or both
Slash command
/code-canvas:canvasThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Visual design knowledge graph. Maps architecture, flows, pipelines, and decisions as an interactive node-and-edge diagram in the browser. Event-sourced — every change is an immutable event in `.code-canvas/events.jsonl`.
Visual design knowledge graph. Maps architecture, flows, pipelines, and decisions as an interactive node-and-edge diagram in the browser. Event-sourced — every change is an immutable event in .code-canvas/events.jsonl.
When /canvas generate is called and no .code-canvas/ exists yet:
mkdir -p .code-canvastouch .code-canvas/events.jsonlnode "${CLAUDE_PLUGIN_ROOT}/server/index.js" --project-dir .
.code-canvas/.server-info& or use disowncurl -X POST http://localhost:<port>/api/events/batch -H 'Content-Type: application/json' -d '[...events...]'open http://localhost:<port>If .code-canvas/ already exists, the server URL is in the session context above.
| Command | Behavior |
|---|---|
/canvas | Open canvas in browser (auto-start server if needed) |
/canvas generate | Read spec/codebase, POST node/edge/view events to build canvas |
/canvas regenerate | Wipe all events and regenerate from scratch (fresh analysis) |
/canvas update | Compare canvas state to codebase, update node statuses |
/canvas reset | Wipe all canvas data (events, layouts, server info). Clean slate. |
/canvas diff [since] | Read events after ISO timestamp, summarize what changed |
/canvas comments | List unresolved comments with targets |
/canvas story | Narrate decision history from decision.recorded events |
/canvas export md | Generate markdown summary of current state |
All events use envelope: { id, ts, type, actor, data }
| Type | Data fields |
|---|---|
node.created | nodeId, label, subtitle, parent, depth, category, confidence, status, files[] |
node.updated | nodeId, changes: { ...changed fields } |
node.deleted | nodeId |
node.status | nodeId, status, prev |
edge.created | edgeId, from, to, label, edgeType, color |
edge.updated | edgeId, changes: { ...changed fields } |
edge.deleted | edgeId |
decision.recorded | nodeId, type (decision|workaround), chosen, alternatives[], reason |
comment.added | commentId, target, targetLabel, text, actor |
comment.resolved | commentId |
comment.reopened | commentId |
comment.deleted | commentId |
view.created | viewId, name, description, rendering, tabNodes[], tabConnections[] |
view.updated | viewId, changes: { ...changed fields } |
view.deleted | viewId |
system | domain | module | interfacedone | in-progress | planned | placeholder0-3["src/lib/events.*", "server/index.js"])"arch", "flow", "data", "actor" for UML actors)Views can carry a rendering object with composable hints that control how nodes and edges are drawn. Claude picks hints based on what the diagram is trying to communicate.
| Hint | Values | Default | Purpose |
|---|---|---|---|
nodeShape | card, ellipse, rounded, pill | card | How nodes are drawn |
nodeSize | compact, standard, expanded | standard | Node dimensions |
nodeContent | Array: label, subtitle, fields, status-badge | ["label", "subtitle"] | What to show on nodes |
edgeStyle | curve, straight, step, ordered-arrows | curve | How edges are drawn |
edgeLabels | pill, inline, hidden | pill | Edge label style |
layout | grid, horizontal-lanes, vertical-lanes, layered-top-down | grid | Layout algorithm |
Auto-detection: Nodes with category: "actor" automatically render as UML stick figures regardless of the view's nodeShape hint.
Per-node override: Individual nodes can override the view's shape via tabNode.shape.
Examples:
UML use case diagram:
{ "rendering": { "nodeShape": "ellipse" } }
State machine:
{ "rendering": { "nodeShape": "rounded" } }
| Endpoint | Method | Purpose |
|---|---|---|
/api/events | GET | Fetch all events |
/api/events | POST | Append single event |
/api/events/batch | POST | Append multiple events (JSON array) |
/api/state | GET | Current replayed state (?level=L0|L1) |
/api/layouts/:viewId | GET/PUT | Node positions per view |
/api/health | GET | Server health |
When running /canvas generate, analyze the codebase and create a meaningful architecture map.
The canvas uses maxGraph (the engine behind draw.io) to render diagrams. Store draw.io XML in the view's drawioXml field. Use the draw.io MCP (open_drawio_xml or open_drawio_mermaid) for complex diagrams, or generate XML directly for simple updates.
Cell IDs must match node IDs (e.g., n_server). This enables click-to-detail: when a user clicks a shape, the detail panel shows that node's properties, comments, and decisions.
NEVER send a view.created event with an empty drawioXml field. Always craft the XML yourself. The auto-layout fallback produces generic hierarchical layouts that all look identical regardless of the view type. Each view MUST have distinct, hand-crafted drawioXml tailored to what the diagram is communicating.
Each node is an architectural component. Include files glob patterns so the plugin can auto-track edits.
The number and type of tabs should NOT be predetermined. Analyze the codebase and decide what perspectives would help a developer understand it. Consider:
Examples of view types (pick what fits, don't use all):
Rules:
description explaining what this diagram showsEach view type demands a different layout and shape vocabulary. Do NOT reuse the same top-down hierarchy for every view.
Architecture / Component diagrams — Layered layout, top-to-bottom:
rounded=1 rectangles for services, shape=cylinder3 for databases, shape=cloud for external services.<!-- Architecture: layered, vertical spacing between tiers -->
<mxCell id="n_server" value="Server" style="rounded=1;whiteSpace=wrap;fillColor=#1a3320;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=13;" vertex="1" parent="1">
<mxGeometry x="200" y="40" width="160" height="60" as="geometry"/>
</mxCell>
<mxCell id="n_database" value="Database" style="shape=cylinder3;whiteSpace=wrap;fillColor=#1a3320;strokeColor=#3fb950;fontColor=#c9d1d9;fontSize=13;size=15;" vertex="1" parent="1">
<mxGeometry x="200" y="280" width="160" height="80" as="geometry"/>
</mxCell>
Flow / Lifecycle diagrams — Horizontal layout, left-to-right:
rounded=1 rectangles or shape=process. Connect with orthogonal edges (edgeStyle=orthogonalEdgeStyle).<!-- Flow: horizontal chain, left-to-right -->
<mxCell id="n_step1" value="Session Start" style="rounded=1;whiteSpace=wrap;fillColor=#2a2a10;strokeColor=#d29922;fontColor=#c9d1d9;fontSize=13;" vertex="1" parent="1">
<mxGeometry x="40" y="100" width="140" height="50" as="geometry"/>
</mxCell>
<mxCell id="n_step2" value="Pre-Tool Hook" style="rounded=1;whiteSpace=wrap;fillColor=#1e2a3a;strokeColor=#58a6ff;fontColor=#c9d1d9;fontSize=13;" vertex="1" parent="1">
<mxGeometry x="240" y="100" width="140" height="50" as="geometry"/>
</mxCell>
<mxCell id="e_step1_step2" style="edgeStyle=orthogonalEdgeStyle;strokeColor=#58a6ff;fontColor=#999;fontSize=11;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" source="n_step1" target="n_step2" parent="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
UI / Component tree diagrams — Hierarchical tree, top-down:
Data flow / Sequence diagrams — Participants across the top horizontally:
edgeStyle=orthogonalEdgeStyle for message arrows.<mxCell> text elements positioned near edges, NOT inline value on edge cells. Inline edge labels often overlap shapes.exitX/exitY and entryX/entryY to control which side edges connect to. Use <Array as="points"> waypoints for edges that cross between layers.rounded=1 for components, shape=cylinder3 for data stores, shape=document for docs, shape=actor for people/systems. All shapes should have two lines of text (name + description).#888 or #999.Before sending any view.created event, verify:
n_server, e_server_db)fillColor/strokeColor (not all the same color)exitX/exitY and entryX/entryY for clean connectionsUse node.status events after creation to set the real status. The default is planned — explicitly set done, in-progress, etc.
When /canvas reset is called:
.code-canvas/.server-info> .code-canvas/events.jsonlrm -f .code-canvas/layouts/*.jsonrm -f .code-canvas/.claude-last-seen/canvas generate to rebuild."When /canvas regenerate is called:
/canvas generate (fresh analysis of current codebase)The shape registry auto-selects shapes from node properties (database → cylinder, cache → hexagon, etc.). When a project needs shapes that don't exist in the registry:
Option 1: Inline style — Set shape on the node to a raw draw.io style string:
{"nodeId": "n_lambda", "label": "Lambda", "shape": "shape=mxgraph.aws4.lambda_function;fontColor=#e6edf3;fontSize=12;"}
Option 2: Project-specific shapes — Save to .code-canvas/shapes.json via PUT /api/shapes:
curl -X PUT http://localhost:<port>/api/shapes -H 'Content-Type: application/json' -d '{
"lambda": {"style": "shape=mxgraph.aws4.lambda_function;whiteSpace=wrap;fontSize=12;fontColor=#e6edf3;", "width": 60, "height": 60, "tags": ["aws", "serverless"], "description": "AWS Lambda function"}
}'
Option 3: User-level shapes — Save to ~/.claude/shapes.json via PUT /api/shapes/user. These are available in ALL projects for this user:
curl -X PUT http://localhost:<port>/api/shapes/user -H 'Content-Type: application/json' -d '{
"lambda": {"style": "shape=mxgraph.aws4.lambda_function;whiteSpace=wrap;fontSize=12;fontColor=#e6edf3;", "width": 60, "height": 60, "tags": ["aws", "serverless"], "description": "AWS Lambda function"}
}'
When creating custom shapes, save to BOTH user-level AND project-level so they're available everywhere AND in this specific project.
Load order: Built-in → user-level → project-level (later overrides earlier).
Built-in shapes: actor, server, database, queue, cache, cloud, domain, module, interface, usecase, package, class, decision, start, end, process, state, document, file, swimlane, group.
actor: "claude" when posting eventsn_<slug>, e_<from>_<to>, v_<slug>files patterns on nodes when the file mapping is cleardecision.recorded, update file patterns, add comments noting deviationsProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub lilo-labs/claude-code-plugins --plugin code-canvas