claudemesh-cli 1.0.0-alpha.13 → 1.0.0-alpha.15
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/entrypoints/cli.js +161 -64
- package/dist/entrypoints/cli.js.map +5 -5
- package/package.json +3 -3
package/dist/entrypoints/cli.js
CHANGED
|
@@ -4331,30 +4331,84 @@ var exports_list = {};
|
|
|
4331
4331
|
__export(exports_list, {
|
|
4332
4332
|
runList: () => runList
|
|
4333
4333
|
});
|
|
4334
|
-
function runList() {
|
|
4334
|
+
async function runList() {
|
|
4335
4335
|
const config = readConfig();
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4336
|
+
const auth = getStoredToken();
|
|
4337
|
+
let serverMeshes = [];
|
|
4338
|
+
if (auth) {
|
|
4339
|
+
try {
|
|
4340
|
+
let userId = "";
|
|
4341
|
+
try {
|
|
4342
|
+
const payload = JSON.parse(Buffer.from(auth.session_token.split(".")[1], "base64url").toString());
|
|
4343
|
+
userId = payload.sub ?? "";
|
|
4344
|
+
} catch {}
|
|
4345
|
+
if (userId) {
|
|
4346
|
+
const res = await request({
|
|
4347
|
+
path: `/cli/meshes?user_id=${userId}`,
|
|
4348
|
+
baseUrl: BROKER_HTTP2
|
|
4349
|
+
});
|
|
4350
|
+
serverMeshes = res.meshes ?? [];
|
|
4351
|
+
}
|
|
4352
|
+
} catch {}
|
|
4353
|
+
}
|
|
4354
|
+
const localSlugs = new Set(config.meshes.map((m) => m.slug));
|
|
4355
|
+
const serverSlugs = new Set(serverMeshes.map((m) => m.slug));
|
|
4356
|
+
const allSlugs = new Set([...localSlugs, ...serverSlugs]);
|
|
4357
|
+
if (allSlugs.size === 0) {
|
|
4358
|
+
console.log(`
|
|
4359
|
+
No meshes yet.
|
|
4360
|
+
`);
|
|
4361
|
+
console.log(" Create one: claudemesh mesh create <name>");
|
|
4362
|
+
console.log(` Join one: claudemesh mesh add <invite-url>
|
|
4363
|
+
`);
|
|
4341
4364
|
return;
|
|
4342
4365
|
}
|
|
4343
|
-
console.log(`
|
|
4366
|
+
console.log(`
|
|
4367
|
+
Your meshes:
|
|
4368
|
+
`);
|
|
4369
|
+
for (const slug of allSlugs) {
|
|
4370
|
+
const local = config.meshes.find((m) => m.slug === slug);
|
|
4371
|
+
const server = serverMeshes.find((m) => m.slug === slug);
|
|
4372
|
+
const name = server?.name ?? local?.name ?? slug;
|
|
4373
|
+
const role = server?.role ?? "member";
|
|
4374
|
+
const isOwner = server?.is_owner ?? false;
|
|
4375
|
+
const roleLabel = isOwner ? "owner" : role;
|
|
4376
|
+
const memberCount = server?.member_count;
|
|
4377
|
+
const activePeers = server?.active_peers ?? 0;
|
|
4378
|
+
const inLocal = localSlugs.has(slug);
|
|
4379
|
+
const inServer = serverSlugs.has(slug);
|
|
4380
|
+
let status;
|
|
4381
|
+
let icon;
|
|
4382
|
+
if (inLocal && inServer) {
|
|
4383
|
+
icon = green("●");
|
|
4384
|
+
status = activePeers > 0 ? green(`${activePeers} online`) : dim("synced");
|
|
4385
|
+
} else if (inLocal && !inServer) {
|
|
4386
|
+
icon = yellow("●");
|
|
4387
|
+
status = yellow("local only");
|
|
4388
|
+
} else {
|
|
4389
|
+
icon = dim("○");
|
|
4390
|
+
status = dim("not added locally");
|
|
4391
|
+
}
|
|
4392
|
+
const memberInfo = memberCount ? dim(`${memberCount} member${memberCount !== 1 ? "s" : ""}`) : "";
|
|
4393
|
+
const parts = [roleLabel, memberInfo, status].filter(Boolean);
|
|
4394
|
+
console.log(` ${icon} ${bold(name)} ${dim(slug)}`);
|
|
4395
|
+
console.log(` ${parts.join(" · ")}`);
|
|
4396
|
+
}
|
|
4344
4397
|
console.log("");
|
|
4345
|
-
|
|
4346
|
-
console.log(`
|
|
4347
|
-
console.log(` mesh id: ${m.meshId}`);
|
|
4348
|
-
console.log(` member id: ${m.memberId}`);
|
|
4349
|
-
console.log(` pubkey: ${m.pubkey.slice(0, 16)}…`);
|
|
4350
|
-
console.log(` broker: ${m.brokerUrl}`);
|
|
4351
|
-
console.log(` joined: ${m.joinedAt}`);
|
|
4352
|
-
console.log("");
|
|
4398
|
+
if (serverMeshes.some((m) => !localSlugs.has(m.slug))) {
|
|
4399
|
+
console.log(dim(" ○ = server only — run `claudemesh mesh add` to use locally"));
|
|
4353
4400
|
}
|
|
4354
|
-
console.log(`Config: ${getConfigPath()}`);
|
|
4401
|
+
console.log(dim(` Config: ${getConfigPath()}`));
|
|
4402
|
+
console.log("");
|
|
4355
4403
|
}
|
|
4404
|
+
var BROKER_HTTP2;
|
|
4356
4405
|
var init_list2 = __esm(() => {
|
|
4357
4406
|
init_facade();
|
|
4407
|
+
init_facade6();
|
|
4408
|
+
init_facade3();
|
|
4409
|
+
init_urls();
|
|
4410
|
+
init_styles();
|
|
4411
|
+
BROKER_HTTP2 = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
|
|
4358
4412
|
});
|
|
4359
4413
|
|
|
4360
4414
|
// src/commands/delete-mesh.ts
|
|
@@ -4368,19 +4422,38 @@ function prompt(question) {
|
|
|
4368
4422
|
return new Promise((resolve) => {
|
|
4369
4423
|
rl.question(question, (a) => {
|
|
4370
4424
|
rl.close();
|
|
4371
|
-
resolve(a.trim()
|
|
4425
|
+
resolve(a.trim());
|
|
4372
4426
|
});
|
|
4373
4427
|
});
|
|
4374
4428
|
}
|
|
4429
|
+
function getUserId(token) {
|
|
4430
|
+
try {
|
|
4431
|
+
const payload = JSON.parse(Buffer.from(token.split(".")[1], "base64url").toString());
|
|
4432
|
+
return payload.sub ?? "";
|
|
4433
|
+
} catch {
|
|
4434
|
+
return "";
|
|
4435
|
+
}
|
|
4436
|
+
}
|
|
4437
|
+
async function isOwner(slug, userId) {
|
|
4438
|
+
try {
|
|
4439
|
+
const res = await request({
|
|
4440
|
+
path: `/cli/meshes?user_id=${userId}`,
|
|
4441
|
+
baseUrl: BROKER_HTTP3
|
|
4442
|
+
});
|
|
4443
|
+
return res.meshes?.find((m) => m.slug === slug)?.is_owner ?? false;
|
|
4444
|
+
} catch {
|
|
4445
|
+
return false;
|
|
4446
|
+
}
|
|
4447
|
+
}
|
|
4375
4448
|
async function deleteMesh(slug, opts = {}) {
|
|
4449
|
+
const config = readConfig();
|
|
4376
4450
|
if (!slug) {
|
|
4377
|
-
const config = readConfig();
|
|
4378
4451
|
if (config.meshes.length === 0) {
|
|
4379
|
-
console.error(" No meshes to
|
|
4452
|
+
console.error(" No meshes to remove.");
|
|
4380
4453
|
return EXIT.NOT_FOUND;
|
|
4381
4454
|
}
|
|
4382
4455
|
console.log(`
|
|
4383
|
-
Select mesh to
|
|
4456
|
+
Select mesh to remove:
|
|
4384
4457
|
`);
|
|
4385
4458
|
config.meshes.forEach((m, i) => {
|
|
4386
4459
|
console.log(` ${bold(String(i + 1) + ")")} ${m.slug} ${dim("(" + m.name + ")")}`);
|
|
@@ -4394,48 +4467,72 @@ async function deleteMesh(slug, opts = {}) {
|
|
|
4394
4467
|
}
|
|
4395
4468
|
slug = config.meshes[idx].slug;
|
|
4396
4469
|
}
|
|
4470
|
+
const auth = getStoredToken();
|
|
4471
|
+
const userId = auth ? getUserId(auth.session_token) : "";
|
|
4472
|
+
const ownerCheck = userId ? await isOwner(slug, userId) : false;
|
|
4397
4473
|
if (!opts.yes) {
|
|
4398
4474
|
console.log(`
|
|
4399
|
-
${
|
|
4400
|
-
|
|
4401
|
-
if (
|
|
4402
|
-
console.log("
|
|
4403
|
-
|
|
4404
|
-
}
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4475
|
+
${bold(slug)}
|
|
4476
|
+
`);
|
|
4477
|
+
if (ownerCheck) {
|
|
4478
|
+
console.log(` ${bold("1)")} Remove from this device only ${dim("(keep on server)")}`);
|
|
4479
|
+
console.log(` ${bold("2)")} ${red("Delete everywhere")} ${dim("(removes for all members)")}`);
|
|
4480
|
+
console.log(` ${bold("3)")} Cancel`);
|
|
4481
|
+
console.log("");
|
|
4482
|
+
const choice = await prompt(" Choice [1]: ") || "1";
|
|
4483
|
+
if (choice === "3") {
|
|
4484
|
+
console.log(" Cancelled.");
|
|
4485
|
+
return EXIT.USER_CANCELLED;
|
|
4486
|
+
}
|
|
4487
|
+
if (choice === "2") {
|
|
4488
|
+
console.log(`
|
|
4489
|
+
${red("Warning:")} This will delete ${bold(slug)} for all members.`);
|
|
4490
|
+
const confirm = await prompt(` Type "${slug}" to confirm: `);
|
|
4491
|
+
if (confirm.toLowerCase() !== slug.toLowerCase()) {
|
|
4492
|
+
console.log(" Cancelled.");
|
|
4493
|
+
return EXIT.USER_CANCELLED;
|
|
4494
|
+
}
|
|
4495
|
+
try {
|
|
4496
|
+
await request({
|
|
4497
|
+
path: `/cli/mesh/${slug}`,
|
|
4498
|
+
method: "DELETE",
|
|
4499
|
+
body: { user_id: userId },
|
|
4500
|
+
baseUrl: BROKER_HTTP3
|
|
4501
|
+
});
|
|
4502
|
+
console.log(` ${green(icons.check)} Deleted "${slug}" from server.`);
|
|
4503
|
+
} catch (err) {
|
|
4504
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
4505
|
+
console.error(` ${icons.cross} Server delete failed: ${msg}`);
|
|
4506
|
+
}
|
|
4507
|
+
leaveMesh(slug);
|
|
4508
|
+
console.log(` ${green(icons.check)} Removed from local config.`);
|
|
4509
|
+
return EXIT.SUCCESS;
|
|
4510
|
+
}
|
|
4511
|
+
} else {
|
|
4512
|
+
console.log(` ${bold("1)")} Remove from this device ${dim("(you can re-add later)")}`);
|
|
4513
|
+
console.log(` ${bold("2)")} Cancel`);
|
|
4514
|
+
if (!ownerCheck && userId) {
|
|
4515
|
+
console.log(dim(`
|
|
4516
|
+
${yellow(icons.warn)} Only the mesh owner can delete it from the server.`));
|
|
4517
|
+
}
|
|
4518
|
+
console.log("");
|
|
4519
|
+
const choice = await prompt(" Choice [1]: ") || "1";
|
|
4520
|
+
if (choice === "2") {
|
|
4521
|
+
console.log(" Cancelled.");
|
|
4522
|
+
return EXIT.USER_CANCELLED;
|
|
4431
4523
|
}
|
|
4432
4524
|
}
|
|
4433
4525
|
}
|
|
4434
|
-
leaveMesh(slug);
|
|
4435
|
-
|
|
4526
|
+
const removed = leaveMesh(slug);
|
|
4527
|
+
if (removed) {
|
|
4528
|
+
console.log(` ${green(icons.check)} Removed "${slug}" from this device.`);
|
|
4529
|
+
console.log(dim(` Re-add anytime with: claudemesh mesh add <invite-url>`));
|
|
4530
|
+
} else {
|
|
4531
|
+
console.error(` Mesh "${slug}" not found in local config.`);
|
|
4532
|
+
}
|
|
4436
4533
|
return EXIT.SUCCESS;
|
|
4437
4534
|
}
|
|
4438
|
-
var
|
|
4535
|
+
var BROKER_HTTP3;
|
|
4439
4536
|
var init_delete_mesh = __esm(() => {
|
|
4440
4537
|
init_facade();
|
|
4441
4538
|
init_facade9();
|
|
@@ -4444,7 +4541,7 @@ var init_delete_mesh = __esm(() => {
|
|
|
4444
4541
|
init_urls();
|
|
4445
4542
|
init_styles();
|
|
4446
4543
|
init_exit_codes();
|
|
4447
|
-
|
|
4544
|
+
BROKER_HTTP3 = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
|
|
4448
4545
|
});
|
|
4449
4546
|
|
|
4450
4547
|
// src/commands/rename.ts
|
|
@@ -8540,7 +8637,7 @@ async function runStatus() {
|
|
|
8540
8637
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
8541
8638
|
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
8542
8639
|
const green3 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
|
|
8543
|
-
const
|
|
8640
|
+
const red3 = (s) => useColor ? `\x1B[31m${s}\x1B[39m` : s;
|
|
8544
8641
|
console.log(`claudemesh status (v${VERSION})`);
|
|
8545
8642
|
console.log("─".repeat(60));
|
|
8546
8643
|
const configPath = getConfigPath();
|
|
@@ -8573,7 +8670,7 @@ async function runStatus() {
|
|
|
8573
8670
|
if (probe.ok) {
|
|
8574
8671
|
console.log(green3("reachable"));
|
|
8575
8672
|
} else {
|
|
8576
|
-
console.log(
|
|
8673
|
+
console.log(red3(`unreachable (${probe.error})`));
|
|
8577
8674
|
}
|
|
8578
8675
|
}
|
|
8579
8676
|
console.log("");
|
|
@@ -8587,7 +8684,7 @@ async function runStatus() {
|
|
|
8587
8684
|
process.exit(0);
|
|
8588
8685
|
} else {
|
|
8589
8686
|
const broken = results.filter((r) => !r.reachable).length;
|
|
8590
|
-
console.log(
|
|
8687
|
+
console.log(red3(`${broken} of ${results.length} mesh(es) unreachable.`));
|
|
8591
8688
|
process.exit(1);
|
|
8592
8689
|
}
|
|
8593
8690
|
}
|
|
@@ -8751,7 +8848,7 @@ async function runDoctor() {
|
|
|
8751
8848
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
8752
8849
|
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
8753
8850
|
const green3 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
|
|
8754
|
-
const
|
|
8851
|
+
const red3 = (s) => useColor ? `\x1B[31m${s}\x1B[39m` : s;
|
|
8755
8852
|
console.log(`claudemesh doctor (v${VERSION})`);
|
|
8756
8853
|
console.log("─".repeat(60));
|
|
8757
8854
|
const checks = [
|
|
@@ -8763,7 +8860,7 @@ async function runDoctor() {
|
|
|
8763
8860
|
checkKeypairs()
|
|
8764
8861
|
];
|
|
8765
8862
|
for (const c of checks) {
|
|
8766
|
-
const mark = c.pass ? green3("✓") :
|
|
8863
|
+
const mark = c.pass ? green3("✓") : red3("✗");
|
|
8767
8864
|
const detail = c.detail ? dim2(` (${c.detail})`) : "";
|
|
8768
8865
|
console.log(`${mark} ${c.name}${detail}`);
|
|
8769
8866
|
if (!c.pass && c.fix) {
|
|
@@ -8776,7 +8873,7 @@ async function runDoctor() {
|
|
|
8776
8873
|
console.log(green3("All checks passed."));
|
|
8777
8874
|
process.exit(0);
|
|
8778
8875
|
} else {
|
|
8779
|
-
console.log(
|
|
8876
|
+
console.log(red3(`${failing.length} check(s) failed.`));
|
|
8780
8877
|
process.exit(1);
|
|
8781
8878
|
}
|
|
8782
8879
|
}
|
|
@@ -9616,7 +9713,7 @@ async function handleMeshSubcommand() {
|
|
|
9616
9713
|
case "list":
|
|
9617
9714
|
case "ls": {
|
|
9618
9715
|
const { runList: runList2 } = await Promise.resolve().then(() => (init_list2(), exports_list));
|
|
9619
|
-
runList2();
|
|
9716
|
+
await runList2();
|
|
9620
9717
|
break;
|
|
9621
9718
|
}
|
|
9622
9719
|
case "delete":
|
|
@@ -9822,4 +9919,4 @@ main().catch((err) => {
|
|
|
9822
9919
|
process.exit(EXIT.INTERNAL_ERROR);
|
|
9823
9920
|
});
|
|
9824
9921
|
|
|
9825
|
-
//# debugId=
|
|
9922
|
+
//# debugId=CB53B1FA4B95E06264756E2164756E21
|