Give Claude Code eyes and a whiteboard. Install the skill, start a session, and Claude automatically draws diagrams, wireframes, and mockups on a shared canvas — asking visual questions and collecting your feedback instead of cluttering the terminal.
Installation • Quick Start • Visual Q&A • Drawing • DSL Format • Interactive Canvas • Claude Code Skill • CLI Reference
Claude Code is powerful, but it's stuck in text. When Claude needs to show you a layout, compare design options, or ask "which of these do you prefer?" — a terminal isn't enough.
claude-canvas is a shared visual canvas for Claude Code. Once installed, Claude automatically draws diagrams, sketches wireframes, and asks visual questions on the canvas — you just answer by clicking, typing, or drawing in the browser. You don't run any drawing commands yourself; the included Claude Code skill teaches Claude when and how to use the canvas.
| Without Claude Canvas | With Claude Canvas |
![]() |
![]() |
- "Which layout do you prefer?" — Claude draws the options on canvas, you click your choice
- "What should this look like?" — Claude sketches a wireframe, you annotate it
- "Here's the architecture" — Claude draws a diagram you can actually see, not ASCII art
- "Name this feature" — Claude shows context on canvas, you type your answer
- Install & setup —
npm install -g claude-canvas && claude-canvas setup - Talk to Claude — just use Claude Code as you normally would
- Claude opens the canvas — when visuals would help, Claude starts a session and opens a browser tab automatically
- Claude draws — diagrams, wireframes, and mockups appear on the canvas
- You respond — answer visual questions by clicking, typing, or drawing in the browser
- Claude continues — your answers flow back to Claude automatically
You never need to run any
claude-canvascommands yourself. The skill handles everything — Claude calls the CLI under the hood using a compact DSL that minimizes token usage.
- Fully automatic — the Claude Code skill teaches Claude when and how to use the canvas; no manual commands needed
- Visual Q&A — structured questions with per-question canvas drawings, answers returned automatically
- Shared drawing surface — Claude draws on the canvas, you draw interactively in the browser, both in real-time
- Compact DSL — a concise drawing language that uses 3-5x fewer tokens than JSON, with auto-layout and label-based arrow routing (reference)
- Hand-drawn aesthetic — powered by Rough.js, everything looks like a natural whiteboard sketch
- Multiple fill styles — hachure, solid, zigzag, cross-hatch, dots, dashed, and wireframe outlines
- Status badge — Claude updates a live status message in the browser so you always know what it's working on
- Export — save as PNG, SVG, or JSON
npm install -g claude-canvas
claude-canvas setupThe setup command installs the Claude Code skill, which lets Claude automatically use the canvas when it makes sense.
claude-canvas updateThis checks for the latest version, installs it, and automatically updates the Claude Code skill if it has changed.
git clone https://github.com/uditalias/claude-canvas.git
cd claude-canvas
npm install
npm run build
npm link # makes `claude-canvas` available globally
claude-canvas setup- Node.js >= 18
- A modern browser (Chrome, Firefox, Safari, Edge)
1. Install and set up the skill:
npm install -g claude-canvas
claude-canvas setup2. Use Claude Code as normal:
That's it. When visuals would help — architecture diagrams, wireframe comparisons, design decisions — Claude will automatically start a canvas session, open a browser tab, and draw there instead of cluttering the terminal.
For example, ask Claude to "design a dashboard layout" or "show me the system architecture". Claude will open the canvas, draw the diagrams, and if it needs your input, a question panel will appear in the browser for you to answer.
The core feature of claude-canvas. When Claude needs your input on a visual decision, it draws options on the canvas and presents a floating question panel in your browser. You answer by clicking options, typing text, or drawing — then click Done. Claude receives your answers automatically and continues working.
You don't run the
askcommand yourself — Claude calls it via the skill. The examples below show what Claude sends under the hood.
Users select answers via interactive pill buttons. Selected answers are highlighted:
# Claude uses the DSL format to minimize token usage:
claude-canvas ask --dsl 'ask {
question #q1 single "Which layout do you prefer?" {
options "Layout A" | "Layout B" | "Layout C"
row gap=40 {
box "Layout A" 200x150 fill=none
box "Layout B" 200x150 fill=none
}
}
question #q2 text "What should the title be?"
}'| Type | Description | User interaction | Answer format |
|---|---|---|---|
single |
Pick one option | Radio-style pill buttons | "value": "Option A" |
multi |
Pick multiple options | Toggle pill buttons | "value": ["Option A", "Option C"] |
text |
Free text input | Text field | "value": "user's text" |
canvas |
Draw on canvas | Freeform drawing | "value": "see canvas" + snapshot PNG |
The ask command blocks until you click Done, then Claude receives:
{
"ok": true,
"status": "answered",
"path": "/tmp/claude-canvas/canvas-123.png",
"answers": [
{"questionId": "q1", "value": "Layout A"},
{"questionId": "q2", "value": "My Custom Title"}
]
}If the browser disconnects before the user submits:
{
"ok": false,
"status": "disconnected",
"error": "Browser disconnected before answers were submitted"
}For canvas-type questions, Claude draws a diagram and you respond by drawing directly on the canvas. The answer includes a snapshot of what you drew:
{"questionId": "q3", "value": "see canvas", "canvasSnapshot": "/tmp/claude-canvas/canvas-q3-456.png"}Claude draws shapes, diagrams, and wireframes on the canvas automatically when visuals would help. The skill instructs Claude to use a compact DSL format for all drawing, which reduces token usage by 3-5x compared to JSON.
You don't run
drawcommands yourself — Claude calls them via the skill. The examples below show what Claude sends under the hood.
# What Claude sends (DSL):
claude-canvas draw --dsl 'row gap=40 {
box "Frontend" 200x100
box "Backend" 200x100
}
arrow "Frontend" -> "Backend" "API"'DrawCommand Types (click to expand)
All support optional label, color, opacity, and fillStyle:
// Line
{"type": "line", "x1": 100, "y1": 100, "x2": 300, "y2": 100}
// Arrow (with directional head)
{"type": "arrow", "x1": 100, "y1": 200, "x2": 300, "y2": 200, "label": "flow"}// textAlign: "left" | "center" | "right"
{"type": "text", "x": 200, "y": 50, "content": "Title", "fontSize": 24, "textAlign": "center"}{"type": "freehand", "points": [[10, 10], [50, 30], [90, 10], [130, 30]]}For structured flowcharts:
// Group: bundle shapes under an ID for connectors
{"type": "group", "id": "box-a", "commands": [
{"type": "rect", "x": 200, "y": 30, "width": 140, "height": 60},
{"type": "text", "x": 270, "y": 50, "content": "Start", "textAlign": "center"}
]}
// Connector: auto-routes between group edges
{"type": "connector", "from": "box-a", "to": "box-b", "label": "next"}Fill Styles (click to expand)
Shapes default to "hachure". Set fillStyle on any shape:
| Style | Description |
|---|---|
hachure |
Hand-drawn diagonal lines (default) |
solid |
Solid fill |
zigzag |
Zigzag pattern |
cross-hatch |
Cross-hatched lines |
dots |
Dotted pattern |
dashed |
Dashed lines |
zigzag-line |
Zigzag line pattern |
none |
No fill (wireframe outline only) |
claude-canvas includes a concise DSL (domain-specific language) for drawing commands. The Claude Code skill instructs Claude to always use the DSL instead of JSON — it's 3-5x fewer tokens, which keeps conversations within context limits during complex visual sessions.
The DSL handles automatic layout via row and stack containers (no manual coordinate math) and supports label-based arrow routing (reference shapes by name instead of pixel positions). Claude uses these features automatically — you don't need to know the DSL syntax yourself.
# DSL — 2 lines, auto-layout, no coordinates (what Claude sends)
claude-canvas draw --dsl 'row gap=40 { box "Frontend" 200x100; box "Backend" 200x100 }
arrow "Frontend" -> "Backend" "API"'
# JSON equivalent — 5 lines, manual x/y for every shape
claude-canvas draw '{"commands": [
{"type": "rect", "x": 50, "y": 50, "width": 200, "height": 100, "label": "Frontend"},
{"type": "rect", "x": 350, "y": 50, "width": 200, "height": 100, "label": "Backend"},
{"type": "arrow", "x1": 250, "y1": 100, "x2": 350, "y2": 100, "label": "API"}
]}'# Shapes with layout
claude-canvas draw --dsl 'row gap=40 {
box "Web App" 180x80 fill=solid color=#7198C9
box "API" 180x80 fill=solid color=#8AAD5A
box "DB" 180x80 fill=solid color=#D9925E
}
arrow "Web App" -> "API" "REST"
arrow "API" -> "DB" "SQL"'
# Flowchart with connectors
claude-canvas draw --dsl '
group #start { box "Start" 140x60 }
group #process { box "Process" 140x60 }
group #end { box "End" 140x60 }
#start -> #process
#process -> #end'
# Visual Q&A
claude-canvas ask --dsl 'ask {
question #theme single "Which color theme?" {
options "Blue Ocean" | "Forest Green" | "Sunset Purple"
row gap=40 {
circle "Blue" 50 fill=solid color=#7198C9
circle "Green" 50 fill=solid color=#8AAD5A
circle "Purple" 50 fill=solid color=#9B85B5
}
}
question #name text "What should we name this feature?"
}'For the full DSL syntax — shapes, layout containers, attributes, and more examples — see the DSL Reference. This reference is also included in the skill, so other LLMs that read it can use claude-canvas the same way.
The browser canvas is a full interactive drawing surface, not just a display. You can draw alongside Claude's shapes in real-time — annotate diagrams, sketch alternatives, or respond to canvas-type questions.
The toolbar provides these drawing tools:
| Tool | Description |
|---|---|
| Rectangle | Draw rectangles with optional fill |
| Circle | Draw circles |
| Line | Draw straight lines |
| Arrow | Draw directional arrows |
| Freehand | Freeform pencil drawing |
| Text | Click to place text |
| Paint | Brush painting with adjustable size |
- Zoom & Pan — scroll to zoom, drag to pan the canvas
- Undo/Redo — full history support (up to 50 states)
- Snap Guides — alignment guides appear when moving objects near other objects
- Context Menu — right-click any shape to change color, fill, opacity, label, lock, or layer order
- Color Palette — soft muted color presets with custom color picker
- Brush Size — adjustable size for paint and freehand tools
- Dark Mode — respects system theme preference
- Keyboard Shortcuts — quick tool switching via keyboard
Objects have a layer property:
user— shapes drawn interactively in the browserclaude— shapes drawn via the CLI/API
Use claude-canvas clear --layer claude to remove Claude's drawings without affecting user drawings.
The skill is what makes everything automatic. It teaches Claude Code when to use the canvas and how to call the CLI — you don't need to learn any commands.
claude-canvas setupThis installs (or updates) the skill to ~/.claude/skills/claude-canvas/. You can also install it manually:
cp -r $(npm root -g)/claude-canvas/src/skill/claude-canvas ~/.claude/skills/Once installed, Claude Code will automatically use the canvas when it makes sense — for example:
- Drawing architecture diagrams during system design discussions
- Sketching UI wireframes when discussing layouts
- Creating flowcharts to explain processes
- Presenting visual options and asking for your preference via Q&A
The skill instructs Claude to use the DSL format for all draw and ask commands, which uses 3-5x fewer tokens than JSON. This keeps conversations within context limits during complex visual sessions. The DSL Reference is bundled with the skill so Claude (and other LLMs that read the skill files) can use the full DSL syntax.
You don't need to tell Claude to use the canvas — the skill handles that. Just have a conversation, and Claude will reach for the canvas when visuals would help.
The CLI is what Claude (and other LLMs) call under the hood. You typically only need
start,stop, andsetup. Thedraw,ask,screenshot, and other commands are called automatically by the skill.
All commands accept -s, --session <id>. You can omit it when only one session is running.
| Command | Description |
|---|---|
claude-canvas start |
Start a new canvas session (opens browser) |
claude-canvas start -p 8080 |
Start on a specific port |
claude-canvas list |
List all running sessions |
claude-canvas stop -s <id> |
Stop a specific session |
claude-canvas stop --all |
Stop all running sessions |
claude-canvas ask '<json>' |
Send visual questions (JSON), block until answered |
claude-canvas ask --dsl '<dsl>' |
Send visual questions (DSL), block until answered |
claude-canvas draw '<json>' |
Send draw commands (JSON) |
claude-canvas draw --dsl '<dsl>' |
Send draw commands (DSL) |
claude-canvas draw --no-animate '<json|dsl>' |
Draw without animation |
claude-canvas clear |
Clear all objects from the canvas |
claude-canvas clear --layer claude |
Clear only Claude's objects |
claude-canvas status '<text>' |
Update status badge in browser |
claude-canvas screenshot |
Capture canvas as PNG |
claude-canvas export -f png|svg|json |
Export canvas in various formats |
claude-canvas setup |
Install/update the Claude Code skill |
claude-canvas update |
Update to the latest version |
Both ask and draw accept - to read from stdin. Use --dsl for the compact DSL format (see DSL Reference).
Claude updates a live status message in the browser so you always know what it's working on:
Project Structure (click to expand)
src/
├── bin/
│ ├── claude-canvas.ts # CLI entry point (Commander)
│ ├── actions/ # CLI subcommand handlers
│ │ ├── ask.ts, draw.ts # Drawing & Q&A commands
│ │ ├── start.ts, stop.ts # Session lifecycle
│ │ └── setup.ts, update.ts # Skill installation & updates
│ ├── dsl/ # DSL compiler (text → DrawCommands)
│ │ ├── tokenizer.ts # Lexer
│ │ ├── parser.ts # AST builder
│ │ └── layout.ts # Auto-layout engine (row/stack)
│ └── utils.ts, version.ts
├── server/
│ ├── router.ts # REST API endpoints
│ ├── websocket.ts # WebSocket server
│ ├── state.ts # In-memory state & broadcast
│ └── process.ts # Session management (PID/port)
├── client/
│ ├── components/
│ │ ├── Canvas.tsx # Main canvas view
│ │ ├── Toolbox.tsx # Drawing toolbar
│ │ ├── QuestionPanel.tsx # Q&A floating panel
│ │ ├── Hud.tsx # Connection status & zoom
│ │ ├── ContextMenu.tsx # Right-click context menu
│ │ ├── Narration.tsx # Animated narration text
│ │ └── ShortcutsOverlay.tsx
│ ├── hooks/
│ │ ├── useCanvas.ts # Fabric.js canvas + rough.js rendering
│ │ ├── useDrawingTools.ts # Interactive drawing tools
│ │ ├── useWebSocket.ts # WS connection + auto-reconnect
│ │ ├── useToolState.ts # Tool selection + shortcuts
│ │ ├── useUndoRedo.ts # Canvas history (50 states)
│ │ ├── useSnapGuides.ts # Alignment snap guides
│ │ ├── useQuestionPanel.ts # Q&A state management
│ │ └── ... # Zoom, export, label editing, etc.
│ └── lib/
│ ├── rough-line.ts # Custom Fabric objects for rough.js
│ ├── render-engine.ts # Shape rendering pipeline
│ └── wobble.ts # Hand-drawn effect engine
├── protocol/
│ └── types.ts # Shared types (DrawCommand, WsMessage, etc.)
├── skill/
│ └── claude-canvas/
│ ├── SKILL.md # Claude Code skill definition
│ └── DSL-REFERENCE.md # Full DSL syntax reference
└── utils/ # Shared utilities (browser, port, screenshot)
# Clone the repository
git clone https://github.com/uditalias/claude-canvas.git
cd claude-canvas
npm install
# Run in development mode (server with hot reload)
npm run dev
# Run client only (Vite dev server on :5173, proxies to :7890)
npm run dev:client
# Build everything
npm run build
# Run unit tests
npm test
# Run E2E tests (requires build first)
npm run build && npx playwright testThese show the commands Claude generates automatically via the skill. You don't need to write these yourself — they're here for reference and for other LLMs reading this documentation.
Architecture Diagram (DSL)
claude-canvas draw --dsl '
text "System Architecture" size=28 weight=bold align=center
row gap=40 {
box "Client App" 180x80
box "API Gateway" 180x80 fill=solid
box "Database" 180x80 fill=dots
}
arrow "Client App" -> "API Gateway" "REST"
arrow "API Gateway" -> "Database" "SQL"
'Architecture Diagram (JSON)
claude-canvas draw '{"commands": [
{"type": "text", "x": 400, "y": 40, "content": "System Architecture", "fontSize": 28, "textAlign": "center"},
{"type": "rect", "x": 50, "y": 100, "width": 180, "height": 80, "label": "Client App", "fillStyle": "hachure"},
{"type": "rect", "x": 310, "y": 100, "width": 180, "height": 80, "label": "API Gateway", "fillStyle": "solid"},
{"type": "rect", "x": 570, "y": 100, "width": 180, "height": 80, "label": "Database", "fillStyle": "dots"},
{"type": "arrow", "x1": 230, "y1": 140, "x2": 310, "y2": 140, "label": "REST"},
{"type": "arrow", "x1": 490, "y1": 140, "x2": 570, "y2": 140, "label": "SQL"}
]}'Wireframe Layout (DSL)
claude-canvas draw --dsl '
stack gap=10 {
box "Navigation" 500x60 fill=none
row gap=10 {
box "Sidebar" 150x300 fill=none
box "Main Content" 330x300 fill=none
}
}
'Wireframe Layout (JSON)
claude-canvas draw '{"commands": [
{"type": "rect", "x": 50, "y": 30, "width": 500, "height": 60, "label": "Navigation", "fillStyle": "none"},
{"type": "rect", "x": 50, "y": 110, "width": 150, "height": 300, "label": "Sidebar", "fillStyle": "none"},
{"type": "rect", "x": 220, "y": 110, "width": 330, "height": 300, "label": "Main Content", "fillStyle": "none"}
]}'Flowchart with Connectors (DSL)
claude-canvas draw --dsl '
group #start { box "Start" 140x60 }
group #process { box "Process" 140x60 }
group #end { box "End" 140x60 }
#start -> #process
#process -> #end
'Flowchart with Connectors (JSON)
claude-canvas draw '{"commands": [
{"type": "group", "id": "start", "commands": [
{"type": "rect", "x": 200, "y": 30, "width": 140, "height": 60},
{"type": "text", "x": 270, "y": 50, "content": "Start", "textAlign": "center"}
]},
{"type": "group", "id": "process", "commands": [
{"type": "rect", "x": 200, "y": 150, "width": 140, "height": 60},
{"type": "text", "x": 270, "y": 170, "content": "Process", "textAlign": "center"}
]},
{"type": "group", "id": "end", "commands": [
{"type": "rect", "x": 200, "y": 270, "width": 140, "height": 60},
{"type": "text", "x": 270, "y": 290, "content": "End", "textAlign": "center"}
]},
{"type": "connector", "from": "start", "to": "process"},
{"type": "connector", "from": "process", "to": "end"}
]}'Visual Decision Making — Q&A (DSL)
claude-canvas ask --dsl '
ask {
question #theme single "Which color theme should we use?" {
options "Blue Ocean" | "Forest Green" | "Sunset Purple"
row gap=40 {
circle "Blue" 50 fill=solid color=#7198C9
circle "Green" 50 fill=solid color=#8AAD5A
circle "Purple" 50 fill=solid color=#9B85B5
}
}
question #name text "What should we name this feature?"
question #features multi "Which features should we include?" {
options "Dark mode" | "Animations" | "Keyboard shortcuts" | "Mobile support"
}
}
'Visual Decision Making — Q&A (JSON)
claude-canvas ask '{"questions": [
{
"id": "theme",
"text": "Which color theme should we use?",
"type": "single",
"options": ["Blue Ocean", "Forest Green", "Sunset Purple"],
"commands": [
{"type": "circle", "x": 150, "y": 150, "radius": 50, "label": "Blue", "fillStyle": "solid"},
{"type": "circle", "x": 350, "y": 150, "radius": 50, "label": "Green", "fillStyle": "solid"},
{"type": "circle", "x": 550, "y": 150, "radius": 50, "label": "Purple", "fillStyle": "solid"}
]
},
{
"id": "name",
"text": "What should we name this feature?",
"type": "text"
},
{
"id": "features",
"text": "Which features should we include?",
"type": "multi",
"options": ["Dark mode", "Animations", "Keyboard shortcuts", "Mobile support"]
}
]}'- No setup beyond install — Claude starts and stops canvas sessions automatically
- You can draw too — use the toolbar to annotate Claude's diagrams or sketch your own ideas
- Canvas-type questions — when Claude asks a
canvasquestion, draw your answer directly on the canvas - Export your work — use
claude-canvas export -f png|svg|jsonto save diagrams - Multiple sessions — each
startcreates an isolated session; useclaude-canvas listto see them all
Contributions are welcome! See CONTRIBUTING.md for setup instructions, development workflow, and guidelines.
This project is licensed under the MIT License — see the LICENSE file for details.
Built with ✨ by Udi Talias









