claude-canvas 1.0.2 → 1.0.4
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 +14 -2
- package/dist/bin/claude-canvas.js +75 -1
- package/package.json +6 -1
- package/scripts/postinstall.js +35 -112
package/README.md
CHANGED
|
@@ -69,8 +69,19 @@ It also serves as a **visual Q&A tool** — Claude can send structured questions
|
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
71
|
npm install -g claude-canvas
|
|
72
|
+
claude-canvas setup
|
|
72
73
|
```
|
|
73
74
|
|
|
75
|
+
The `setup` command installs the Claude Code skill, which lets Claude automatically use the canvas when it makes sense.
|
|
76
|
+
|
|
77
|
+
### Updating
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
claude-canvas update
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
This checks for the latest version, installs it, and automatically updates the Claude Code skill if it has changed.
|
|
84
|
+
|
|
74
85
|
### From source
|
|
75
86
|
|
|
76
87
|
```bash
|
|
@@ -79,6 +90,7 @@ cd claude-canvas
|
|
|
79
90
|
npm install
|
|
80
91
|
npm run build
|
|
81
92
|
npm link # makes `claude-canvas` available globally
|
|
93
|
+
claude-canvas setup
|
|
82
94
|
```
|
|
83
95
|
|
|
84
96
|
### Requirements
|
|
@@ -365,10 +377,10 @@ Install the included skill so Claude Code automatically knows when and how to us
|
|
|
365
377
|
### Installation
|
|
366
378
|
|
|
367
379
|
```bash
|
|
368
|
-
|
|
380
|
+
claude-canvas setup
|
|
369
381
|
```
|
|
370
382
|
|
|
371
|
-
|
|
383
|
+
This interactively installs (or updates) the skill to `~/.claude/skills/claude-canvas/`. You can also install it manually:
|
|
372
384
|
|
|
373
385
|
```bash
|
|
374
386
|
cp -r $(npm root -g)/claude-canvas/src/skill/claude-canvas ~/.claude/skills/
|
|
@@ -3179,10 +3179,12 @@ function spawnServer(port) {
|
|
|
3179
3179
|
// src/bin/claude-canvas.ts
|
|
3180
3180
|
var import_node_fs = require("node:fs");
|
|
3181
3181
|
var import_node_path = require("node:path");
|
|
3182
|
+
var import_node_os = require("node:os");
|
|
3183
|
+
var import_node_readline = require("node:readline");
|
|
3182
3184
|
var import_node_url = require("node:url");
|
|
3183
3185
|
var import_meta = {};
|
|
3184
3186
|
function getVersion() {
|
|
3185
|
-
if (true) return "1.0.
|
|
3187
|
+
if (true) return "1.0.4";
|
|
3186
3188
|
try {
|
|
3187
3189
|
const dir = (0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
3188
3190
|
const pkg = JSON.parse((0, import_node_fs.readFileSync)((0, import_node_path.resolve)(dir, "../../package.json"), "utf-8"));
|
|
@@ -3318,11 +3320,83 @@ program2.command("update").description("Check for updates and install the latest
|
|
|
3318
3320
|
const { execSync } = await import("child_process");
|
|
3319
3321
|
execSync("npm install -g claude-canvas@latest", { stdio: "inherit" });
|
|
3320
3322
|
console.log(`Successfully updated to ${latest}`);
|
|
3323
|
+
const skillDestDir = (0, import_node_path.join)((0, import_node_os.homedir)(), ".claude", "skills", "claude-canvas");
|
|
3324
|
+
const skillDest = (0, import_node_path.join)(skillDestDir, "SKILL.md");
|
|
3325
|
+
if ((0, import_node_fs.existsSync)(skillDest)) {
|
|
3326
|
+
const skillSourceDir = (0, import_node_path.resolve)((0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(import_meta.url)), "../../src/skill/claude-canvas");
|
|
3327
|
+
const skillSource = (0, import_node_path.join)(skillSourceDir, "SKILL.md");
|
|
3328
|
+
if ((0, import_node_fs.existsSync)(skillSource)) {
|
|
3329
|
+
const installed = (0, import_node_fs.readFileSync)(skillDest, "utf-8");
|
|
3330
|
+
const bundled = (0, import_node_fs.readFileSync)(skillSource, "utf-8");
|
|
3331
|
+
if (installed !== bundled) {
|
|
3332
|
+
(0, import_node_fs.copyFileSync)(skillSource, skillDest);
|
|
3333
|
+
console.log("\x1B[32m\u2713\x1B[0m Claude Code skill updated to the latest version.");
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
}
|
|
3321
3337
|
} catch (err) {
|
|
3322
3338
|
console.error("Update failed:", err.message);
|
|
3323
3339
|
process.exit(1);
|
|
3324
3340
|
}
|
|
3325
3341
|
});
|
|
3342
|
+
program2.command("setup").description("Install or update the Claude Code skill for canvas").action(async () => {
|
|
3343
|
+
const skillSourceDir = (0, import_node_path.resolve)((0, import_node_path.dirname)((0, import_node_url.fileURLToPath)(import_meta.url)), "../../src/skill/claude-canvas");
|
|
3344
|
+
const skillSource = (0, import_node_path.join)(skillSourceDir, "SKILL.md");
|
|
3345
|
+
const skillDestDir = (0, import_node_path.join)((0, import_node_os.homedir)(), ".claude", "skills", "claude-canvas");
|
|
3346
|
+
const skillDest = (0, import_node_path.join)(skillDestDir, "SKILL.md");
|
|
3347
|
+
const skillUrl = "https://github.com/uditalias/claude-canvas/blob/main/src/skill/claude-canvas/SKILL.md";
|
|
3348
|
+
if (!(0, import_node_fs.existsSync)(skillSource)) {
|
|
3349
|
+
console.error("Skill source not found. Try reinstalling claude-canvas.");
|
|
3350
|
+
process.exit(1);
|
|
3351
|
+
}
|
|
3352
|
+
const bundled = (0, import_node_fs.readFileSync)(skillSource, "utf-8");
|
|
3353
|
+
const installed = (0, import_node_fs.existsSync)(skillDest) ? (0, import_node_fs.readFileSync)(skillDest, "utf-8") : null;
|
|
3354
|
+
console.log("");
|
|
3355
|
+
if (installed && installed === bundled) {
|
|
3356
|
+
console.log(" \x1B[1m\x1B[32m\u2713\x1B[0m Skill is already installed and up to date.");
|
|
3357
|
+
console.log(` \x1B[2m${skillDest}\x1B[0m`);
|
|
3358
|
+
console.log("");
|
|
3359
|
+
return;
|
|
3360
|
+
}
|
|
3361
|
+
const isUpdate = installed !== null;
|
|
3362
|
+
console.log(isUpdate ? " \x1B[1m\x1B[33m\u26A1\x1B[0m A new version of the claude-canvas skill is available." : " \x1B[1m\x1B[36m\u2728\x1B[0m claude-canvas skill setup");
|
|
3363
|
+
console.log("");
|
|
3364
|
+
console.log(" The skill lets Claude Code use the canvas tool automatically.");
|
|
3365
|
+
console.log(" It will be installed to:");
|
|
3366
|
+
console.log(` \x1B[36m${skillDest}\x1B[0m`);
|
|
3367
|
+
console.log("");
|
|
3368
|
+
const rl = (0, import_node_readline.createInterface)({ input: process.stdin, output: process.stdout });
|
|
3369
|
+
const ask = (q) => new Promise((resolve3) => rl.question(q, (a) => resolve3(a.trim().toLowerCase())));
|
|
3370
|
+
const viewSkill = await ask(" Would you like to view the skill before installing? (y/N) ");
|
|
3371
|
+
if (viewSkill === "y" || viewSkill === "yes") {
|
|
3372
|
+
console.log("");
|
|
3373
|
+
console.log(` \x1B[4m${skillUrl}\x1B[0m`);
|
|
3374
|
+
console.log("");
|
|
3375
|
+
}
|
|
3376
|
+
const action = isUpdate ? "Update" : "Install";
|
|
3377
|
+
const confirm = await ask(` ${action} the skill to ~/.claude/skills/? (Y/n) `);
|
|
3378
|
+
if (confirm === "n" || confirm === "no") {
|
|
3379
|
+
console.log("");
|
|
3380
|
+
console.log(" Skipped. You can run this again anytime with:");
|
|
3381
|
+
console.log(" \x1B[33mclaude-canvas setup\x1B[0m");
|
|
3382
|
+
console.log("");
|
|
3383
|
+
} else {
|
|
3384
|
+
try {
|
|
3385
|
+
(0, import_node_fs.mkdirSync)(skillDestDir, { recursive: true });
|
|
3386
|
+
(0, import_node_fs.copyFileSync)(skillSource, skillDest);
|
|
3387
|
+
console.log("");
|
|
3388
|
+
console.log(` \x1B[1m\x1B[32m\u2713\x1B[0m Skill ${isUpdate ? "updated" : "installed"} to \x1B[36m${skillDest}\x1B[0m`);
|
|
3389
|
+
console.log("");
|
|
3390
|
+
} catch (err) {
|
|
3391
|
+
console.log("");
|
|
3392
|
+
console.log(` \x1B[31m\u2717 Failed: ${err.message}\x1B[0m`);
|
|
3393
|
+
console.log(" You can install it manually:");
|
|
3394
|
+
console.log(` \x1B[33mcp -r $(npm root -g)/claude-canvas/src/skill/claude-canvas ~/.claude/skills/\x1B[0m`);
|
|
3395
|
+
console.log("");
|
|
3396
|
+
}
|
|
3397
|
+
}
|
|
3398
|
+
rl.close();
|
|
3399
|
+
});
|
|
3326
3400
|
program2.parse();
|
|
3327
3401
|
function fetchLatestVersion() {
|
|
3328
3402
|
return new Promise((resolve3, reject) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-canvas",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "A shared visual canvas for Claude Code",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Udi Talias",
|
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
"bugs": {
|
|
13
13
|
"url": "https://github.com/uditalias/claude-canvas/issues"
|
|
14
14
|
},
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"provenance": false,
|
|
17
|
+
"access": "public",
|
|
18
|
+
"registry": "https://registry.npmjs.org/"
|
|
19
|
+
},
|
|
15
20
|
"keywords": [
|
|
16
21
|
"claude",
|
|
17
22
|
"canvas",
|
package/scripts/postinstall.js
CHANGED
|
@@ -1,126 +1,49 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const readline = require("readline");
|
|
4
3
|
const fs = require("fs");
|
|
5
4
|
const path = require("path");
|
|
6
5
|
const os = require("os");
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const SKILL_DEST = path.join(SKILL_DEST_DIR, "SKILL.md");
|
|
11
|
-
const SKILL_URL =
|
|
12
|
-
"https://github.com/uditalias/claude-canvas/blob/main/src/skill/claude-canvas/SKILL.md";
|
|
13
|
-
|
|
14
|
-
// Skip in CI or non-interactive environments
|
|
15
|
-
if (
|
|
16
|
-
process.env.CI ||
|
|
17
|
-
process.env.NODE_ENV === "test" ||
|
|
18
|
-
!process.stdin.isTTY
|
|
19
|
-
) {
|
|
7
|
+
// Skip in CI or test environments
|
|
8
|
+
if (process.env.CI || process.env.NODE_ENV === "test") {
|
|
20
9
|
process.exit(0);
|
|
21
10
|
}
|
|
22
11
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
print(
|
|
43
|
-
" claude-canvas is a visual canvas tool for \x1b[1mClaude Code\x1b[0m."
|
|
44
|
-
);
|
|
45
|
-
print(
|
|
46
|
-
" Instead of asking questions in the terminal, Claude can draw diagrams,"
|
|
47
|
-
);
|
|
48
|
-
print(
|
|
49
|
-
" wireframes, and mockups on a shared canvas and collect visual feedback"
|
|
50
|
-
);
|
|
51
|
-
print(" from you directly in the browser.");
|
|
52
|
-
print("");
|
|
53
|
-
print(" \x1b[1mHow it works:\x1b[0m");
|
|
54
|
-
print(
|
|
55
|
-
" 1. Claude runs \x1b[33mclaude-canvas start\x1b[0m to open a canvas in your browser"
|
|
56
|
-
);
|
|
57
|
-
print(
|
|
58
|
-
" 2. Claude draws shapes, diagrams, or wireframes on the canvas"
|
|
59
|
-
);
|
|
60
|
-
print(
|
|
61
|
-
" 3. Claude asks you visual questions — you answer by clicking or drawing"
|
|
62
|
-
);
|
|
63
|
-
print(
|
|
64
|
-
" 4. Claude captures your answers with \x1b[33mclaude-canvas screenshot\x1b[0m"
|
|
65
|
-
);
|
|
66
|
-
print("");
|
|
67
|
-
print(" \x1b[1m\x1b[33m⚠ Important:\x1b[0m For Claude to use this tool automatically, you need");
|
|
68
|
-
print(" to install the \x1b[1mclaude-canvas skill\x1b[0m into your Claude Code skills folder.");
|
|
69
|
-
print("");
|
|
70
|
-
|
|
71
|
-
const viewSkill = await ask(
|
|
72
|
-
" Would you like to view the skill before installing? (y/N) "
|
|
73
|
-
);
|
|
74
|
-
if (viewSkill === "y" || viewSkill === "yes") {
|
|
75
|
-
print("");
|
|
76
|
-
print(` \x1b[4m${SKILL_URL}\x1b[0m`);
|
|
77
|
-
print("");
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const installSkill = await ask(
|
|
81
|
-
" Install the skill to ~/.claude/skills/? (Y/n) "
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
if (installSkill === "n" || installSkill === "no") {
|
|
85
|
-
print("");
|
|
86
|
-
print(" Skipped skill installation. You can install it later with:");
|
|
87
|
-
print("");
|
|
88
|
-
print(
|
|
89
|
-
` \x1b[33mcp -r $(npm root -g)/claude-canvas/src/skill/claude-canvas ~/.claude/skills/\x1b[0m`
|
|
90
|
-
);
|
|
91
|
-
print("");
|
|
92
|
-
} else {
|
|
93
|
-
try {
|
|
94
|
-
fs.mkdirSync(SKILL_DEST_DIR, { recursive: true });
|
|
12
|
+
const SKILL_DEST = path.join(os.homedir(), ".claude", "skills", "claude-canvas", "SKILL.md");
|
|
13
|
+
const skillInstalled = fs.existsSync(SKILL_DEST);
|
|
14
|
+
|
|
15
|
+
console.log("");
|
|
16
|
+
console.log(" \x1b[1m\x1b[36m✨ claude-canvas installed successfully!\x1b[0m");
|
|
17
|
+
console.log("");
|
|
18
|
+
console.log(" claude-canvas is a visual canvas tool for \x1b[1mClaude Code\x1b[0m.");
|
|
19
|
+
console.log(" Instead of asking questions in the terminal, Claude can draw diagrams,");
|
|
20
|
+
console.log(" wireframes, and mockups on a shared canvas and collect visual feedback");
|
|
21
|
+
console.log(" from you directly in the browser.");
|
|
22
|
+
console.log("");
|
|
23
|
+
|
|
24
|
+
if (skillInstalled) {
|
|
25
|
+
// Check if the skill needs updating
|
|
26
|
+
const SKILL_SOURCE = path.resolve(__dirname, "../src/skill/claude-canvas/SKILL.md");
|
|
27
|
+
try {
|
|
28
|
+
const installed = fs.readFileSync(SKILL_DEST, "utf-8");
|
|
29
|
+
const bundled = fs.readFileSync(SKILL_SOURCE, "utf-8");
|
|
30
|
+
if (installed !== bundled) {
|
|
95
31
|
fs.copyFileSync(SKILL_SOURCE, SKILL_DEST);
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
` \x1b[1m\x1b[32m✓\x1b[0m Skill installed to \x1b[36m${SKILL_DEST}\x1b[0m`
|
|
99
|
-
);
|
|
100
|
-
print("");
|
|
101
|
-
} catch (err) {
|
|
102
|
-
print("");
|
|
103
|
-
print(` \x1b[31m✗ Failed to install skill: ${err.message}\x1b[0m`);
|
|
104
|
-
print(" You can install it manually:");
|
|
105
|
-
print("");
|
|
106
|
-
print(
|
|
107
|
-
` \x1b[33mcp -r $(npm root -g)/claude-canvas/src/skill/claude-canvas ~/.claude/skills/\x1b[0m`
|
|
108
|
-
);
|
|
109
|
-
print("");
|
|
32
|
+
console.log(" \x1b[1m\x1b[32m✓\x1b[0m Skill updated to the latest version.");
|
|
33
|
+
console.log("");
|
|
110
34
|
}
|
|
35
|
+
} catch {
|
|
36
|
+
// Ignore errors — user can run setup manually
|
|
111
37
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
);
|
|
118
|
-
print("");
|
|
119
|
-
|
|
120
|
-
rl.close();
|
|
38
|
+
} else {
|
|
39
|
+
console.log(" \x1b[1m\x1b[33m⚠ Important:\x1b[0m To let Claude use this tool automatically,");
|
|
40
|
+
console.log(" install the skill by running:");
|
|
41
|
+
console.log("");
|
|
42
|
+
console.log(" \x1b[33mclaude-canvas setup\x1b[0m");
|
|
43
|
+
console.log("");
|
|
121
44
|
}
|
|
122
45
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
46
|
+
console.log(" \x1b[1mGet started:\x1b[0m");
|
|
47
|
+
console.log(" \x1b[33mclaude-canvas start\x1b[0m Open a new canvas session");
|
|
48
|
+
console.log(" \x1b[33mclaude-canvas --help\x1b[0m See all available commands");
|
|
49
|
+
console.log("");
|