claude-canvas 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,599 @@
1
+ <p align="center">
2
+ <img src="docs/assets/claude_canvas_art_2.png" alt="claude-canvas" width="600" />
3
+ </p>
4
+
5
+ <h1 align="center">claude-canvas</h1>
6
+
7
+ <p align="center">
8
+ <strong>A visual canvas for Claude Code — instead of asking questions in the terminal, Claude can draw diagrams, wireframes, and mockups on a shared canvas and collect visual feedback from the user.</strong>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/claude-canvas"><img src="https://img.shields.io/npm/v/claude-canvas?style=for-the-badge&logo=npm&logoColor=white&color=CB3837" alt="npm version" /></a>
13
+ <a href="https://github.com/uditalias/claude-canvas/blob/main/LICENSE"><img src="https://img.shields.io/github/license/uditalias/claude-canvas?style=for-the-badge&color=blue" alt="License" /></a>
14
+ <a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-%3E%3D18-339933?style=for-the-badge&logo=node.js&logoColor=white" alt="Node.js" /></a>
15
+ <a href="https://www.typescriptlang.org"><img src="https://img.shields.io/badge/typescript-5.4-3178C6?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript" /></a>
16
+ <a href="https://github.com/uditalias/claude-canvas/issues"><img src="https://img.shields.io/github/issues/uditalias/claude-canvas?style=for-the-badge&logo=github&color=orange" alt="Issues" /></a>
17
+ </p>
18
+
19
+ <p align="center">
20
+ <a href="#installation">Installation</a> &bull;
21
+ <a href="#quick-start">Quick Start</a> &bull;
22
+ <a href="#cli-reference">CLI Reference</a> &bull;
23
+ <a href="#visual-qa">Visual Q&A</a> &bull;
24
+ <a href="#interactive-canvas">Interactive Canvas</a> &bull;
25
+ <a href="#claude-code-skill">Claude Code Skill</a> &bull;
26
+ <a href="#architecture">Architecture</a>
27
+ </p>
28
+
29
+ ---
30
+
31
+ ## What is claude-canvas?
32
+
33
+ **claude-canvas** gives [Claude Code](https://claude.ai/code) a visual canvas. It runs a local server that opens a browser-based drawing surface where Claude can send draw commands (shapes, arrows, text, freehand paths) via CLI or HTTP API, and users can draw interactively too. Communication happens in real-time over WebSocket.
34
+
35
+ It also serves as a **visual Q&A tool** — Claude can send structured questions alongside canvas drawings, and users answer by picking options, typing text, or drawing directly on the canvas.
36
+
37
+ <p align="center">
38
+ <img src="docs/screenshots/ui-drawing.png" alt="claude-canvas UI — architecture diagram with toolbar and canvas" width="700" />
39
+ </p>
40
+
41
+ ### Key Features
42
+
43
+ - **Sketchy hand-drawn aesthetic** — powered by [Rough.js](https://roughjs.com), all shapes render with a natural, whiteboard feel
44
+ - **Bidirectional drawing** — Claude draws via CLI/API, users draw interactively in the browser
45
+ - **Visual Q&A system** — ask structured questions with per-question canvas drawings, collect answers programmatically
46
+ - **Multiple fill styles** — hachure, solid, zigzag, cross-hatch, dots, dashed, and wireframe outlines
47
+ - **Session management** — run multiple isolated canvas sessions simultaneously
48
+ - **Real-time sync** — WebSocket-powered instant updates between CLI and browser
49
+ - **Export options** — save as PNG, SVG, or JSON
50
+ - **Claude Code skill** — install the skill so Claude automatically knows when and how to use the canvas
51
+
52
+ <p align="center">
53
+ <img src="docs/screenshots/fill-styles.png" alt="Fill styles gallery — hachure, solid, zigzag, cross-hatch, dots" width="700" />
54
+ </p>
55
+
56
+ ### How It Works
57
+
58
+ 1. **`claude-canvas start`** launches a local Express + WebSocket server and opens a browser tab
59
+ 2. **Claude Code** sends draw commands and questions via the CLI (which hits the HTTP API)
60
+ 3. The **server broadcasts** commands to the browser over WebSocket in real-time
61
+ 4. **Users interact** directly on the canvas — drawing, answering questions, or annotating Claude's work
62
+ 5. **`claude-canvas screenshot`** captures the canvas state and returns answers to any pending questions
63
+
64
+ ---
65
+
66
+ ## Installation
67
+
68
+ ### Via npm (recommended)
69
+
70
+ ```bash
71
+ npm install -g claude-canvas
72
+ ```
73
+
74
+ ### From source
75
+
76
+ ```bash
77
+ git clone https://github.com/uditalias/claude-canvas.git
78
+ cd claude-canvas
79
+ npm install
80
+ npm run build
81
+ npm link # makes `claude-canvas` available globally
82
+ ```
83
+
84
+ ### Requirements
85
+
86
+ - **Node.js** >= 18
87
+ - A modern browser (Chrome, Firefox, Safari, Edge)
88
+
89
+ ---
90
+
91
+ ## Quick Start
92
+
93
+ **1. Start a canvas session:**
94
+
95
+ ```bash
96
+ claude-canvas start
97
+ ```
98
+
99
+ This opens a browser tab with a fresh canvas and returns session info:
100
+
101
+ ```json
102
+ {"sessionId": "a1b2c3d4", "port": 7890, "url": "http://127.0.0.1:7890", "pid": 1234}
103
+ ```
104
+
105
+ **2. Draw something:**
106
+
107
+ ```bash
108
+ claude-canvas draw '{"commands": [
109
+ {"type": "rect", "x": 50, "y": 50, "width": 200, "height": 100, "label": "Frontend"},
110
+ {"type": "rect", "x": 350, "y": 50, "width": 200, "height": 100, "label": "Backend"},
111
+ {"type": "arrow", "x1": 250, "y1": 100, "x2": 350, "y2": 100, "label": "API"}
112
+ ]}'
113
+ ```
114
+
115
+ **3. Take a screenshot:**
116
+
117
+ ```bash
118
+ claude-canvas screenshot
119
+ ```
120
+
121
+ ```json
122
+ {"ok": true, "path": "/tmp/claude-canvas/canvas-123.png", "answers": []}
123
+ ```
124
+
125
+ **4. Stop the session when done:**
126
+
127
+ ```bash
128
+ claude-canvas stop --all
129
+ ```
130
+
131
+ ---
132
+
133
+ ## CLI Reference
134
+
135
+ All commands accept `-s, --session <id>`. You can omit it when only one session is running.
136
+
137
+ ### Session Management
138
+
139
+ | Command | Description |
140
+ |---------|-------------|
141
+ | `claude-canvas start` | Start a new canvas session (opens browser) |
142
+ | `claude-canvas start -p 8080` | Start on a specific port |
143
+ | `claude-canvas stop -s <id>` | Stop a specific session |
144
+ | `claude-canvas stop --all` | Stop all running sessions |
145
+
146
+ ### Drawing
147
+
148
+ ```bash
149
+ # Send draw commands as JSON
150
+ claude-canvas draw '{"commands": [...]}'
151
+
152
+ # Read from stdin (useful for large payloads)
153
+ echo '{"commands": [...]}' | claude-canvas draw -
154
+
155
+ # Render instantly without animation
156
+ claude-canvas draw --no-animate '{"commands": [...]}'
157
+ ```
158
+
159
+ ### Canvas Operations
160
+
161
+ | Command | Description |
162
+ |---------|-------------|
163
+ | `claude-canvas clear` | Clear all objects from the canvas |
164
+ | `claude-canvas clear --layer claude` | Clear only Claude's objects (keep user drawings) |
165
+ | `claude-canvas screenshot` | Capture canvas as PNG and collect Q&A answers |
166
+ | `claude-canvas export -f png` | Export as PNG |
167
+ | `claude-canvas export -f svg` | Export as SVG |
168
+ | `claude-canvas export -f json` | Export as JSON |
169
+ | `claude-canvas export -f png --labels` | Export with shape labels included |
170
+
171
+ <details>
172
+ <summary><strong>DrawCommand Types</strong> (click to expand)</summary>
173
+
174
+ #### Shapes
175
+
176
+ All support optional `label`, `color`, `opacity`, and `fillStyle`:
177
+
178
+ ```jsonc
179
+ // Rectangle
180
+ {"type": "rect", "x": 50, "y": 50, "width": 200, "height": 120, "label": "Header"}
181
+
182
+ // Circle
183
+ {"type": "circle", "x": 200, "y": 200, "radius": 60, "label": "Node"}
184
+
185
+ // Ellipse
186
+ {"type": "ellipse", "x": 300, "y": 150, "width": 180, "height": 100}
187
+ ```
188
+
189
+ #### Lines and Arrows
190
+
191
+ ```jsonc
192
+ // Line
193
+ {"type": "line", "x1": 100, "y1": 100, "x2": 300, "y2": 100}
194
+
195
+ // Arrow (with directional head)
196
+ {"type": "arrow", "x1": 100, "y1": 200, "x2": 300, "y2": 200, "label": "flow"}
197
+ ```
198
+
199
+ #### Text
200
+
201
+ ```jsonc
202
+ // textAlign: "left" | "center" | "right"
203
+ {"type": "text", "x": 200, "y": 50, "content": "Title", "fontSize": 24, "textAlign": "center"}
204
+ ```
205
+
206
+ #### Freehand
207
+
208
+ ```jsonc
209
+ {"type": "freehand", "points": [[10, 10], [50, 30], [90, 10], [130, 30]]}
210
+ ```
211
+
212
+ #### Groups and Connectors
213
+
214
+ For structured flowcharts:
215
+
216
+ ```jsonc
217
+ // Group: bundle shapes under an ID for connectors
218
+ {"type": "group", "id": "box-a", "commands": [
219
+ {"type": "rect", "x": 200, "y": 30, "width": 140, "height": 60},
220
+ {"type": "text", "x": 270, "y": 50, "content": "Start", "textAlign": "center"}
221
+ ]}
222
+
223
+ // Connector: auto-routes between group edges
224
+ {"type": "connector", "from": "box-a", "to": "box-b", "label": "next"}
225
+ ```
226
+
227
+ </details>
228
+
229
+ ### Fill Styles
230
+
231
+ Shapes default to `"hachure"`. Set `fillStyle` on any shape:
232
+
233
+ | Style | Description |
234
+ |-------|-------------|
235
+ | `hachure` | Hand-drawn diagonal lines (default) |
236
+ | `solid` | Solid fill |
237
+ | `zigzag` | Zigzag pattern |
238
+ | `cross-hatch` | Cross-hatched lines |
239
+ | `dots` | Dotted pattern |
240
+ | `dashed` | Dashed lines |
241
+ | `zigzag-line` | Zigzag line pattern |
242
+ | `none` | No fill (wireframe outline only) |
243
+
244
+ ---
245
+
246
+ ## Visual Q&A
247
+
248
+ The Q&A system lets Claude send structured questions with visual context. A floating panel appears in the browser where users can answer by clicking options, typing text, or drawing.
249
+
250
+ <p align="center">
251
+ <img src="docs/screenshots/ui-ask.png" alt="Visual Q&A — question panel with layout options" width="700" />
252
+ </p>
253
+
254
+ Users select answers via interactive pill buttons. Selected answers are highlighted:
255
+
256
+ <p align="center">
257
+ <img src="docs/screenshots/ui-ask-answered.png" alt="Visual Q&A — answer selected" width="700" />
258
+ </p>
259
+
260
+ ### Sending Questions
261
+
262
+ ```bash
263
+ claude-canvas ask '{"questions": [
264
+ {
265
+ "id": "q1",
266
+ "text": "Which layout do you prefer?",
267
+ "type": "single",
268
+ "options": ["Layout A", "Layout B", "Layout C"],
269
+ "commands": [
270
+ {"type": "rect", "x": 80, "y": 80, "width": 200, "height": 150, "label": "Layout A"},
271
+ {"type": "rect", "x": 350, "y": 80, "width": 200, "height": 150, "label": "Layout B"}
272
+ ]
273
+ },
274
+ {
275
+ "id": "q2",
276
+ "text": "What should the title be?",
277
+ "type": "text"
278
+ }
279
+ ]}'
280
+ ```
281
+
282
+ ### Question Types
283
+
284
+ | Type | Description | User interaction | Answer format |
285
+ |------|------------|------------------|---------------|
286
+ | `single` | Pick one option | Radio-style pill buttons | `"value": "Option A"` |
287
+ | `multi` | Pick multiple options | Toggle pill buttons | `"value": ["Option A", "Option C"]` |
288
+ | `text` | Free text input | Text field | `"value": "user's text"` |
289
+ | `canvas` | Draw on canvas | Freeform drawing | `"value": "see canvas"` + snapshot PNG |
290
+
291
+ ### Collecting Answers
292
+
293
+ After sending questions, call `screenshot` to retrieve answers:
294
+
295
+ ```bash
296
+ claude-canvas screenshot
297
+ ```
298
+
299
+ ```json
300
+ {
301
+ "ok": true,
302
+ "path": "/tmp/claude-canvas/canvas-123.png",
303
+ "answers": [
304
+ {"questionId": "q1", "value": "Layout A"},
305
+ {"questionId": "q2", "value": "My Custom Title"}
306
+ ]
307
+ }
308
+ ```
309
+
310
+ For `canvas`-type questions, Claude draws a diagram and the user responds by drawing directly on the canvas. The answer includes a snapshot of what the user drew:
311
+
312
+ <p align="center">
313
+ <img src="docs/screenshots/ui-canvas-answer.png" alt="Canvas Q&A — Claude draws a wireframe, user annotates with freehand drawings" width="700" />
314
+ </p>
315
+
316
+ ```json
317
+ {"questionId": "q3", "value": "see canvas", "canvasSnapshot": "/tmp/claude-canvas/canvas-q3-456.png"}
318
+ ```
319
+
320
+ ---
321
+
322
+ ## Interactive Canvas
323
+
324
+ The browser canvas is a full interactive drawing surface, not just a display. Users can draw alongside Claude's shapes in real-time.
325
+
326
+ ### Drawing Tools
327
+
328
+ The toolbar provides these drawing tools:
329
+
330
+ | Tool | Description |
331
+ |------|-------------|
332
+ | Rectangle | Draw rectangles with optional fill |
333
+ | Circle | Draw circles |
334
+ | Line | Draw straight lines |
335
+ | Arrow | Draw directional arrows |
336
+ | Freehand | Freeform pencil drawing |
337
+ | Text | Click to place text |
338
+ | Paint | Brush painting with adjustable size |
339
+
340
+ ### Canvas Features
341
+
342
+ - **Zoom & Pan** — scroll to zoom, drag to pan the canvas
343
+ - **Undo/Redo** — full history support (up to 50 states)
344
+ - **Snap Guides** — alignment guides appear when moving objects near other objects
345
+ - **Context Menu** — right-click any shape to change color, fill, opacity, label, lock, or layer order
346
+ - **Color Palette** — soft muted color presets with custom color picker
347
+ - **Brush Size** — adjustable size for paint and freehand tools
348
+ - **Dark Mode** — respects system theme preference
349
+ - **Keyboard Shortcuts** — quick tool switching via keyboard
350
+
351
+ ### Layer System
352
+
353
+ Objects have a layer property:
354
+ - **`user`** — shapes drawn interactively in the browser
355
+ - **`claude`** — shapes drawn via the CLI/API
356
+
357
+ Use `claude-canvas clear --layer claude` to remove Claude's drawings without affecting user drawings.
358
+
359
+ ---
360
+
361
+ ## Claude Code Skill
362
+
363
+ Install the included skill so Claude Code automatically knows when and how to use the canvas.
364
+
365
+ ### Installation
366
+
367
+ ```bash
368
+ cp -r src/skill/claude-canvas ~/.claude/skills/
369
+ ```
370
+
371
+ Or if installed globally via npm:
372
+
373
+ ```bash
374
+ cp -r $(npm root -g)/claude-canvas/src/skill/claude-canvas ~/.claude/skills/
375
+ ```
376
+
377
+ ### What the Skill Does
378
+
379
+ Once installed, Claude Code will automatically use the canvas when it makes sense — for example:
380
+
381
+ - Drawing architecture diagrams during system design discussions
382
+ - Sketching UI wireframes when discussing layouts
383
+ - Creating flowcharts to explain processes
384
+ - Presenting visual options and asking for your preference via Q&A
385
+
386
+ You don't need to explicitly tell Claude to use the canvas. The skill teaches Claude when the canvas is the right tool for the job.
387
+
388
+ ---
389
+
390
+ ## Architecture
391
+
392
+ ```
393
+ ┌─────────────────┐
394
+ │ Claude Code │
395
+ │ (CLI / Skill) │
396
+ └────────┬────────┘
397
+ │ HTTP API
398
+ ┌────────▼────────┐
399
+ │ Express Server │
400
+ │ + WebSocket │
401
+ └────────┬────────┘
402
+ │ WebSocket
403
+ ┌────────▼────────┐
404
+ │ Browser Canvas │
405
+ │ React + Fabric │
406
+ └─────────────────┘
407
+ ```
408
+
409
+ <p align="center">
410
+ <img src="docs/screenshots/architecture-diagram.png" alt="Architecture diagram drawn on claude-canvas" width="700" />
411
+ </p>
412
+
413
+ <details>
414
+ <summary><strong>Project Structure</strong> (click to expand)</summary>
415
+
416
+ ```
417
+ src/
418
+ ├── bin/claude-canvas.ts # CLI entry point (Commander)
419
+ ├── server/
420
+ │ ├── router.ts # REST API endpoints
421
+ │ ├── websocket.ts # WebSocket server
422
+ │ ├── state.ts # In-memory state & broadcast
423
+ │ └── process.ts # Session management (PID/port)
424
+ ├── client/
425
+ │ ├── components/
426
+ │ │ ├── Canvas.tsx # Main canvas view
427
+ │ │ ├── Toolbox.tsx # Drawing toolbar
428
+ │ │ ├── QuestionPanel.tsx # Q&A floating panel
429
+ │ │ ├── Hud.tsx # Connection status & zoom
430
+ │ │ └── ContextMenu.tsx # Right-click context menu
431
+ │ ├── hooks/
432
+ │ │ ├── useCanvas.ts # Fabric.js canvas + rough.js rendering
433
+ │ │ ├── useDrawingTools.ts# Interactive drawing tools
434
+ │ │ ├── useWebSocket.ts # WS connection + auto-reconnect
435
+ │ │ ├── useToolState.ts # Tool selection + shortcuts
436
+ │ │ ├── useUndoRedo.ts # Canvas history (50 states)
437
+ │ │ ├── useSnapGuides.ts # Alignment snap guides
438
+ │ │ └── useQuestionPanel.ts# Q&A state management
439
+ │ └── lib/
440
+ │ └── rough-line.ts # Custom Fabric objects for rough.js
441
+ ├── protocol/
442
+ │ └── types.ts # Shared types (DrawCommand, WsMessage, etc.)
443
+ └── skill/
444
+ └── claude-canvas.md # Claude Code skill definition
445
+ ```
446
+
447
+ </details>
448
+
449
+ ---
450
+
451
+ ## Development
452
+
453
+ ```bash
454
+ # Clone the repository
455
+ git clone https://github.com/uditalias/claude-canvas.git
456
+ cd claude-canvas
457
+ npm install
458
+
459
+ # Run in development mode (server with hot reload)
460
+ npm run dev
461
+
462
+ # Run client only (Vite dev server on :5173, proxies to :7890)
463
+ npm run dev:client
464
+
465
+ # Build everything
466
+ npm run build
467
+
468
+ # Run unit tests
469
+ npm test
470
+
471
+ # Run E2E tests (requires build first)
472
+ npm run build && npx playwright test
473
+ ```
474
+
475
+ ---
476
+
477
+ ## Examples
478
+
479
+ <details>
480
+ <summary><strong>Architecture Diagram</strong></summary>
481
+
482
+ ```bash
483
+ claude-canvas draw '{"commands": [
484
+ {"type": "text", "x": 400, "y": 40, "content": "System Architecture", "fontSize": 28, "textAlign": "center"},
485
+ {"type": "rect", "x": 50, "y": 100, "width": 180, "height": 80, "label": "Client App", "fillStyle": "hachure"},
486
+ {"type": "rect", "x": 310, "y": 100, "width": 180, "height": 80, "label": "API Gateway", "fillStyle": "solid"},
487
+ {"type": "rect", "x": 570, "y": 100, "width": 180, "height": 80, "label": "Database", "fillStyle": "dots"},
488
+ {"type": "arrow", "x1": 230, "y1": 140, "x2": 310, "y2": 140, "label": "REST"},
489
+ {"type": "arrow", "x1": 490, "y1": 140, "x2": 570, "y2": 140, "label": "SQL"}
490
+ ]}'
491
+ ```
492
+
493
+ </details>
494
+
495
+ <details>
496
+ <summary><strong>Wireframe Layout</strong></summary>
497
+
498
+ ```bash
499
+ claude-canvas draw '{"commands": [
500
+ {"type": "rect", "x": 50, "y": 30, "width": 500, "height": 60, "label": "Navigation", "fillStyle": "none"},
501
+ {"type": "rect", "x": 50, "y": 110, "width": 150, "height": 300, "label": "Sidebar", "fillStyle": "none"},
502
+ {"type": "rect", "x": 220, "y": 110, "width": 330, "height": 300, "label": "Main Content", "fillStyle": "none"}
503
+ ]}'
504
+ ```
505
+
506
+ </details>
507
+
508
+ <details>
509
+ <summary><strong>Flowchart with Connectors</strong></summary>
510
+
511
+ ```bash
512
+ claude-canvas draw '{"commands": [
513
+ {"type": "group", "id": "start", "commands": [
514
+ {"type": "rect", "x": 200, "y": 30, "width": 140, "height": 60},
515
+ {"type": "text", "x": 270, "y": 50, "content": "Start", "textAlign": "center"}
516
+ ]},
517
+ {"type": "group", "id": "process", "commands": [
518
+ {"type": "rect", "x": 200, "y": 150, "width": 140, "height": 60},
519
+ {"type": "text", "x": 270, "y": 170, "content": "Process", "textAlign": "center"}
520
+ ]},
521
+ {"type": "group", "id": "end", "commands": [
522
+ {"type": "rect", "x": 200, "y": 270, "width": 140, "height": 60},
523
+ {"type": "text", "x": 270, "y": 290, "content": "End", "textAlign": "center"}
524
+ ]},
525
+ {"type": "connector", "from": "start", "to": "process"},
526
+ {"type": "connector", "from": "process", "to": "end"}
527
+ ]}'
528
+ ```
529
+
530
+ </details>
531
+
532
+ <details>
533
+ <summary><strong>Visual Decision Making (Q&A)</strong></summary>
534
+
535
+ ```bash
536
+ claude-canvas ask '{"questions": [
537
+ {
538
+ "id": "theme",
539
+ "text": "Which color theme should we use?",
540
+ "type": "single",
541
+ "options": ["Blue Ocean", "Forest Green", "Sunset Purple"],
542
+ "commands": [
543
+ {"type": "circle", "x": 150, "y": 150, "radius": 50, "label": "Blue", "fillStyle": "solid"},
544
+ {"type": "circle", "x": 350, "y": 150, "radius": 50, "label": "Green", "fillStyle": "solid"},
545
+ {"type": "circle", "x": 550, "y": 150, "radius": 50, "label": "Purple", "fillStyle": "solid"}
546
+ ]
547
+ },
548
+ {
549
+ "id": "name",
550
+ "text": "What should we name this feature?",
551
+ "type": "text"
552
+ },
553
+ {
554
+ "id": "features",
555
+ "text": "Which features should we include?",
556
+ "type": "multi",
557
+ "options": ["Dark mode", "Animations", "Keyboard shortcuts", "Mobile support"]
558
+ }
559
+ ]}'
560
+ ```
561
+
562
+ </details>
563
+
564
+ ---
565
+
566
+ ## Tips
567
+
568
+ - The visible canvas area is roughly **1200 x 800 pixels** — place shapes within this range
569
+ - Use `label` on shapes for clarity — labels float above shapes as text overlays
570
+ - Use `textAlign: "center"` with text inside groups to center text within boxes
571
+ - For groups, place the text `x` at the center of the rect (`rect.x + rect.width / 2`)
572
+ - After drawing, call `screenshot` to capture and verify what the user sees
573
+ - Use `clear --layer claude` to remove Claude's drawings without erasing user drawings
574
+ - Connectors automatically route between group edges — just specify `from` and `to` group IDs
575
+ - Pass `color` as a hex string for custom colors: `"color": "#D4726A"`
576
+
577
+ ---
578
+
579
+ ## Contributing
580
+
581
+ Contributions are welcome! Please feel free to submit a [Pull Request](https://github.com/uditalias/claude-canvas/pulls).
582
+
583
+ 1. Fork the repository
584
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
585
+ 3. Commit your changes (`git commit -m 'Add amazing feature'`)
586
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
587
+ 5. Open a Pull Request
588
+
589
+ ---
590
+
591
+ ## License
592
+
593
+ This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
594
+
595
+ ---
596
+
597
+ <p align="center">
598
+ Built with &#10024; by <a href="https://github.com/uditalias">Udi Talias</a>
599
+ </p>
@@ -3038,6 +3038,7 @@ var {
3038
3038
 
3039
3039
  // src/bin/claude-canvas.ts
3040
3040
  var http = __toESM(require("http"));
3041
+ var https = __toESM(require("https"));
3041
3042
 
3042
3043
  // src/utils/port.ts
3043
3044
  var net = __toESM(require("net"));
@@ -3181,7 +3182,7 @@ var import_node_path = require("node:path");
3181
3182
  var import_node_url = require("node:url");
3182
3183
  var import_meta = {};
3183
3184
  function getVersion() {
3184
- if (true) return "1.0.0";
3185
+ if (true) return "1.0.2";
3185
3186
  try {
3186
3187
  const dir = (0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
3187
3188
  const pkg = JSON.parse((0, import_node_fs.readFileSync)((0, import_node_path.resolve)(dir, "../../package.json"), "utf-8"));
@@ -3302,7 +3303,43 @@ program2.command("export").description("Export the canvas as PNG, SVG, or JSON")
3302
3303
  process.exit(1);
3303
3304
  }
3304
3305
  });
3306
+ program2.command("update").description("Check for updates and install the latest version").action(async () => {
3307
+ const currentVersion = getVersion();
3308
+ console.log(`Current version: ${currentVersion}`);
3309
+ console.log("Checking for updates...");
3310
+ try {
3311
+ const latest = await fetchLatestVersion();
3312
+ if (latest === currentVersion) {
3313
+ console.log("You are already on the latest version.");
3314
+ return;
3315
+ }
3316
+ console.log(`New version available: ${latest}`);
3317
+ console.log("Updating...");
3318
+ const { execSync } = await import("child_process");
3319
+ execSync("npm install -g claude-canvas@latest", { stdio: "inherit" });
3320
+ console.log(`Successfully updated to ${latest}`);
3321
+ } catch (err) {
3322
+ console.error("Update failed:", err.message);
3323
+ process.exit(1);
3324
+ }
3325
+ });
3305
3326
  program2.parse();
3327
+ function fetchLatestVersion() {
3328
+ return new Promise((resolve3, reject) => {
3329
+ https.get("https://registry.npmjs.org/claude-canvas/latest", (res) => {
3330
+ let data = "";
3331
+ res.on("data", (chunk) => data += chunk);
3332
+ res.on("end", () => {
3333
+ try {
3334
+ const pkg = JSON.parse(data);
3335
+ resolve3(pkg.version);
3336
+ } catch {
3337
+ reject(new Error("Failed to parse npm registry response"));
3338
+ }
3339
+ });
3340
+ }).on("error", reject);
3341
+ });
3342
+ }
3306
3343
  function httpGet(url) {
3307
3344
  return new Promise((resolve3, reject) => {
3308
3345
  http.get(url, (res) => {