claudemesh-cli 0.1.2 → 0.1.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/dist/index.js +429 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -55344,7 +55344,7 @@ ${body}`;
|
|
|
55344
55344
|
}
|
|
55345
55345
|
async function startMcpServer() {
|
|
55346
55346
|
const config2 = loadConfig();
|
|
55347
|
-
const server = new Server({ name: "claudemesh", version: "0.1.
|
|
55347
|
+
const server = new Server({ name: "claudemesh", version: "0.1.4" }, {
|
|
55348
55348
|
capabilities: {
|
|
55349
55349
|
experimental: { "claude/channel": {} },
|
|
55350
55350
|
tools: {}
|
|
@@ -56081,8 +56081,418 @@ function runLaunch(extraArgs = []) {
|
|
|
56081
56081
|
});
|
|
56082
56082
|
}
|
|
56083
56083
|
|
|
56084
|
+
// src/commands/status.ts
|
|
56085
|
+
import { statSync, existsSync as existsSync3 } from "node:fs";
|
|
56086
|
+
// package.json
|
|
56087
|
+
var package_default = {
|
|
56088
|
+
name: "claudemesh-cli",
|
|
56089
|
+
version: "0.1.4",
|
|
56090
|
+
description: "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
|
|
56091
|
+
keywords: [
|
|
56092
|
+
"claude-code",
|
|
56093
|
+
"mcp",
|
|
56094
|
+
"model-context-protocol",
|
|
56095
|
+
"claudemesh",
|
|
56096
|
+
"peer-messaging",
|
|
56097
|
+
"multi-agent"
|
|
56098
|
+
],
|
|
56099
|
+
author: "Alejandro Gutiérrez",
|
|
56100
|
+
license: "MIT",
|
|
56101
|
+
homepage: "https://claudemesh.com",
|
|
56102
|
+
repository: {
|
|
56103
|
+
type: "git",
|
|
56104
|
+
url: "https://github.com/alezmad/claudemesh.git",
|
|
56105
|
+
directory: "apps/cli"
|
|
56106
|
+
},
|
|
56107
|
+
type: "module",
|
|
56108
|
+
bin: {
|
|
56109
|
+
claudemesh: "./dist/index.js"
|
|
56110
|
+
},
|
|
56111
|
+
files: [
|
|
56112
|
+
"dist",
|
|
56113
|
+
"README.md",
|
|
56114
|
+
"LICENSE"
|
|
56115
|
+
],
|
|
56116
|
+
publishConfig: {
|
|
56117
|
+
access: "public"
|
|
56118
|
+
},
|
|
56119
|
+
scripts: {
|
|
56120
|
+
build: 'bun build src/index.ts --target=node --outfile dist/index.js --banner "#!/usr/bin/env node" && chmod +x dist/index.js',
|
|
56121
|
+
clean: "git clean -xdf .cache .turbo dist node_modules",
|
|
56122
|
+
dev: "bun --hot src/index.ts",
|
|
56123
|
+
start: "bun src/index.ts",
|
|
56124
|
+
format: "prettier --check . --ignore-path ../../.gitignore",
|
|
56125
|
+
lint: "eslint",
|
|
56126
|
+
prepublishOnly: "bun run build",
|
|
56127
|
+
test: "vitest run",
|
|
56128
|
+
typecheck: "tsc --noEmit"
|
|
56129
|
+
},
|
|
56130
|
+
prettier: "@turbostarter/prettier-config",
|
|
56131
|
+
engines: {
|
|
56132
|
+
node: ">=20"
|
|
56133
|
+
},
|
|
56134
|
+
dependencies: {
|
|
56135
|
+
"@modelcontextprotocol/sdk": "1.27.1",
|
|
56136
|
+
"libsodium-wrappers": "0.7.15",
|
|
56137
|
+
ws: "8.20.0",
|
|
56138
|
+
zod: "4.1.13"
|
|
56139
|
+
},
|
|
56140
|
+
devDependencies: {
|
|
56141
|
+
"@turbostarter/eslint-config": "workspace:*",
|
|
56142
|
+
"@turbostarter/prettier-config": "workspace:*",
|
|
56143
|
+
"@turbostarter/tsconfig": "workspace:*",
|
|
56144
|
+
"@turbostarter/vitest-config": "workspace:*",
|
|
56145
|
+
"@types/libsodium-wrappers": "0.7.14",
|
|
56146
|
+
"@types/ws": "8.5.13",
|
|
56147
|
+
eslint: "catalog:",
|
|
56148
|
+
prettier: "catalog:",
|
|
56149
|
+
typescript: "catalog:",
|
|
56150
|
+
vitest: "catalog:"
|
|
56151
|
+
}
|
|
56152
|
+
};
|
|
56153
|
+
|
|
56154
|
+
// src/version.ts
|
|
56155
|
+
var VERSION = package_default.version;
|
|
56156
|
+
|
|
56157
|
+
// src/commands/status.ts
|
|
56158
|
+
async function probeBroker(url2, timeoutMs = 4000) {
|
|
56159
|
+
return new Promise((resolve2) => {
|
|
56160
|
+
const ws = new wrapper_default(url2);
|
|
56161
|
+
const timer = setTimeout(() => {
|
|
56162
|
+
try {
|
|
56163
|
+
ws.terminate();
|
|
56164
|
+
} catch {}
|
|
56165
|
+
resolve2({ ok: false, error: "timeout" });
|
|
56166
|
+
}, timeoutMs);
|
|
56167
|
+
ws.on("open", () => {
|
|
56168
|
+
clearTimeout(timer);
|
|
56169
|
+
try {
|
|
56170
|
+
ws.close();
|
|
56171
|
+
} catch {}
|
|
56172
|
+
resolve2({ ok: true });
|
|
56173
|
+
});
|
|
56174
|
+
ws.on("error", (err) => {
|
|
56175
|
+
clearTimeout(timer);
|
|
56176
|
+
resolve2({ ok: false, error: err.message });
|
|
56177
|
+
});
|
|
56178
|
+
});
|
|
56179
|
+
}
|
|
56180
|
+
async function runStatus() {
|
|
56181
|
+
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
56182
|
+
const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
56183
|
+
const green = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
|
|
56184
|
+
const red = (s) => useColor ? `\x1B[31m${s}\x1B[39m` : s;
|
|
56185
|
+
console.log(`claudemesh status (v${VERSION})`);
|
|
56186
|
+
console.log("─".repeat(60));
|
|
56187
|
+
const configPath = getConfigPath();
|
|
56188
|
+
let configPerms = "missing";
|
|
56189
|
+
if (existsSync3(configPath)) {
|
|
56190
|
+
const st = statSync(configPath);
|
|
56191
|
+
const mode = (st.mode & 511).toString(8).padStart(4, "0");
|
|
56192
|
+
configPerms = mode === "0600" ? `${mode} ✓` : `${mode} ⚠ (expected 0600)`;
|
|
56193
|
+
}
|
|
56194
|
+
console.log(`Config: ${configPath} (${configPerms})`);
|
|
56195
|
+
const config2 = loadConfig();
|
|
56196
|
+
if (config2.meshes.length === 0) {
|
|
56197
|
+
console.log("");
|
|
56198
|
+
console.log(dim("No meshes joined. Run `claudemesh join <invite-url>` to get started."));
|
|
56199
|
+
process.exit(0);
|
|
56200
|
+
}
|
|
56201
|
+
console.log("");
|
|
56202
|
+
console.log(`Meshes (${config2.meshes.length}):`);
|
|
56203
|
+
const results = [];
|
|
56204
|
+
for (const m of config2.meshes) {
|
|
56205
|
+
process.stdout.write(` ${m.slug.padEnd(20)} probing ${m.brokerUrl}… `);
|
|
56206
|
+
const probe = await probeBroker(m.brokerUrl);
|
|
56207
|
+
results.push({
|
|
56208
|
+
slug: m.slug,
|
|
56209
|
+
brokerUrl: m.brokerUrl,
|
|
56210
|
+
pubkey: m.pubkey,
|
|
56211
|
+
reachable: probe.ok,
|
|
56212
|
+
error: probe.error
|
|
56213
|
+
});
|
|
56214
|
+
if (probe.ok) {
|
|
56215
|
+
console.log(green("reachable"));
|
|
56216
|
+
} else {
|
|
56217
|
+
console.log(red(`unreachable (${probe.error})`));
|
|
56218
|
+
}
|
|
56219
|
+
}
|
|
56220
|
+
console.log("");
|
|
56221
|
+
for (const r of results) {
|
|
56222
|
+
console.log(dim(` ${r.slug}: pubkey ${r.pubkey.slice(0, 16)}…`));
|
|
56223
|
+
}
|
|
56224
|
+
const allOk = results.every((r) => r.reachable);
|
|
56225
|
+
console.log("");
|
|
56226
|
+
if (allOk) {
|
|
56227
|
+
console.log(green("All meshes reachable."));
|
|
56228
|
+
process.exit(0);
|
|
56229
|
+
} else {
|
|
56230
|
+
const broken = results.filter((r) => !r.reachable).length;
|
|
56231
|
+
console.log(red(`${broken} of ${results.length} mesh(es) unreachable.`));
|
|
56232
|
+
process.exit(1);
|
|
56233
|
+
}
|
|
56234
|
+
}
|
|
56235
|
+
|
|
56236
|
+
// src/commands/doctor.ts
|
|
56237
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, statSync as statSync2 } from "node:fs";
|
|
56238
|
+
import { homedir as homedir3, platform as platform2 } from "node:os";
|
|
56239
|
+
import { join as join3 } from "node:path";
|
|
56240
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
56241
|
+
function checkNode() {
|
|
56242
|
+
const major = Number(process.versions.node.split(".")[0]);
|
|
56243
|
+
return {
|
|
56244
|
+
name: "Node.js >= 20",
|
|
56245
|
+
pass: major >= 20,
|
|
56246
|
+
detail: `v${process.versions.node}`,
|
|
56247
|
+
fix: "Install Node 20 or newer (https://nodejs.org)"
|
|
56248
|
+
};
|
|
56249
|
+
}
|
|
56250
|
+
function checkClaudeOnPath() {
|
|
56251
|
+
const res = platform2() === "win32" ? spawnSync2("where", ["claude"]) : spawnSync2("sh", ["-c", "command -v claude"]);
|
|
56252
|
+
const onPath = res.status === 0;
|
|
56253
|
+
const location = onPath ? res.stdout.toString().trim().split(`
|
|
56254
|
+
`)[0] : undefined;
|
|
56255
|
+
return {
|
|
56256
|
+
name: "claude binary on PATH",
|
|
56257
|
+
pass: onPath,
|
|
56258
|
+
detail: location,
|
|
56259
|
+
fix: "Install Claude Code (https://claude.com/claude-code)"
|
|
56260
|
+
};
|
|
56261
|
+
}
|
|
56262
|
+
function checkMcpRegistered() {
|
|
56263
|
+
const claudeConfig = join3(homedir3(), ".claude.json");
|
|
56264
|
+
if (!existsSync4(claudeConfig)) {
|
|
56265
|
+
return {
|
|
56266
|
+
name: "claudemesh MCP registered in ~/.claude.json",
|
|
56267
|
+
pass: false,
|
|
56268
|
+
fix: "Run `claudemesh install`"
|
|
56269
|
+
};
|
|
56270
|
+
}
|
|
56271
|
+
try {
|
|
56272
|
+
const cfg = JSON.parse(readFileSync3(claudeConfig, "utf-8"));
|
|
56273
|
+
const registered = Boolean(cfg.mcpServers?.["claudemesh"]);
|
|
56274
|
+
return {
|
|
56275
|
+
name: "claudemesh MCP registered in ~/.claude.json",
|
|
56276
|
+
pass: registered,
|
|
56277
|
+
fix: registered ? undefined : "Run `claudemesh install`"
|
|
56278
|
+
};
|
|
56279
|
+
} catch (e) {
|
|
56280
|
+
return {
|
|
56281
|
+
name: "claudemesh MCP registered in ~/.claude.json",
|
|
56282
|
+
pass: false,
|
|
56283
|
+
detail: e instanceof Error ? e.message : String(e),
|
|
56284
|
+
fix: "Check ~/.claude.json for JSON parse errors"
|
|
56285
|
+
};
|
|
56286
|
+
}
|
|
56287
|
+
}
|
|
56288
|
+
function checkHooksRegistered() {
|
|
56289
|
+
const settings = join3(homedir3(), ".claude", "settings.json");
|
|
56290
|
+
if (!existsSync4(settings)) {
|
|
56291
|
+
return {
|
|
56292
|
+
name: "Status hooks registered in ~/.claude/settings.json",
|
|
56293
|
+
pass: false,
|
|
56294
|
+
fix: "Run `claudemesh install` (remove --no-hooks)"
|
|
56295
|
+
};
|
|
56296
|
+
}
|
|
56297
|
+
try {
|
|
56298
|
+
const raw = readFileSync3(settings, "utf-8");
|
|
56299
|
+
const has = raw.includes("claudemesh hook ");
|
|
56300
|
+
return {
|
|
56301
|
+
name: "Status hooks registered in ~/.claude/settings.json",
|
|
56302
|
+
pass: has,
|
|
56303
|
+
fix: has ? undefined : "Run `claudemesh install` (remove --no-hooks)"
|
|
56304
|
+
};
|
|
56305
|
+
} catch (e) {
|
|
56306
|
+
return {
|
|
56307
|
+
name: "Status hooks registered in ~/.claude/settings.json",
|
|
56308
|
+
pass: false,
|
|
56309
|
+
detail: e instanceof Error ? e.message : String(e)
|
|
56310
|
+
};
|
|
56311
|
+
}
|
|
56312
|
+
}
|
|
56313
|
+
function checkConfigFile() {
|
|
56314
|
+
const path = getConfigPath();
|
|
56315
|
+
if (!existsSync4(path)) {
|
|
56316
|
+
return {
|
|
56317
|
+
name: "~/.claudemesh/config.json exists and parses",
|
|
56318
|
+
pass: true,
|
|
56319
|
+
detail: "not created yet (fine — no meshes joined)"
|
|
56320
|
+
};
|
|
56321
|
+
}
|
|
56322
|
+
try {
|
|
56323
|
+
loadConfig();
|
|
56324
|
+
const st = statSync2(path);
|
|
56325
|
+
const mode = (st.mode & 511).toString(8);
|
|
56326
|
+
const secure = platform2() === "win32" || mode === "600";
|
|
56327
|
+
return {
|
|
56328
|
+
name: "~/.claudemesh/config.json parses + chmod 0600",
|
|
56329
|
+
pass: secure,
|
|
56330
|
+
detail: platform2() === "win32" ? "chmod skipped on Windows" : `0${mode}`,
|
|
56331
|
+
fix: secure ? undefined : `chmod 600 ${path}`
|
|
56332
|
+
};
|
|
56333
|
+
} catch (e) {
|
|
56334
|
+
return {
|
|
56335
|
+
name: "~/.claudemesh/config.json exists and parses",
|
|
56336
|
+
pass: false,
|
|
56337
|
+
detail: e instanceof Error ? e.message : String(e),
|
|
56338
|
+
fix: "Inspect or delete ~/.claudemesh/config.json and re-join"
|
|
56339
|
+
};
|
|
56340
|
+
}
|
|
56341
|
+
}
|
|
56342
|
+
function checkKeypairs() {
|
|
56343
|
+
try {
|
|
56344
|
+
const cfg = loadConfig();
|
|
56345
|
+
if (cfg.meshes.length === 0) {
|
|
56346
|
+
return {
|
|
56347
|
+
name: "Mesh keypairs valid",
|
|
56348
|
+
pass: true,
|
|
56349
|
+
detail: "no meshes joined"
|
|
56350
|
+
};
|
|
56351
|
+
}
|
|
56352
|
+
for (const m of cfg.meshes) {
|
|
56353
|
+
if (m.pubkey.length !== 64 || !/^[0-9a-f]+$/.test(m.pubkey)) {
|
|
56354
|
+
return {
|
|
56355
|
+
name: "Mesh keypairs valid",
|
|
56356
|
+
pass: false,
|
|
56357
|
+
detail: `${m.slug}: pubkey malformed`,
|
|
56358
|
+
fix: `Leave + re-join the mesh: claudemesh leave ${m.slug}`
|
|
56359
|
+
};
|
|
56360
|
+
}
|
|
56361
|
+
if (m.secretKey.length !== 128 || !/^[0-9a-f]+$/.test(m.secretKey)) {
|
|
56362
|
+
return {
|
|
56363
|
+
name: "Mesh keypairs valid",
|
|
56364
|
+
pass: false,
|
|
56365
|
+
detail: `${m.slug}: secret key malformed`,
|
|
56366
|
+
fix: `Leave + re-join the mesh: claudemesh leave ${m.slug}`
|
|
56367
|
+
};
|
|
56368
|
+
}
|
|
56369
|
+
}
|
|
56370
|
+
return {
|
|
56371
|
+
name: "Mesh keypairs valid",
|
|
56372
|
+
pass: true,
|
|
56373
|
+
detail: `${cfg.meshes.length} mesh(es)`
|
|
56374
|
+
};
|
|
56375
|
+
} catch (e) {
|
|
56376
|
+
return {
|
|
56377
|
+
name: "Mesh keypairs valid",
|
|
56378
|
+
pass: false,
|
|
56379
|
+
detail: e instanceof Error ? e.message : String(e)
|
|
56380
|
+
};
|
|
56381
|
+
}
|
|
56382
|
+
}
|
|
56383
|
+
async function runDoctor() {
|
|
56384
|
+
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
56385
|
+
const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
56386
|
+
const green = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
|
|
56387
|
+
const red = (s) => useColor ? `\x1B[31m${s}\x1B[39m` : s;
|
|
56388
|
+
console.log(`claudemesh doctor (v${VERSION})`);
|
|
56389
|
+
console.log("─".repeat(60));
|
|
56390
|
+
const checks3 = [
|
|
56391
|
+
checkNode(),
|
|
56392
|
+
checkClaudeOnPath(),
|
|
56393
|
+
checkMcpRegistered(),
|
|
56394
|
+
checkHooksRegistered(),
|
|
56395
|
+
checkConfigFile(),
|
|
56396
|
+
checkKeypairs()
|
|
56397
|
+
];
|
|
56398
|
+
for (const c of checks3) {
|
|
56399
|
+
const mark = c.pass ? green("✓") : red("✗");
|
|
56400
|
+
const detail = c.detail ? dim(` (${c.detail})`) : "";
|
|
56401
|
+
console.log(`${mark} ${c.name}${detail}`);
|
|
56402
|
+
if (!c.pass && c.fix) {
|
|
56403
|
+
console.log(dim(` → ${c.fix}`));
|
|
56404
|
+
}
|
|
56405
|
+
}
|
|
56406
|
+
const failing = checks3.filter((c) => !c.pass);
|
|
56407
|
+
console.log("");
|
|
56408
|
+
if (failing.length === 0) {
|
|
56409
|
+
console.log(green("All checks passed."));
|
|
56410
|
+
process.exit(0);
|
|
56411
|
+
} else {
|
|
56412
|
+
console.log(red(`${failing.length} check(s) failed.`));
|
|
56413
|
+
process.exit(1);
|
|
56414
|
+
}
|
|
56415
|
+
}
|
|
56416
|
+
|
|
56417
|
+
// src/commands/welcome.ts
|
|
56418
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
|
|
56419
|
+
import { homedir as homedir4 } from "node:os";
|
|
56420
|
+
import { join as join4 } from "node:path";
|
|
56421
|
+
function detectState() {
|
|
56422
|
+
const claudeConfig = join4(homedir4(), ".claude.json");
|
|
56423
|
+
let mcpRegistered = false;
|
|
56424
|
+
if (existsSync5(claudeConfig)) {
|
|
56425
|
+
try {
|
|
56426
|
+
const cfg = JSON.parse(readFileSync4(claudeConfig, "utf-8"));
|
|
56427
|
+
mcpRegistered = Boolean(cfg.mcpServers?.["claudemesh"]);
|
|
56428
|
+
} catch {}
|
|
56429
|
+
}
|
|
56430
|
+
if (!mcpRegistered)
|
|
56431
|
+
return "no-install";
|
|
56432
|
+
try {
|
|
56433
|
+
const cfg = loadConfig();
|
|
56434
|
+
return cfg.meshes.length === 0 ? "no-meshes" : "ready";
|
|
56435
|
+
} catch {
|
|
56436
|
+
return "broken-config";
|
|
56437
|
+
}
|
|
56438
|
+
}
|
|
56439
|
+
function runWelcome() {
|
|
56440
|
+
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
56441
|
+
const bold = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
56442
|
+
const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
56443
|
+
const green = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
|
|
56444
|
+
const yellow = (s) => useColor ? `\x1B[33m${s}\x1B[39m` : s;
|
|
56445
|
+
console.log(bold(`claudemesh v${VERSION}`) + dim(" — peer mesh for Claude Code"));
|
|
56446
|
+
console.log("─".repeat(60));
|
|
56447
|
+
const state = detectState();
|
|
56448
|
+
switch (state) {
|
|
56449
|
+
case "no-install":
|
|
56450
|
+
console.log("Welcome. Let's get you set up.");
|
|
56451
|
+
console.log("");
|
|
56452
|
+
console.log(bold("Step 1:") + " register the MCP server + status hooks");
|
|
56453
|
+
console.log(` ${green("$")} claudemesh install`);
|
|
56454
|
+
console.log("");
|
|
56455
|
+
console.log(dim("Step 2 (after restart): claudemesh join <invite-url>"));
|
|
56456
|
+
console.log(dim("Step 3: claudemesh launch"));
|
|
56457
|
+
break;
|
|
56458
|
+
case "no-meshes":
|
|
56459
|
+
console.log(green("✓") + " MCP registered. Now join a mesh.");
|
|
56460
|
+
console.log("");
|
|
56461
|
+
console.log(bold("Step 2:") + " join a mesh");
|
|
56462
|
+
console.log(` ${green("$")} claudemesh join https://claudemesh.com/join/<token>`);
|
|
56463
|
+
console.log("");
|
|
56464
|
+
console.log(dim(" Don't have an invite? Create one at ") + bold("https://claudemesh.com") + dim(" or ask a mesh owner."));
|
|
56465
|
+
console.log("");
|
|
56466
|
+
console.log(dim("Step 3 (after joining): claudemesh launch"));
|
|
56467
|
+
break;
|
|
56468
|
+
case "ready": {
|
|
56469
|
+
const cfg = loadConfig();
|
|
56470
|
+
const meshNames = cfg.meshes.map((m) => m.slug).join(", ");
|
|
56471
|
+
console.log(green("✓") + " MCP registered.");
|
|
56472
|
+
console.log(green("✓") + ` ${cfg.meshes.length} mesh(es) joined: ${meshNames}`);
|
|
56473
|
+
console.log("");
|
|
56474
|
+
console.log(bold("You're ready.") + " Launch Claude Code with real-time peer messages:");
|
|
56475
|
+
console.log(` ${green("$")} claudemesh launch`);
|
|
56476
|
+
console.log("");
|
|
56477
|
+
console.log(dim(" (Plain `claude` works too — messages pull-only via check_messages.)"));
|
|
56478
|
+
console.log("");
|
|
56479
|
+
console.log(dim("Health check: claudemesh status"));
|
|
56480
|
+
console.log(dim("Diagnostics: claudemesh doctor"));
|
|
56481
|
+
console.log(dim("All commands: claudemesh --help"));
|
|
56482
|
+
break;
|
|
56483
|
+
}
|
|
56484
|
+
case "broken-config":
|
|
56485
|
+
console.log(yellow("⚠") + " Your ~/.claudemesh/config.json is unreadable.");
|
|
56486
|
+
console.log("");
|
|
56487
|
+
console.log("Run diagnostics to see what's wrong:");
|
|
56488
|
+
console.log(` ${green("$")} claudemesh doctor`);
|
|
56489
|
+
break;
|
|
56490
|
+
}
|
|
56491
|
+
console.log("");
|
|
56492
|
+
}
|
|
56493
|
+
|
|
56084
56494
|
// src/index.ts
|
|
56085
|
-
var HELP = `claudemesh — peer mesh for Claude Code sessions
|
|
56495
|
+
var HELP = `claudemesh v${VERSION} — peer mesh for Claude Code sessions
|
|
56086
56496
|
|
|
56087
56497
|
Usage:
|
|
56088
56498
|
claudemesh <command> [args]
|
|
@@ -56097,9 +56507,12 @@ Commands:
|
|
|
56097
56507
|
join <url> Join a mesh via https://claudemesh.com/join/... URL
|
|
56098
56508
|
list Show all joined meshes
|
|
56099
56509
|
leave <slug> Leave a joined mesh
|
|
56510
|
+
status Health report: broker reachability per joined mesh
|
|
56511
|
+
doctor Diagnostic checks (install, config, keypairs, PATH)
|
|
56100
56512
|
seed-test-mesh Dev-only: inject a mesh into config (skips invite flow)
|
|
56101
56513
|
mcp Start MCP server (stdio) — invoked by Claude Code
|
|
56102
56514
|
--help, -h Show this help
|
|
56515
|
+
--version, -v Show the CLI version
|
|
56103
56516
|
|
|
56104
56517
|
Environment:
|
|
56105
56518
|
CLAUDEMESH_BROKER_URL Override broker URL (default: wss://ic.claudemesh.com/ws)
|
|
@@ -56134,15 +56547,28 @@ async function main() {
|
|
|
56134
56547
|
case "leave":
|
|
56135
56548
|
runLeave(args);
|
|
56136
56549
|
return;
|
|
56550
|
+
case "status":
|
|
56551
|
+
await runStatus();
|
|
56552
|
+
return;
|
|
56553
|
+
case "doctor":
|
|
56554
|
+
await runDoctor();
|
|
56555
|
+
return;
|
|
56137
56556
|
case "seed-test-mesh":
|
|
56138
56557
|
runSeedTestMesh(args);
|
|
56139
56558
|
return;
|
|
56559
|
+
case "--version":
|
|
56560
|
+
case "-v":
|
|
56561
|
+
case "version":
|
|
56562
|
+
console.log(VERSION);
|
|
56563
|
+
return;
|
|
56140
56564
|
case "--help":
|
|
56141
56565
|
case "-h":
|
|
56142
56566
|
case "help":
|
|
56143
|
-
case undefined:
|
|
56144
56567
|
console.log(HELP);
|
|
56145
56568
|
return;
|
|
56569
|
+
case undefined:
|
|
56570
|
+
runWelcome();
|
|
56571
|
+
return;
|
|
56146
56572
|
default:
|
|
56147
56573
|
console.error(`Unknown command: ${cmd}`);
|
|
56148
56574
|
console.error("Run `claudemesh --help` for usage.");
|