claude-queue 1.0.0 → 1.0.3
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/dist/cli.js +113 -11
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
2
8
|
|
|
3
9
|
// src/index.ts
|
|
4
10
|
import { program } from "commander";
|
|
@@ -49,6 +55,19 @@ function getRunningPid() {
|
|
|
49
55
|
return null;
|
|
50
56
|
}
|
|
51
57
|
}
|
|
58
|
+
function findServerPidByPort(port) {
|
|
59
|
+
try {
|
|
60
|
+
const { execSync } = __require("child_process");
|
|
61
|
+
const result = execSync(`lsof -ti tcp:${port}`, { encoding: "utf-8" }).trim();
|
|
62
|
+
if (result) {
|
|
63
|
+
const pids = result.split("\n").map((p) => parseInt(p.trim()));
|
|
64
|
+
return pids[0] || null;
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
52
71
|
function savePid(pid) {
|
|
53
72
|
ensureKanbanDir();
|
|
54
73
|
writeFileSync(PID_FILE, pid.toString());
|
|
@@ -99,8 +118,19 @@ async function startServer(port, detach, verbose) {
|
|
|
99
118
|
}
|
|
100
119
|
const child = spawn("node", [serverPath], {
|
|
101
120
|
env,
|
|
102
|
-
stdio: verbose ? "inherit" : "pipe"
|
|
121
|
+
stdio: verbose ? "inherit" : ["ignore", "pipe", "pipe"]
|
|
103
122
|
});
|
|
123
|
+
if (!verbose && child.stderr) {
|
|
124
|
+
let stderrOutput = "";
|
|
125
|
+
child.stderr.on("data", (data) => {
|
|
126
|
+
stderrOutput += data.toString();
|
|
127
|
+
});
|
|
128
|
+
child.on("exit", (code) => {
|
|
129
|
+
if (code !== 0 && stderrOutput) {
|
|
130
|
+
console.error("Server error:", stderrOutput.trim());
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
104
134
|
return child;
|
|
105
135
|
}
|
|
106
136
|
async function waitForServer(port, maxWait = 1e4) {
|
|
@@ -193,11 +223,11 @@ function getSkillPath() {
|
|
|
193
223
|
}
|
|
194
224
|
throw new Error("Skill file not found. Run 'pnpm build' first.");
|
|
195
225
|
}
|
|
196
|
-
function installSkills() {
|
|
226
|
+
function installSkills(force = false) {
|
|
197
227
|
const queueSkillDir = join3(SKILLS_DIR, "queue");
|
|
198
228
|
const queueSkillFile = join3(queueSkillDir, "SKILL.md");
|
|
199
|
-
if (existsSync2(queueSkillFile)) {
|
|
200
|
-
return;
|
|
229
|
+
if (existsSync2(queueSkillFile) && !force) {
|
|
230
|
+
return false;
|
|
201
231
|
}
|
|
202
232
|
if (!existsSync2(SKILLS_DIR)) {
|
|
203
233
|
mkdirSync2(SKILLS_DIR, { recursive: true });
|
|
@@ -209,6 +239,7 @@ function installSkills() {
|
|
|
209
239
|
const skillContent = readFileSync2(skillSourcePath, "utf-8");
|
|
210
240
|
writeFileSync2(queueSkillFile, skillContent);
|
|
211
241
|
console.log("\u2713 Installed /queue skill to ~/.claude/skills/queue/");
|
|
242
|
+
return true;
|
|
212
243
|
}
|
|
213
244
|
function removeMcp() {
|
|
214
245
|
const settingsPath = join3(CLAUDE_DIR, "settings.json");
|
|
@@ -287,7 +318,7 @@ async function runDoctor(port, fix) {
|
|
|
287
318
|
console.log(" \u2192 Created settings.json with MCP config");
|
|
288
319
|
}
|
|
289
320
|
}
|
|
290
|
-
const skillPath = join4(SKILLS_DIR, "
|
|
321
|
+
const skillPath = join4(SKILLS_DIR, "queue", "SKILL.md");
|
|
291
322
|
if (existsSync3(skillPath)) {
|
|
292
323
|
console.log("\u2705 /queue skill installed");
|
|
293
324
|
} else {
|
|
@@ -304,7 +335,7 @@ async function runDoctor(port, fix) {
|
|
|
304
335
|
console.log("\u26A0\uFE0F Queue data directory not created yet");
|
|
305
336
|
warnings++;
|
|
306
337
|
}
|
|
307
|
-
const dbPath = join4(KANBAN_DIR, "
|
|
338
|
+
const dbPath = join4(KANBAN_DIR, "queue.db");
|
|
308
339
|
if (existsSync3(dbPath)) {
|
|
309
340
|
const stats = await import("fs/promises").then((fs) => fs.stat(dbPath));
|
|
310
341
|
const sizeMB = (stats.size / 1024 / 1024).toFixed(2);
|
|
@@ -371,7 +402,7 @@ program.command("start", { isDefault: true }).description("Start the queue serve
|
|
|
371
402
|
const verbose = options.verbose || false;
|
|
372
403
|
ensureKanbanDir();
|
|
373
404
|
await configureMcp();
|
|
374
|
-
installSkills();
|
|
405
|
+
installSkills(true);
|
|
375
406
|
const running = await isServerRunning(port);
|
|
376
407
|
if (!running) {
|
|
377
408
|
if (verbose) {
|
|
@@ -450,20 +481,64 @@ program.command("status").description("Check server status").option("-p, --port
|
|
|
450
481
|
console.log("Server is not running");
|
|
451
482
|
}
|
|
452
483
|
});
|
|
453
|
-
program.command("stop").description("Stop the
|
|
454
|
-
const
|
|
484
|
+
program.command("stop").description("Stop the server").option("-p, --port <port>", "Server port", DEFAULT_PORT.toString()).action(async (options) => {
|
|
485
|
+
const port = parseInt(options.port);
|
|
486
|
+
let pid = getRunningPid();
|
|
455
487
|
if (!pid) {
|
|
456
|
-
|
|
488
|
+
pid = findServerPidByPort(port);
|
|
489
|
+
}
|
|
490
|
+
if (!pid) {
|
|
491
|
+
console.log("No server running");
|
|
457
492
|
return;
|
|
458
493
|
}
|
|
459
494
|
try {
|
|
460
495
|
process.kill(pid, "SIGTERM");
|
|
461
496
|
console.log(`Stopped server (PID: ${pid})`);
|
|
462
|
-
clearPid();
|
|
497
|
+
await clearPid();
|
|
463
498
|
} catch (error) {
|
|
464
499
|
console.error(`Failed to stop server: ${error}`);
|
|
465
500
|
}
|
|
466
501
|
});
|
|
502
|
+
program.command("restart").description("Restart the server").option("-p, --port <port>", "Server port", DEFAULT_PORT.toString()).option("-d, --detach", "Run server in background").option("-v, --verbose", "Verbose output").action(async (options) => {
|
|
503
|
+
const port = parseInt(options.port);
|
|
504
|
+
const detach = options.detach || false;
|
|
505
|
+
const verbose = options.verbose || false;
|
|
506
|
+
let pid = getRunningPid();
|
|
507
|
+
if (!pid) {
|
|
508
|
+
pid = findServerPidByPort(port);
|
|
509
|
+
}
|
|
510
|
+
if (pid) {
|
|
511
|
+
console.log("Stopping server...");
|
|
512
|
+
try {
|
|
513
|
+
process.kill(pid, "SIGTERM");
|
|
514
|
+
await clearPid();
|
|
515
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
516
|
+
} catch {
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
console.log("Starting server...");
|
|
520
|
+
ensureKanbanDir();
|
|
521
|
+
await configureMcp();
|
|
522
|
+
installSkills(true);
|
|
523
|
+
const child = await startServer(port, detach, verbose);
|
|
524
|
+
const serverReady = await waitForServer(port);
|
|
525
|
+
if (!serverReady) {
|
|
526
|
+
console.error("Server failed to start");
|
|
527
|
+
process.exit(1);
|
|
528
|
+
}
|
|
529
|
+
if (detach) {
|
|
530
|
+
console.log(`Server restarted on port ${port}`);
|
|
531
|
+
} else if (child) {
|
|
532
|
+
console.log(`Server running on port ${port}`);
|
|
533
|
+
console.log("Press Ctrl+C to stop");
|
|
534
|
+
process.on("SIGINT", () => {
|
|
535
|
+
child.kill();
|
|
536
|
+
process.exit(0);
|
|
537
|
+
});
|
|
538
|
+
await new Promise(() => {
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
});
|
|
467
542
|
program.command("logs").description("View server logs").option("-f, --follow", "Follow log output").option("-n, --lines <lines>", "Number of lines to show", "50").action(async (options) => {
|
|
468
543
|
if (!existsSync4(LOG_FILE)) {
|
|
469
544
|
console.log("No logs found");
|
|
@@ -517,6 +592,33 @@ program.command("doctor").description("Check system configuration and diagnose c
|
|
|
517
592
|
const fix = options.fix || false;
|
|
518
593
|
await runDoctor(port, fix);
|
|
519
594
|
});
|
|
595
|
+
program.command("upgrade").description("Upgrade claude-queue to the latest version").action(async () => {
|
|
596
|
+
console.log("\n\u{1F504} Upgrading claude-queue...\n");
|
|
597
|
+
const { execSync } = await import("child_process");
|
|
598
|
+
console.log("Updating npm package...");
|
|
599
|
+
try {
|
|
600
|
+
execSync("npm install -g claude-queue@latest", { stdio: "inherit" });
|
|
601
|
+
console.log("\u2713 Package updated\n");
|
|
602
|
+
} catch {
|
|
603
|
+
console.log("\u26A0\uFE0F Could not update globally, trying npx cache clear...");
|
|
604
|
+
try {
|
|
605
|
+
execSync("npx --yes clear-npx-cache 2>/dev/null || true", { stdio: "ignore" });
|
|
606
|
+
} catch {
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
console.log("Updating skill files...");
|
|
610
|
+
const skillUpdated = installSkills(true);
|
|
611
|
+
if (skillUpdated) {
|
|
612
|
+
console.log("\u2713 Skills updated\n");
|
|
613
|
+
} else {
|
|
614
|
+
console.log("\u26A0\uFE0F Could not update skills\n");
|
|
615
|
+
}
|
|
616
|
+
console.log("Updating MCP configuration...");
|
|
617
|
+
await configureMcp();
|
|
618
|
+
console.log("");
|
|
619
|
+
console.log("\u2705 Upgrade complete!");
|
|
620
|
+
console.log("\nRestart Claude Code to use the new version.");
|
|
621
|
+
});
|
|
520
622
|
program.command("uninstall").description("Remove MCP server and skill from Claude Code configuration").option("--all", "Also remove all data (database, logs)").action(async (options) => {
|
|
521
623
|
const fs = await import("fs/promises");
|
|
522
624
|
const { join: join6 } = await import("path");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-queue",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "A local kanban board for managing Claude Code projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"commander": "^14.0.2",
|
|
49
49
|
"cors": "^2.8.5",
|
|
50
50
|
"express": "^5.2.1",
|
|
51
|
+
"http-proxy-middleware": "^3.0.5",
|
|
51
52
|
"nanoid": "^5.1.6"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|