claudemesh-cli 1.1.0 → 1.2.0
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 +533 -145
- package/dist/entrypoints/cli.js.map +11 -8
- package/dist/entrypoints/mcp.js +240 -37
- package/dist/entrypoints/mcp.js.map +6 -4
- package/package.json +1 -1
package/dist/entrypoints/cli.js
CHANGED
|
@@ -88,7 +88,7 @@ __export(exports_urls, {
|
|
|
88
88
|
VERSION: () => VERSION,
|
|
89
89
|
URLS: () => URLS
|
|
90
90
|
});
|
|
91
|
-
var URLS, VERSION = "1.
|
|
91
|
+
var URLS, VERSION = "1.2.0", env;
|
|
92
92
|
var init_urls = __esm(() => {
|
|
93
93
|
URLS = {
|
|
94
94
|
BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
|
|
@@ -6392,11 +6392,136 @@ var init_ban = __esm(() => {
|
|
|
6392
6392
|
init_exit_codes();
|
|
6393
6393
|
});
|
|
6394
6394
|
|
|
6395
|
+
// src/services/bridge/protocol.ts
|
|
6396
|
+
import { homedir as homedir4 } from "node:os";
|
|
6397
|
+
import { join as join4 } from "node:path";
|
|
6398
|
+
function socketPath(meshSlug) {
|
|
6399
|
+
return join4(homedir4(), ".claudemesh", "sockets", `${meshSlug}.sock`);
|
|
6400
|
+
}
|
|
6401
|
+
function socketDir() {
|
|
6402
|
+
return join4(homedir4(), ".claudemesh", "sockets");
|
|
6403
|
+
}
|
|
6404
|
+
function frame(obj) {
|
|
6405
|
+
return JSON.stringify(obj) + `
|
|
6406
|
+
`;
|
|
6407
|
+
}
|
|
6408
|
+
|
|
6409
|
+
class LineParser {
|
|
6410
|
+
buf = "";
|
|
6411
|
+
feed(chunk) {
|
|
6412
|
+
this.buf += typeof chunk === "string" ? chunk : chunk.toString("utf-8");
|
|
6413
|
+
const lines = [];
|
|
6414
|
+
let nl = this.buf.indexOf(`
|
|
6415
|
+
`);
|
|
6416
|
+
while (nl !== -1) {
|
|
6417
|
+
lines.push(this.buf.slice(0, nl));
|
|
6418
|
+
this.buf = this.buf.slice(nl + 1);
|
|
6419
|
+
nl = this.buf.indexOf(`
|
|
6420
|
+
`);
|
|
6421
|
+
}
|
|
6422
|
+
return lines;
|
|
6423
|
+
}
|
|
6424
|
+
}
|
|
6425
|
+
var init_protocol = () => {};
|
|
6426
|
+
|
|
6427
|
+
// src/services/bridge/client.ts
|
|
6428
|
+
import { createConnection } from "node:net";
|
|
6429
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
6430
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
6431
|
+
async function tryBridge(meshSlug, verb, args = {}, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
6432
|
+
const path = socketPath(meshSlug);
|
|
6433
|
+
if (!existsSync5(path))
|
|
6434
|
+
return null;
|
|
6435
|
+
return new Promise((resolve) => {
|
|
6436
|
+
const id = randomUUID2();
|
|
6437
|
+
const req = { id, verb, args };
|
|
6438
|
+
const parser = new LineParser;
|
|
6439
|
+
let settled = false;
|
|
6440
|
+
const finish = (value) => {
|
|
6441
|
+
if (settled)
|
|
6442
|
+
return;
|
|
6443
|
+
settled = true;
|
|
6444
|
+
try {
|
|
6445
|
+
socket.destroy();
|
|
6446
|
+
} catch {}
|
|
6447
|
+
clearTimeout(timer);
|
|
6448
|
+
resolve(value);
|
|
6449
|
+
};
|
|
6450
|
+
const socket = createConnection({ path });
|
|
6451
|
+
const timer = setTimeout(() => {
|
|
6452
|
+
finish(null);
|
|
6453
|
+
}, timeoutMs);
|
|
6454
|
+
socket.on("connect", () => {
|
|
6455
|
+
try {
|
|
6456
|
+
socket.write(frame(req));
|
|
6457
|
+
} catch {
|
|
6458
|
+
finish(null);
|
|
6459
|
+
}
|
|
6460
|
+
});
|
|
6461
|
+
socket.on("data", (chunk) => {
|
|
6462
|
+
const lines = parser.feed(chunk);
|
|
6463
|
+
for (const line of lines) {
|
|
6464
|
+
if (!line.trim())
|
|
6465
|
+
continue;
|
|
6466
|
+
let res;
|
|
6467
|
+
try {
|
|
6468
|
+
res = JSON.parse(line);
|
|
6469
|
+
} catch {
|
|
6470
|
+
continue;
|
|
6471
|
+
}
|
|
6472
|
+
if (res.id !== id)
|
|
6473
|
+
continue;
|
|
6474
|
+
if (res.ok)
|
|
6475
|
+
finish({ ok: true, result: res.result });
|
|
6476
|
+
else
|
|
6477
|
+
finish({ ok: false, error: res.error });
|
|
6478
|
+
return;
|
|
6479
|
+
}
|
|
6480
|
+
});
|
|
6481
|
+
socket.on("error", (err) => {
|
|
6482
|
+
const code = err.code;
|
|
6483
|
+
if (code === "ECONNREFUSED" || code === "ENOENT" || code === "EPERM") {
|
|
6484
|
+
finish(null);
|
|
6485
|
+
} else {
|
|
6486
|
+
finish(null);
|
|
6487
|
+
}
|
|
6488
|
+
});
|
|
6489
|
+
socket.on("close", () => {
|
|
6490
|
+
finish(null);
|
|
6491
|
+
});
|
|
6492
|
+
});
|
|
6493
|
+
}
|
|
6494
|
+
var DEFAULT_TIMEOUT_MS = 5000;
|
|
6495
|
+
var init_client3 = __esm(() => {
|
|
6496
|
+
init_protocol();
|
|
6497
|
+
});
|
|
6498
|
+
|
|
6395
6499
|
// src/commands/peers.ts
|
|
6396
6500
|
var exports_peers = {};
|
|
6397
6501
|
__export(exports_peers, {
|
|
6398
6502
|
runPeers: () => runPeers
|
|
6399
6503
|
});
|
|
6504
|
+
function projectFields(record, fields) {
|
|
6505
|
+
const out = {};
|
|
6506
|
+
for (const f of fields) {
|
|
6507
|
+
const sourceKey = FIELD_ALIAS[f] ?? f;
|
|
6508
|
+
out[f] = record[sourceKey];
|
|
6509
|
+
}
|
|
6510
|
+
return out;
|
|
6511
|
+
}
|
|
6512
|
+
async function listPeersForMesh(slug) {
|
|
6513
|
+
const bridged = await tryBridge(slug, "peers");
|
|
6514
|
+
if (bridged && bridged.ok) {
|
|
6515
|
+
return bridged.result;
|
|
6516
|
+
}
|
|
6517
|
+
let result = [];
|
|
6518
|
+
await withMesh({ meshSlug: slug }, async (client) => {
|
|
6519
|
+
const all = await client.listPeers();
|
|
6520
|
+
const selfPubkey = client.getSessionPubkey();
|
|
6521
|
+
result = selfPubkey ? all.filter((p) => p.pubkey !== selfPubkey) : all;
|
|
6522
|
+
});
|
|
6523
|
+
return result;
|
|
6524
|
+
}
|
|
6400
6525
|
async function runPeers(flags) {
|
|
6401
6526
|
const config = readConfig();
|
|
6402
6527
|
const slugs = flags.mesh ? [flags.mesh] : config.meshes.map((m) => m.slug);
|
|
@@ -6405,55 +6530,59 @@ async function runPeers(flags) {
|
|
|
6405
6530
|
render.hint("claudemesh <invite-url> # join + launch");
|
|
6406
6531
|
process.exit(1);
|
|
6407
6532
|
}
|
|
6533
|
+
const fieldList = typeof flags.json === "string" && flags.json.length > 0 ? flags.json.split(",").map((s) => s.trim()).filter(Boolean) : null;
|
|
6534
|
+
const wantsJson = flags.json !== undefined && flags.json !== false;
|
|
6408
6535
|
const allJson = [];
|
|
6409
6536
|
for (const slug of slugs) {
|
|
6410
6537
|
try {
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
const
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
6418
|
-
|
|
6419
|
-
render.
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
}
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
render.info(
|
|
6439
|
-
|
|
6440
|
-
render.info(dim(` cwd: ${p.cwd}`));
|
|
6441
|
-
}
|
|
6442
|
-
});
|
|
6538
|
+
const peers = await listPeersForMesh(slug);
|
|
6539
|
+
if (wantsJson) {
|
|
6540
|
+
const projected = fieldList ? peers.map((p) => projectFields(p, fieldList)) : peers;
|
|
6541
|
+
allJson.push({ mesh: slug, peers: projected });
|
|
6542
|
+
continue;
|
|
6543
|
+
}
|
|
6544
|
+
render.section(`peers on ${slug} (${peers.length})`);
|
|
6545
|
+
if (peers.length === 0) {
|
|
6546
|
+
render.info(dim(" (no peers connected)"));
|
|
6547
|
+
continue;
|
|
6548
|
+
}
|
|
6549
|
+
for (const p of peers) {
|
|
6550
|
+
const groups = p.groups.length ? " [" + p.groups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`).join(", ") + "]" : "";
|
|
6551
|
+
const statusDot = p.status === "working" ? yellow("●") : green("●");
|
|
6552
|
+
const name = bold(p.displayName);
|
|
6553
|
+
const meta = [];
|
|
6554
|
+
if (p.peerType)
|
|
6555
|
+
meta.push(p.peerType);
|
|
6556
|
+
if (p.channel)
|
|
6557
|
+
meta.push(p.channel);
|
|
6558
|
+
if (p.model)
|
|
6559
|
+
meta.push(p.model);
|
|
6560
|
+
const metaStr = meta.length ? dim(` (${meta.join(", ")})`) : "";
|
|
6561
|
+
const summary = p.summary ? dim(` — ${p.summary}`) : "";
|
|
6562
|
+
const pubkeyTag = dim(` · ${p.pubkey.slice(0, 16)}…`);
|
|
6563
|
+
render.info(`${statusDot} ${name}${groups}${metaStr}${pubkeyTag}${summary}`);
|
|
6564
|
+
if (p.cwd)
|
|
6565
|
+
render.info(dim(` cwd: ${p.cwd}`));
|
|
6566
|
+
}
|
|
6443
6567
|
} catch (e) {
|
|
6444
6568
|
render.err(`${slug}: ${e instanceof Error ? e.message : String(e)}`);
|
|
6445
6569
|
}
|
|
6446
6570
|
}
|
|
6447
|
-
if (
|
|
6571
|
+
if (wantsJson) {
|
|
6448
6572
|
process.stdout.write(JSON.stringify(slugs.length === 1 ? allJson[0]?.peers : allJson, null, 2) + `
|
|
6449
6573
|
`);
|
|
6450
6574
|
}
|
|
6451
6575
|
}
|
|
6576
|
+
var FIELD_ALIAS;
|
|
6452
6577
|
var init_peers = __esm(() => {
|
|
6453
6578
|
init_connect();
|
|
6454
6579
|
init_facade();
|
|
6580
|
+
init_client3();
|
|
6455
6581
|
init_render();
|
|
6456
6582
|
init_styles();
|
|
6583
|
+
FIELD_ALIAS = {
|
|
6584
|
+
name: "displayName"
|
|
6585
|
+
};
|
|
6457
6586
|
});
|
|
6458
6587
|
|
|
6459
6588
|
// src/commands/send.ts
|
|
@@ -6462,7 +6591,33 @@ __export(exports_send, {
|
|
|
6462
6591
|
runSend: () => runSend
|
|
6463
6592
|
});
|
|
6464
6593
|
async function runSend(flags, to, message) {
|
|
6594
|
+
if (!to || !message) {
|
|
6595
|
+
render.err("Usage: claudemesh send <to> <message>");
|
|
6596
|
+
process.exit(1);
|
|
6597
|
+
}
|
|
6465
6598
|
const priority = flags.priority === "now" ? "now" : flags.priority === "low" ? "low" : "next";
|
|
6599
|
+
const config = readConfig();
|
|
6600
|
+
const meshSlug = flags.mesh ?? (config.meshes.length === 1 ? config.meshes[0].slug : null);
|
|
6601
|
+
if (meshSlug) {
|
|
6602
|
+
const bridged = await tryBridge(meshSlug, "send", { to, message, priority });
|
|
6603
|
+
if (bridged !== null) {
|
|
6604
|
+
if (bridged.ok) {
|
|
6605
|
+
const r = bridged.result;
|
|
6606
|
+
if (flags.json) {
|
|
6607
|
+
console.log(JSON.stringify({ ok: true, messageId: r.messageId, target: to }));
|
|
6608
|
+
} else {
|
|
6609
|
+
render.ok(`sent to ${to}`, r.messageId ? dim(r.messageId.slice(0, 8)) : undefined);
|
|
6610
|
+
}
|
|
6611
|
+
return;
|
|
6612
|
+
}
|
|
6613
|
+
if (flags.json) {
|
|
6614
|
+
console.log(JSON.stringify({ ok: false, error: bridged.error }));
|
|
6615
|
+
} else {
|
|
6616
|
+
render.err(`send failed: ${bridged.error}`);
|
|
6617
|
+
}
|
|
6618
|
+
process.exit(1);
|
|
6619
|
+
}
|
|
6620
|
+
}
|
|
6466
6621
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
|
|
6467
6622
|
let targetSpec = to;
|
|
6468
6623
|
if (!to.startsWith("@") && to !== "*" && !/^[0-9a-f]{64}$/i.test(to)) {
|
|
@@ -6470,22 +6625,34 @@ async function runSend(flags, to, message) {
|
|
|
6470
6625
|
const match = peers.find((p) => p.displayName.toLowerCase() === to.toLowerCase());
|
|
6471
6626
|
if (!match) {
|
|
6472
6627
|
const names = peers.map((p) => p.displayName).join(", ");
|
|
6473
|
-
|
|
6628
|
+
render.err(`Peer "${to}" not found.`, `online: ${names || "(none)"}`);
|
|
6474
6629
|
process.exit(1);
|
|
6475
6630
|
}
|
|
6476
6631
|
targetSpec = match.pubkey;
|
|
6477
6632
|
}
|
|
6478
6633
|
const result = await client.send(targetSpec, message, priority);
|
|
6479
6634
|
if (result.ok) {
|
|
6480
|
-
|
|
6635
|
+
if (flags.json) {
|
|
6636
|
+
console.log(JSON.stringify({ ok: true, messageId: result.messageId, target: to }));
|
|
6637
|
+
} else {
|
|
6638
|
+
render.ok(`sent to ${to}`, result.messageId ? dim(result.messageId.slice(0, 8)) : undefined);
|
|
6639
|
+
}
|
|
6481
6640
|
} else {
|
|
6482
|
-
|
|
6641
|
+
if (flags.json) {
|
|
6642
|
+
console.log(JSON.stringify({ ok: false, error: result.error ?? "unknown" }));
|
|
6643
|
+
} else {
|
|
6644
|
+
render.err(`send failed: ${result.error ?? "unknown error"}`);
|
|
6645
|
+
}
|
|
6483
6646
|
process.exit(1);
|
|
6484
6647
|
}
|
|
6485
6648
|
});
|
|
6486
6649
|
}
|
|
6487
6650
|
var init_send = __esm(() => {
|
|
6488
6651
|
init_connect();
|
|
6652
|
+
init_facade();
|
|
6653
|
+
init_client3();
|
|
6654
|
+
init_render();
|
|
6655
|
+
init_styles();
|
|
6489
6656
|
});
|
|
6490
6657
|
|
|
6491
6658
|
// src/commands/inbox.ts
|
|
@@ -6731,20 +6898,40 @@ __export(exports_broker_actions, {
|
|
|
6731
6898
|
runForget: () => runForget,
|
|
6732
6899
|
runClock: () => runClock
|
|
6733
6900
|
});
|
|
6901
|
+
function unambiguousMesh(opts) {
|
|
6902
|
+
if (opts.mesh)
|
|
6903
|
+
return opts.mesh;
|
|
6904
|
+
const config = readConfig();
|
|
6905
|
+
return config.meshes.length === 1 ? config.meshes[0].slug : null;
|
|
6906
|
+
}
|
|
6734
6907
|
async function runStatusSet(state, opts) {
|
|
6735
6908
|
const valid = ["idle", "working", "dnd"];
|
|
6736
6909
|
if (!valid.includes(state)) {
|
|
6737
6910
|
render.err(`Invalid status: ${state}`, `must be one of: ${valid.join(", ")}`);
|
|
6738
6911
|
return EXIT.INVALID_ARGS;
|
|
6739
6912
|
}
|
|
6913
|
+
const meshSlug = unambiguousMesh(opts);
|
|
6914
|
+
if (meshSlug) {
|
|
6915
|
+
const bridged = await tryBridge(meshSlug, "status_set", { status: state });
|
|
6916
|
+
if (bridged !== null) {
|
|
6917
|
+
if (bridged.ok) {
|
|
6918
|
+
if (opts.json)
|
|
6919
|
+
console.log(JSON.stringify({ status: state }));
|
|
6920
|
+
else
|
|
6921
|
+
render.ok(`status set to ${bold(state)}`);
|
|
6922
|
+
return EXIT.SUCCESS;
|
|
6923
|
+
}
|
|
6924
|
+
render.err(bridged.error);
|
|
6925
|
+
return EXIT.INTERNAL_ERROR;
|
|
6926
|
+
}
|
|
6927
|
+
}
|
|
6740
6928
|
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
6741
6929
|
await client.setStatus(state);
|
|
6742
6930
|
});
|
|
6743
|
-
if (opts.json)
|
|
6931
|
+
if (opts.json)
|
|
6744
6932
|
console.log(JSON.stringify({ status: state }));
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
render.ok(`status set to ${bold(state)}`);
|
|
6933
|
+
else
|
|
6934
|
+
render.ok(`status set to ${bold(state)}`);
|
|
6748
6935
|
return EXIT.SUCCESS;
|
|
6749
6936
|
}
|
|
6750
6937
|
async function runSummary(text, opts) {
|
|
@@ -6752,14 +6939,28 @@ async function runSummary(text, opts) {
|
|
|
6752
6939
|
render.err("Usage: claudemesh summary <text>");
|
|
6753
6940
|
return EXIT.INVALID_ARGS;
|
|
6754
6941
|
}
|
|
6942
|
+
const meshSlug = unambiguousMesh(opts);
|
|
6943
|
+
if (meshSlug) {
|
|
6944
|
+
const bridged = await tryBridge(meshSlug, "summary", { summary: text });
|
|
6945
|
+
if (bridged !== null) {
|
|
6946
|
+
if (bridged.ok) {
|
|
6947
|
+
if (opts.json)
|
|
6948
|
+
console.log(JSON.stringify({ summary: text }));
|
|
6949
|
+
else
|
|
6950
|
+
render.ok("summary set", dim(text));
|
|
6951
|
+
return EXIT.SUCCESS;
|
|
6952
|
+
}
|
|
6953
|
+
render.err(bridged.error);
|
|
6954
|
+
return EXIT.INTERNAL_ERROR;
|
|
6955
|
+
}
|
|
6956
|
+
}
|
|
6755
6957
|
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
6756
6958
|
await client.setSummary(text);
|
|
6757
6959
|
});
|
|
6758
|
-
if (opts.json)
|
|
6960
|
+
if (opts.json)
|
|
6759
6961
|
console.log(JSON.stringify({ summary: text }));
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
render.ok("summary set", dim(text));
|
|
6962
|
+
else
|
|
6963
|
+
render.ok("summary set", dim(text));
|
|
6763
6964
|
return EXIT.SUCCESS;
|
|
6764
6965
|
}
|
|
6765
6966
|
async function runVisible(value, opts) {
|
|
@@ -6772,14 +6973,28 @@ async function runVisible(value, opts) {
|
|
|
6772
6973
|
render.err("Usage: claudemesh visible <true|false>");
|
|
6773
6974
|
return EXIT.INVALID_ARGS;
|
|
6774
6975
|
}
|
|
6976
|
+
const meshSlug = unambiguousMesh(opts);
|
|
6977
|
+
if (meshSlug) {
|
|
6978
|
+
const bridged = await tryBridge(meshSlug, "visible", { visible });
|
|
6979
|
+
if (bridged !== null) {
|
|
6980
|
+
if (bridged.ok) {
|
|
6981
|
+
if (opts.json)
|
|
6982
|
+
console.log(JSON.stringify({ visible }));
|
|
6983
|
+
else
|
|
6984
|
+
render.ok(visible ? "you are now visible to peers" : "you are now hidden", visible ? undefined : "direct messages still reach you");
|
|
6985
|
+
return EXIT.SUCCESS;
|
|
6986
|
+
}
|
|
6987
|
+
render.err(bridged.error);
|
|
6988
|
+
return EXIT.INTERNAL_ERROR;
|
|
6989
|
+
}
|
|
6990
|
+
}
|
|
6775
6991
|
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
6776
6992
|
await client.setVisible(visible);
|
|
6777
6993
|
});
|
|
6778
|
-
if (opts.json)
|
|
6994
|
+
if (opts.json)
|
|
6779
6995
|
console.log(JSON.stringify({ visible }));
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
render.ok(visible ? "you are now visible to peers" : "you are now hidden", visible ? undefined : "direct messages still reach you");
|
|
6996
|
+
else
|
|
6997
|
+
render.ok(visible ? "you are now visible to peers" : "you are now hidden", visible ? undefined : "direct messages still reach you");
|
|
6783
6998
|
return EXIT.SUCCESS;
|
|
6784
6999
|
}
|
|
6785
7000
|
async function runGroupJoin(name, opts) {
|
|
@@ -6967,6 +7182,8 @@ async function runTaskComplete(id, result, opts) {
|
|
|
6967
7182
|
}
|
|
6968
7183
|
var init_broker_actions = __esm(() => {
|
|
6969
7184
|
init_connect();
|
|
7185
|
+
init_facade();
|
|
7186
|
+
init_client3();
|
|
6970
7187
|
init_render();
|
|
6971
7188
|
init_styles();
|
|
6972
7189
|
init_exit_codes();
|
|
@@ -7278,17 +7495,17 @@ __export(exports_install, {
|
|
|
7278
7495
|
import {
|
|
7279
7496
|
chmodSync as chmodSync3,
|
|
7280
7497
|
copyFileSync,
|
|
7281
|
-
existsSync as
|
|
7498
|
+
existsSync as existsSync6,
|
|
7282
7499
|
mkdirSync as mkdirSync3,
|
|
7283
7500
|
readFileSync as readFileSync4,
|
|
7284
7501
|
writeFileSync as writeFileSync5
|
|
7285
7502
|
} from "node:fs";
|
|
7286
|
-
import { homedir as
|
|
7287
|
-
import { dirname as dirname2, join as
|
|
7503
|
+
import { homedir as homedir5, platform as platform5 } from "node:os";
|
|
7504
|
+
import { dirname as dirname2, join as join5, resolve } from "node:path";
|
|
7288
7505
|
import { fileURLToPath } from "node:url";
|
|
7289
7506
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
7290
7507
|
function readClaudeConfig() {
|
|
7291
|
-
if (!
|
|
7508
|
+
if (!existsSync6(CLAUDE_CONFIG))
|
|
7292
7509
|
return {};
|
|
7293
7510
|
const text = readFileSync4(CLAUDE_CONFIG, "utf-8").trim();
|
|
7294
7511
|
if (!text)
|
|
@@ -7300,12 +7517,12 @@ function readClaudeConfig() {
|
|
|
7300
7517
|
}
|
|
7301
7518
|
}
|
|
7302
7519
|
function backupClaudeConfig() {
|
|
7303
|
-
if (!
|
|
7520
|
+
if (!existsSync6(CLAUDE_CONFIG))
|
|
7304
7521
|
return;
|
|
7305
|
-
const backupDir =
|
|
7522
|
+
const backupDir = join5(dirname2(CLAUDE_CONFIG), ".claude", "backups");
|
|
7306
7523
|
mkdirSync3(backupDir, { recursive: true });
|
|
7307
7524
|
const ts = Date.now();
|
|
7308
|
-
const dest =
|
|
7525
|
+
const dest = join5(backupDir, `.claude.json.pre-claudemesh.${ts}`);
|
|
7309
7526
|
copyFileSync(CLAUDE_CONFIG, dest);
|
|
7310
7527
|
}
|
|
7311
7528
|
function patchMcpServer(entry) {
|
|
@@ -7329,7 +7546,7 @@ function patchMcpServer(entry) {
|
|
|
7329
7546
|
return action;
|
|
7330
7547
|
}
|
|
7331
7548
|
function removeMcpServer() {
|
|
7332
|
-
if (!
|
|
7549
|
+
if (!existsSync6(CLAUDE_CONFIG))
|
|
7333
7550
|
return false;
|
|
7334
7551
|
backupClaudeConfig();
|
|
7335
7552
|
const cfg = readClaudeConfig();
|
|
@@ -7377,7 +7594,7 @@ function entriesEqual(a, b) {
|
|
|
7377
7594
|
return a.command === b.command && JSON.stringify(a.args ?? []) === JSON.stringify(b.args ?? []);
|
|
7378
7595
|
}
|
|
7379
7596
|
function readClaudeSettings() {
|
|
7380
|
-
if (!
|
|
7597
|
+
if (!existsSync6(CLAUDE_SETTINGS))
|
|
7381
7598
|
return {};
|
|
7382
7599
|
const text = readFileSync4(CLAUDE_SETTINGS, "utf-8").trim();
|
|
7383
7600
|
if (!text)
|
|
@@ -7404,7 +7621,7 @@ function installAllowedTools() {
|
|
|
7404
7621
|
return { added: toAdd, unchanged: CLAUDEMESH_TOOLS.length - toAdd.length };
|
|
7405
7622
|
}
|
|
7406
7623
|
function uninstallAllowedTools() {
|
|
7407
|
-
if (!
|
|
7624
|
+
if (!existsSync6(CLAUDE_SETTINGS))
|
|
7408
7625
|
return 0;
|
|
7409
7626
|
const settings = readClaudeSettings();
|
|
7410
7627
|
const existing = settings.allowedTools ?? [];
|
|
@@ -7439,7 +7656,7 @@ function installHooks() {
|
|
|
7439
7656
|
return { added, unchanged };
|
|
7440
7657
|
}
|
|
7441
7658
|
function uninstallHooks() {
|
|
7442
|
-
if (!
|
|
7659
|
+
if (!existsSync6(CLAUDE_SETTINGS))
|
|
7443
7660
|
return 0;
|
|
7444
7661
|
const settings = readClaudeSettings();
|
|
7445
7662
|
const hooks = settings.hooks;
|
|
@@ -7487,7 +7704,7 @@ function runInstall(args = []) {
|
|
|
7487
7704
|
render.err("`bun` is not on PATH.", "Install Bun first: https://bun.com");
|
|
7488
7705
|
process.exit(1);
|
|
7489
7706
|
}
|
|
7490
|
-
if (!
|
|
7707
|
+
if (!existsSync6(entry)) {
|
|
7491
7708
|
render.err(`MCP entry not found at ${entry}`);
|
|
7492
7709
|
process.exit(1);
|
|
7493
7710
|
}
|
|
@@ -7603,8 +7820,8 @@ var init_install = __esm(() => {
|
|
|
7603
7820
|
init_facade();
|
|
7604
7821
|
init_render();
|
|
7605
7822
|
init_styles();
|
|
7606
|
-
CLAUDE_CONFIG =
|
|
7607
|
-
CLAUDE_SETTINGS =
|
|
7823
|
+
CLAUDE_CONFIG = join5(homedir5(), ".claude.json");
|
|
7824
|
+
CLAUDE_SETTINGS = join5(homedir5(), ".claude", "settings.json");
|
|
7608
7825
|
CLAUDEMESH_TOOLS = [
|
|
7609
7826
|
"mcp__claudemesh__cancel_scheduled",
|
|
7610
7827
|
"mcp__claudemesh__check_messages",
|
|
@@ -7659,10 +7876,10 @@ var exports_uninstall = {};
|
|
|
7659
7876
|
__export(exports_uninstall, {
|
|
7660
7877
|
uninstall: () => uninstall
|
|
7661
7878
|
});
|
|
7662
|
-
import { readFileSync as readFileSync5, writeFileSync as writeFileSync6, existsSync as
|
|
7879
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync6, existsSync as existsSync7 } from "node:fs";
|
|
7663
7880
|
async function uninstall() {
|
|
7664
7881
|
let removed = 0;
|
|
7665
|
-
if (
|
|
7882
|
+
if (existsSync7(PATHS.CLAUDE_JSON)) {
|
|
7666
7883
|
try {
|
|
7667
7884
|
const raw = readFileSync5(PATHS.CLAUDE_JSON, "utf-8");
|
|
7668
7885
|
const config = JSON.parse(raw);
|
|
@@ -7676,7 +7893,7 @@ async function uninstall() {
|
|
|
7676
7893
|
}
|
|
7677
7894
|
} catch {}
|
|
7678
7895
|
}
|
|
7679
|
-
if (
|
|
7896
|
+
if (existsSync7(PATHS.CLAUDE_SETTINGS)) {
|
|
7680
7897
|
try {
|
|
7681
7898
|
const raw = readFileSync5(PATHS.CLAUDE_SETTINGS, "utf-8");
|
|
7682
7899
|
const config = JSON.parse(raw);
|
|
@@ -7724,9 +7941,9 @@ var exports_doctor = {};
|
|
|
7724
7941
|
__export(exports_doctor, {
|
|
7725
7942
|
runDoctor: () => runDoctor
|
|
7726
7943
|
});
|
|
7727
|
-
import { existsSync as
|
|
7728
|
-
import { homedir as
|
|
7729
|
-
import { join as
|
|
7944
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync2 } from "node:fs";
|
|
7945
|
+
import { homedir as homedir6, platform as platform6 } from "node:os";
|
|
7946
|
+
import { join as join6 } from "node:path";
|
|
7730
7947
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
7731
7948
|
function checkNode() {
|
|
7732
7949
|
const major = Number(process.versions.node.split(".")[0]);
|
|
@@ -7750,8 +7967,8 @@ function checkClaudeOnPath() {
|
|
|
7750
7967
|
};
|
|
7751
7968
|
}
|
|
7752
7969
|
function checkMcpRegistered() {
|
|
7753
|
-
const claudeConfig =
|
|
7754
|
-
if (!
|
|
7970
|
+
const claudeConfig = join6(homedir6(), ".claude.json");
|
|
7971
|
+
if (!existsSync8(claudeConfig)) {
|
|
7755
7972
|
return {
|
|
7756
7973
|
name: "claudemesh MCP registered in ~/.claude.json",
|
|
7757
7974
|
pass: false,
|
|
@@ -7776,8 +7993,8 @@ function checkMcpRegistered() {
|
|
|
7776
7993
|
}
|
|
7777
7994
|
}
|
|
7778
7995
|
function checkHooksRegistered() {
|
|
7779
|
-
const settings =
|
|
7780
|
-
if (!
|
|
7996
|
+
const settings = join6(homedir6(), ".claude", "settings.json");
|
|
7997
|
+
if (!existsSync8(settings)) {
|
|
7781
7998
|
return {
|
|
7782
7999
|
name: "Status hooks registered in ~/.claude/settings.json",
|
|
7783
8000
|
pass: false,
|
|
@@ -7802,7 +8019,7 @@ function checkHooksRegistered() {
|
|
|
7802
8019
|
}
|
|
7803
8020
|
function checkConfigFile() {
|
|
7804
8021
|
const path = getConfigPath();
|
|
7805
|
-
if (!
|
|
8022
|
+
if (!existsSync8(path)) {
|
|
7806
8023
|
return {
|
|
7807
8024
|
name: "~/.claudemesh/config.json exists and parses",
|
|
7808
8025
|
pass: true,
|
|
@@ -7985,7 +8202,7 @@ var exports_status = {};
|
|
|
7985
8202
|
__export(exports_status, {
|
|
7986
8203
|
runStatus: () => runStatus
|
|
7987
8204
|
});
|
|
7988
|
-
import { statSync as statSync3, existsSync as
|
|
8205
|
+
import { statSync as statSync3, existsSync as existsSync9 } from "node:fs";
|
|
7989
8206
|
import WebSocket2 from "ws";
|
|
7990
8207
|
async function probeBroker(url, timeoutMs = 4000) {
|
|
7991
8208
|
return new Promise((resolve2) => {
|
|
@@ -8015,7 +8232,7 @@ async function runStatus() {
|
|
|
8015
8232
|
render.section(`status (v${VERSION})`);
|
|
8016
8233
|
const configPath = getConfigPath();
|
|
8017
8234
|
let configPermsNote = "missing";
|
|
8018
|
-
if (
|
|
8235
|
+
if (existsSync9(configPath)) {
|
|
8019
8236
|
const mode = (statSync3(configPath).mode & 511).toString(8).padStart(4, "0");
|
|
8020
8237
|
configPermsNote = mode === "0600" ? `${mode}` : `${mode} — expected 0600`;
|
|
8021
8238
|
}
|
|
@@ -8161,10 +8378,10 @@ var init_check_claude_binary = __esm(() => {
|
|
|
8161
8378
|
});
|
|
8162
8379
|
|
|
8163
8380
|
// src/services/health/check-mcp-registered.ts
|
|
8164
|
-
import { existsSync as
|
|
8381
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "node:fs";
|
|
8165
8382
|
function checkMcpRegistered2() {
|
|
8166
8383
|
try {
|
|
8167
|
-
if (!
|
|
8384
|
+
if (!existsSync10(PATHS.CLAUDE_JSON)) {
|
|
8168
8385
|
return { name: "mcp-registered", ok: false, message: "~/.claude.json not found" };
|
|
8169
8386
|
}
|
|
8170
8387
|
const raw = readFileSync7(PATHS.CLAUDE_JSON, "utf-8");
|
|
@@ -8182,10 +8399,10 @@ var init_check_mcp_registered = __esm(() => {
|
|
|
8182
8399
|
});
|
|
8183
8400
|
|
|
8184
8401
|
// src/services/health/check-hooks-registered.ts
|
|
8185
|
-
import { existsSync as
|
|
8402
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8 } from "node:fs";
|
|
8186
8403
|
function checkHooksRegistered2() {
|
|
8187
8404
|
try {
|
|
8188
|
-
if (!
|
|
8405
|
+
if (!existsSync11(PATHS.CLAUDE_SETTINGS)) {
|
|
8189
8406
|
return { name: "hooks-registered", ok: false, message: "~/.claude/settings.json not found" };
|
|
8190
8407
|
}
|
|
8191
8408
|
const raw = readFileSync8(PATHS.CLAUDE_SETTINGS, "utf-8");
|
|
@@ -8203,10 +8420,10 @@ var init_check_hooks_registered = __esm(() => {
|
|
|
8203
8420
|
});
|
|
8204
8421
|
|
|
8205
8422
|
// src/services/health/check-config-perms.ts
|
|
8206
|
-
import { existsSync as
|
|
8423
|
+
import { existsSync as existsSync12, statSync as statSync4 } from "node:fs";
|
|
8207
8424
|
function checkConfigPerms() {
|
|
8208
8425
|
const configFile = PATHS.CONFIG_FILE;
|
|
8209
|
-
if (!
|
|
8426
|
+
if (!existsSync12(configFile)) {
|
|
8210
8427
|
return { name: "config-perms", ok: true, message: "No config file yet (first run)" };
|
|
8211
8428
|
}
|
|
8212
8429
|
try {
|
|
@@ -8224,9 +8441,9 @@ var init_check_config_perms = __esm(() => {
|
|
|
8224
8441
|
});
|
|
8225
8442
|
|
|
8226
8443
|
// src/services/health/check-keypairs-valid.ts
|
|
8227
|
-
import { existsSync as
|
|
8444
|
+
import { existsSync as existsSync13, readFileSync as readFileSync9 } from "node:fs";
|
|
8228
8445
|
function checkKeypairsValid() {
|
|
8229
|
-
if (!
|
|
8446
|
+
if (!existsSync13(PATHS.CONFIG_FILE)) {
|
|
8230
8447
|
return { name: "keypairs-valid", ok: true, message: "No config (first run)" };
|
|
8231
8448
|
}
|
|
8232
8449
|
try {
|
|
@@ -8710,18 +8927,18 @@ var exports_url_handler = {};
|
|
|
8710
8927
|
__export(exports_url_handler, {
|
|
8711
8928
|
runUrlHandler: () => runUrlHandler
|
|
8712
8929
|
});
|
|
8713
|
-
import { platform as platform7, homedir as
|
|
8714
|
-
import { existsSync as
|
|
8715
|
-
import { join as
|
|
8930
|
+
import { platform as platform7, homedir as homedir7 } from "node:os";
|
|
8931
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync4, writeFileSync as writeFileSync7, rmSync as rmSync2, chmodSync as chmodSync4 } from "node:fs";
|
|
8932
|
+
import { join as join7 } from "node:path";
|
|
8716
8933
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
8717
8934
|
function resolveClaudemeshBin() {
|
|
8718
8935
|
return process.argv[1] ?? "claudemesh";
|
|
8719
8936
|
}
|
|
8720
8937
|
function installDarwin() {
|
|
8721
8938
|
const binPath = resolveClaudemeshBin();
|
|
8722
|
-
const appDir =
|
|
8723
|
-
const contents =
|
|
8724
|
-
const macOS =
|
|
8939
|
+
const appDir = join7(homedir7(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
|
|
8940
|
+
const contents = join7(appDir, "Contents");
|
|
8941
|
+
const macOS = join7(contents, "MacOS");
|
|
8725
8942
|
mkdirSync4(macOS, { recursive: true });
|
|
8726
8943
|
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
8727
8944
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -8745,7 +8962,7 @@ function installDarwin() {
|
|
|
8745
8962
|
</array>
|
|
8746
8963
|
</dict>
|
|
8747
8964
|
</plist>`;
|
|
8748
|
-
writeFileSync7(
|
|
8965
|
+
writeFileSync7(join7(contents, "Info.plist"), plist);
|
|
8749
8966
|
const shim = `#!/bin/sh
|
|
8750
8967
|
URL="$1"
|
|
8751
8968
|
CODE=\${URL#claudemesh://}
|
|
@@ -8759,7 +8976,7 @@ tell application "Terminal"
|
|
|
8759
8976
|
end tell
|
|
8760
8977
|
EOF
|
|
8761
8978
|
`;
|
|
8762
|
-
const shimPath =
|
|
8979
|
+
const shimPath = join7(macOS, "open-url");
|
|
8763
8980
|
writeFileSync7(shimPath, shim);
|
|
8764
8981
|
chmodSync4(shimPath, 493);
|
|
8765
8982
|
const lsreg = spawnSync5("/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister", ["-f", appDir], { encoding: "utf-8" });
|
|
@@ -8771,7 +8988,7 @@ EOF
|
|
|
8771
8988
|
}
|
|
8772
8989
|
function installLinux() {
|
|
8773
8990
|
const binPath = resolveClaudemeshBin();
|
|
8774
|
-
const appsDir =
|
|
8991
|
+
const appsDir = join7(homedir7(), ".local", "share", "applications");
|
|
8775
8992
|
mkdirSync4(appsDir, { recursive: true });
|
|
8776
8993
|
const desktop = `[Desktop Entry]
|
|
8777
8994
|
Type=Application
|
|
@@ -8783,7 +9000,7 @@ Terminal=true
|
|
|
8783
9000
|
MimeType=x-scheme-handler/claudemesh;
|
|
8784
9001
|
NoDisplay=true
|
|
8785
9002
|
`;
|
|
8786
|
-
const desktopPath =
|
|
9003
|
+
const desktopPath = join7(appsDir, "claudemesh.desktop");
|
|
8787
9004
|
writeFileSync7(desktopPath, desktop);
|
|
8788
9005
|
const xdg1 = spawnSync5("xdg-mime", ["default", "claudemesh.desktop", "x-scheme-handler/claudemesh"], { encoding: "utf-8" });
|
|
8789
9006
|
if (xdg1.status !== 0) {
|
|
@@ -8806,7 +9023,7 @@ function installWindows() {
|
|
|
8806
9023
|
`[HKEY_CURRENT_USER\\Software\\Classes\\claudemesh\\shell\\open\\command]`,
|
|
8807
9024
|
`@="\\"${binPath.replace(/\\/g, "\\\\")}\\" \\"%1\\""`
|
|
8808
9025
|
];
|
|
8809
|
-
const regPath =
|
|
9026
|
+
const regPath = join7(homedir7(), "claudemesh-handler.reg");
|
|
8810
9027
|
writeFileSync7(regPath, lines.join(`\r
|
|
8811
9028
|
`));
|
|
8812
9029
|
const res = spawnSync5("reg.exe", ["import", regPath], { encoding: "utf-8" });
|
|
@@ -8818,15 +9035,15 @@ function installWindows() {
|
|
|
8818
9035
|
return EXIT.SUCCESS;
|
|
8819
9036
|
}
|
|
8820
9037
|
function uninstallDarwin() {
|
|
8821
|
-
const appDir =
|
|
8822
|
-
if (
|
|
9038
|
+
const appDir = join7(homedir7(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
|
|
9039
|
+
if (existsSync14(appDir))
|
|
8823
9040
|
rmSync2(appDir, { recursive: true, force: true });
|
|
8824
9041
|
render.ok("removed claudemesh:// handler on macOS");
|
|
8825
9042
|
return EXIT.SUCCESS;
|
|
8826
9043
|
}
|
|
8827
9044
|
function uninstallLinux() {
|
|
8828
|
-
const desktopPath =
|
|
8829
|
-
if (
|
|
9045
|
+
const desktopPath = join7(homedir7(), ".local", "share", "applications", "claudemesh.desktop");
|
|
9046
|
+
if (existsSync14(desktopPath))
|
|
8830
9047
|
rmSync2(desktopPath, { force: true });
|
|
8831
9048
|
render.ok("removed claudemesh:// handler on Linux");
|
|
8832
9049
|
return EXIT.SUCCESS;
|
|
@@ -8871,9 +9088,9 @@ var exports_status_line = {};
|
|
|
8871
9088
|
__export(exports_status_line, {
|
|
8872
9089
|
runStatusLine: () => runStatusLine
|
|
8873
9090
|
});
|
|
8874
|
-
import { existsSync as
|
|
8875
|
-
import { join as
|
|
8876
|
-
import { homedir as
|
|
9091
|
+
import { existsSync as existsSync15, readFileSync as readFileSync10 } from "node:fs";
|
|
9092
|
+
import { join as join8 } from "node:path";
|
|
9093
|
+
import { homedir as homedir8 } from "node:os";
|
|
8877
9094
|
async function runStatusLine() {
|
|
8878
9095
|
try {
|
|
8879
9096
|
const config = readConfig();
|
|
@@ -8881,9 +9098,9 @@ async function runStatusLine() {
|
|
|
8881
9098
|
process.stdout.write("◇ claudemesh (not joined)");
|
|
8882
9099
|
return EXIT.SUCCESS;
|
|
8883
9100
|
}
|
|
8884
|
-
const cachePath =
|
|
9101
|
+
const cachePath = join8(homedir8(), ".claudemesh", "peer-cache.json");
|
|
8885
9102
|
let cache = {};
|
|
8886
|
-
if (
|
|
9103
|
+
if (existsSync15(cachePath)) {
|
|
8887
9104
|
try {
|
|
8888
9105
|
cache = JSON.parse(readFileSync10(cachePath, "utf-8"));
|
|
8889
9106
|
} catch {}
|
|
@@ -8916,7 +9133,7 @@ __export(exports_backup, {
|
|
|
8916
9133
|
runRestore: () => runRestore,
|
|
8917
9134
|
runBackup: () => runBackup
|
|
8918
9135
|
});
|
|
8919
|
-
import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, existsSync as
|
|
9136
|
+
import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, existsSync as existsSync16 } from "node:fs";
|
|
8920
9137
|
import { createInterface as createInterface10 } from "node:readline";
|
|
8921
9138
|
function readHidden(prompt5) {
|
|
8922
9139
|
return new Promise((resolve2) => {
|
|
@@ -8958,7 +9175,7 @@ async function deriveKey(pass, salt, s) {
|
|
|
8958
9175
|
}
|
|
8959
9176
|
async function runBackup(outPath) {
|
|
8960
9177
|
const configPath = getConfigPath();
|
|
8961
|
-
if (!
|
|
9178
|
+
if (!existsSync16(configPath)) {
|
|
8962
9179
|
console.error(" No config found — nothing to back up. Join a mesh first.");
|
|
8963
9180
|
return EXIT.NOT_FOUND;
|
|
8964
9181
|
}
|
|
@@ -8992,7 +9209,7 @@ async function runRestore(inPath) {
|
|
|
8992
9209
|
console.error(" Usage: claudemesh restore <backup-file>");
|
|
8993
9210
|
return EXIT.INVALID_ARGS;
|
|
8994
9211
|
}
|
|
8995
|
-
if (!
|
|
9212
|
+
if (!existsSync16(inPath)) {
|
|
8996
9213
|
console.error(` ✗ File not found: ${inPath}`);
|
|
8997
9214
|
return EXIT.NOT_FOUND;
|
|
8998
9215
|
}
|
|
@@ -9015,7 +9232,7 @@ async function runRestore(inPath) {
|
|
|
9015
9232
|
return EXIT.INTERNAL_ERROR;
|
|
9016
9233
|
}
|
|
9017
9234
|
const configPath = getConfigPath();
|
|
9018
|
-
if (
|
|
9235
|
+
if (existsSync16(configPath)) {
|
|
9019
9236
|
const backupOld = `${configPath}.before-restore.${Date.now()}`;
|
|
9020
9237
|
writeFileSync8(backupOld, readFileSync11(configPath), { mode: 384 });
|
|
9021
9238
|
console.log(` ↻ Existing config saved to ${backupOld}`);
|
|
@@ -9040,8 +9257,8 @@ __export(exports_upgrade, {
|
|
|
9040
9257
|
runUpgrade: () => runUpgrade
|
|
9041
9258
|
});
|
|
9042
9259
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
9043
|
-
import { existsSync as
|
|
9044
|
-
import { dirname as dirname3, join as
|
|
9260
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
9261
|
+
import { dirname as dirname3, join as join9, resolve as resolve2 } from "node:path";
|
|
9045
9262
|
async function latestVersion() {
|
|
9046
9263
|
try {
|
|
9047
9264
|
const res = await fetch(URLS.NPM_REGISTRY, { signal: AbortSignal.timeout(8000) });
|
|
@@ -9054,15 +9271,15 @@ async function latestVersion() {
|
|
|
9054
9271
|
}
|
|
9055
9272
|
}
|
|
9056
9273
|
function findNpm() {
|
|
9057
|
-
const portable =
|
|
9058
|
-
if (
|
|
9059
|
-
return { npm: portable, prefix:
|
|
9274
|
+
const portable = join9(process.env.HOME ?? "", ".claudemesh", "node", "bin", "npm");
|
|
9275
|
+
if (existsSync17(portable)) {
|
|
9276
|
+
return { npm: portable, prefix: join9(process.env.HOME ?? "", ".claudemesh") };
|
|
9060
9277
|
}
|
|
9061
9278
|
let cur = resolve2(process.argv[1] ?? ".");
|
|
9062
9279
|
for (let i = 0;i < 6; i++) {
|
|
9063
9280
|
cur = dirname3(cur);
|
|
9064
|
-
const candidate =
|
|
9065
|
-
if (
|
|
9281
|
+
const candidate = join9(cur, "bin", "npm");
|
|
9282
|
+
if (existsSync17(candidate))
|
|
9066
9283
|
return { npm: candidate };
|
|
9067
9284
|
}
|
|
9068
9285
|
return { npm: "npm" };
|
|
@@ -9124,9 +9341,9 @@ __export(exports_grants, {
|
|
|
9124
9341
|
runBlock: () => runBlock,
|
|
9125
9342
|
isAllowed: () => isAllowed
|
|
9126
9343
|
});
|
|
9127
|
-
import { existsSync as
|
|
9128
|
-
import { homedir as
|
|
9129
|
-
import { join as
|
|
9344
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
|
|
9345
|
+
import { homedir as homedir9 } from "node:os";
|
|
9346
|
+
import { join as join10 } from "node:path";
|
|
9130
9347
|
async function syncToBroker(meshSlug, grants) {
|
|
9131
9348
|
const auth = getStoredToken();
|
|
9132
9349
|
if (!auth)
|
|
@@ -9144,7 +9361,7 @@ async function syncToBroker(meshSlug, grants) {
|
|
|
9144
9361
|
}
|
|
9145
9362
|
}
|
|
9146
9363
|
function readGrants() {
|
|
9147
|
-
if (!
|
|
9364
|
+
if (!existsSync18(GRANT_FILE))
|
|
9148
9365
|
return {};
|
|
9149
9366
|
try {
|
|
9150
9367
|
return JSON.parse(readFileSync12(GRANT_FILE, "utf-8"));
|
|
@@ -9153,8 +9370,8 @@ function readGrants() {
|
|
|
9153
9370
|
}
|
|
9154
9371
|
}
|
|
9155
9372
|
function writeGrants(g) {
|
|
9156
|
-
const dir =
|
|
9157
|
-
if (!
|
|
9373
|
+
const dir = join10(homedir9(), ".claudemesh");
|
|
9374
|
+
if (!existsSync18(dir))
|
|
9158
9375
|
mkdirSync5(dir, { recursive: true });
|
|
9159
9376
|
writeFileSync9(GRANT_FILE, JSON.stringify(g, null, 2), { mode: 384 });
|
|
9160
9377
|
}
|
|
@@ -9312,7 +9529,7 @@ var init_grants = __esm(() => {
|
|
|
9312
9529
|
BROKER_HTTP7 = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
|
|
9313
9530
|
ALL_CAPS = ["read", "dm", "broadcast", "state-read", "state-write", "file-read"];
|
|
9314
9531
|
DEFAULT_CAPS = ["read", "dm", "broadcast", "state-read"];
|
|
9315
|
-
GRANT_FILE =
|
|
9532
|
+
GRANT_FILE = join10(homedir9(), ".claudemesh", "grants.json");
|
|
9316
9533
|
});
|
|
9317
9534
|
|
|
9318
9535
|
// src/mcp/tools/definitions.ts
|
|
@@ -10238,6 +10455,165 @@ var init_definitions = __esm(() => {
|
|
|
10238
10455
|
];
|
|
10239
10456
|
});
|
|
10240
10457
|
|
|
10458
|
+
// src/services/bridge/server.ts
|
|
10459
|
+
import { createServer as createServer2 } from "node:net";
|
|
10460
|
+
import { mkdirSync as mkdirSync6, unlinkSync as unlinkSync2, existsSync as existsSync19, chmodSync as chmodSync5 } from "node:fs";
|
|
10461
|
+
async function resolveTarget2(client, to) {
|
|
10462
|
+
if (to.startsWith("@") || to === "*" || /^[0-9a-f]{64}$/i.test(to)) {
|
|
10463
|
+
return { ok: true, spec: to };
|
|
10464
|
+
}
|
|
10465
|
+
const peers = await client.listPeers();
|
|
10466
|
+
const match = peers.find((p) => p.displayName.toLowerCase() === to.toLowerCase());
|
|
10467
|
+
if (!match) {
|
|
10468
|
+
return {
|
|
10469
|
+
ok: false,
|
|
10470
|
+
error: `peer "${to}" not found. online: ${peers.map((p) => p.displayName).join(", ") || "(none)"}`
|
|
10471
|
+
};
|
|
10472
|
+
}
|
|
10473
|
+
return { ok: true, spec: match.pubkey };
|
|
10474
|
+
}
|
|
10475
|
+
async function dispatch(client, req) {
|
|
10476
|
+
const args = req.args ?? {};
|
|
10477
|
+
try {
|
|
10478
|
+
switch (req.verb) {
|
|
10479
|
+
case "ping": {
|
|
10480
|
+
const peers = await client.listPeers();
|
|
10481
|
+
return {
|
|
10482
|
+
id: req.id,
|
|
10483
|
+
ok: true,
|
|
10484
|
+
result: {
|
|
10485
|
+
mesh: client.meshSlug,
|
|
10486
|
+
ws_status: client.status,
|
|
10487
|
+
peers_online: peers.length,
|
|
10488
|
+
push_buffer: client.pushHistory.length
|
|
10489
|
+
}
|
|
10490
|
+
};
|
|
10491
|
+
}
|
|
10492
|
+
case "peers": {
|
|
10493
|
+
const peers = await client.listPeers();
|
|
10494
|
+
return { id: req.id, ok: true, result: peers };
|
|
10495
|
+
}
|
|
10496
|
+
case "send": {
|
|
10497
|
+
const to = String(args.to ?? "");
|
|
10498
|
+
const message = String(args.message ?? "");
|
|
10499
|
+
const priority = args.priority ?? "next";
|
|
10500
|
+
if (!to || !message) {
|
|
10501
|
+
return { id: req.id, ok: false, error: "send: `to` and `message` required" };
|
|
10502
|
+
}
|
|
10503
|
+
const resolved = await resolveTarget2(client, to);
|
|
10504
|
+
if (!resolved.ok)
|
|
10505
|
+
return { id: req.id, ok: false, error: resolved.error };
|
|
10506
|
+
const result = await client.send(resolved.spec, message, priority);
|
|
10507
|
+
if (!result.ok) {
|
|
10508
|
+
return { id: req.id, ok: false, error: result.error ?? "send failed" };
|
|
10509
|
+
}
|
|
10510
|
+
return {
|
|
10511
|
+
id: req.id,
|
|
10512
|
+
ok: true,
|
|
10513
|
+
result: { messageId: result.messageId, target: resolved.spec }
|
|
10514
|
+
};
|
|
10515
|
+
}
|
|
10516
|
+
case "summary": {
|
|
10517
|
+
const text = String(args.summary ?? "");
|
|
10518
|
+
if (!text)
|
|
10519
|
+
return { id: req.id, ok: false, error: "summary: `summary` required" };
|
|
10520
|
+
await client.setSummary(text);
|
|
10521
|
+
return { id: req.id, ok: true, result: { summary: text } };
|
|
10522
|
+
}
|
|
10523
|
+
case "status_set": {
|
|
10524
|
+
const state = String(args.status ?? "");
|
|
10525
|
+
if (!["idle", "working", "dnd"].includes(state)) {
|
|
10526
|
+
return { id: req.id, ok: false, error: "status_set: must be idle | working | dnd" };
|
|
10527
|
+
}
|
|
10528
|
+
await client.setStatus(state);
|
|
10529
|
+
return { id: req.id, ok: true, result: { status: state } };
|
|
10530
|
+
}
|
|
10531
|
+
case "visible": {
|
|
10532
|
+
const visible = Boolean(args.visible);
|
|
10533
|
+
await client.setVisible(visible);
|
|
10534
|
+
return { id: req.id, ok: true, result: { visible } };
|
|
10535
|
+
}
|
|
10536
|
+
default:
|
|
10537
|
+
return { id: req.id, ok: false, error: `unknown verb: ${req.verb}` };
|
|
10538
|
+
}
|
|
10539
|
+
} catch (err) {
|
|
10540
|
+
return {
|
|
10541
|
+
id: req.id,
|
|
10542
|
+
ok: false,
|
|
10543
|
+
error: err instanceof Error ? err.message : String(err)
|
|
10544
|
+
};
|
|
10545
|
+
}
|
|
10546
|
+
}
|
|
10547
|
+
function handleConnection(socket, client) {
|
|
10548
|
+
const parser = new LineParser;
|
|
10549
|
+
socket.on("data", (chunk) => {
|
|
10550
|
+
const lines = parser.feed(chunk);
|
|
10551
|
+
for (const line of lines) {
|
|
10552
|
+
if (!line.trim())
|
|
10553
|
+
continue;
|
|
10554
|
+
let req;
|
|
10555
|
+
try {
|
|
10556
|
+
req = JSON.parse(line);
|
|
10557
|
+
} catch {
|
|
10558
|
+
continue;
|
|
10559
|
+
}
|
|
10560
|
+
if (!req || typeof req !== "object" || !req.id || !req.verb)
|
|
10561
|
+
continue;
|
|
10562
|
+
dispatch(client, req).then((res) => {
|
|
10563
|
+
try {
|
|
10564
|
+
socket.write(frame(res));
|
|
10565
|
+
} catch {}
|
|
10566
|
+
});
|
|
10567
|
+
}
|
|
10568
|
+
});
|
|
10569
|
+
socket.on("error", () => {});
|
|
10570
|
+
}
|
|
10571
|
+
function startBridgeServer(client) {
|
|
10572
|
+
const path = socketPath(client.meshSlug);
|
|
10573
|
+
const dir = socketDir();
|
|
10574
|
+
if (!existsSync19(dir)) {
|
|
10575
|
+
mkdirSync6(dir, { recursive: true, mode: 448 });
|
|
10576
|
+
}
|
|
10577
|
+
if (existsSync19(path)) {
|
|
10578
|
+
try {
|
|
10579
|
+
unlinkSync2(path);
|
|
10580
|
+
} catch {}
|
|
10581
|
+
}
|
|
10582
|
+
const server = createServer2((socket) => handleConnection(socket, client));
|
|
10583
|
+
try {
|
|
10584
|
+
server.listen(path);
|
|
10585
|
+
} catch (err) {
|
|
10586
|
+
process.stderr.write(`[claudemesh] bridge: failed to bind ${path}: ${String(err)}
|
|
10587
|
+
`);
|
|
10588
|
+
return null;
|
|
10589
|
+
}
|
|
10590
|
+
server.on("error", (err) => {
|
|
10591
|
+
process.stderr.write(`[claudemesh] bridge: ${String(err)}
|
|
10592
|
+
`);
|
|
10593
|
+
});
|
|
10594
|
+
try {
|
|
10595
|
+
chmodSync5(path, 384);
|
|
10596
|
+
} catch {}
|
|
10597
|
+
let stopped = false;
|
|
10598
|
+
return {
|
|
10599
|
+
path,
|
|
10600
|
+
stop() {
|
|
10601
|
+
if (stopped)
|
|
10602
|
+
return;
|
|
10603
|
+
stopped = true;
|
|
10604
|
+
try {
|
|
10605
|
+
server.close();
|
|
10606
|
+
} catch {}
|
|
10607
|
+
try {
|
|
10608
|
+
unlinkSync2(path);
|
|
10609
|
+
} catch {}
|
|
10610
|
+
}
|
|
10611
|
+
};
|
|
10612
|
+
}
|
|
10613
|
+
var init_server = __esm(() => {
|
|
10614
|
+
init_protocol();
|
|
10615
|
+
});
|
|
10616
|
+
|
|
10241
10617
|
// src/mcp/server.ts
|
|
10242
10618
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
10243
10619
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -10803,12 +11179,12 @@ ${peerLines.join(`
|
|
|
10803
11179
|
}
|
|
10804
11180
|
}
|
|
10805
11181
|
try {
|
|
10806
|
-
const { writeFileSync: writeFileSync10, mkdirSync:
|
|
11182
|
+
const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync7, existsSync: existsSync20 } = await import("node:fs");
|
|
10807
11183
|
const { join: joinPath } = await import("node:path");
|
|
10808
|
-
const { homedir:
|
|
10809
|
-
const dir = joinPath(
|
|
10810
|
-
if (!
|
|
10811
|
-
|
|
11184
|
+
const { homedir: homedir10 } = await import("node:os");
|
|
11185
|
+
const dir = joinPath(homedir10(), ".claudemesh");
|
|
11186
|
+
if (!existsSync20(dir))
|
|
11187
|
+
mkdirSync7(dir, { recursive: true });
|
|
10812
11188
|
writeFileSync10(joinPath(dir, "peer-cache.json"), JSON.stringify(statusCache));
|
|
10813
11189
|
} catch {}
|
|
10814
11190
|
return text(sections.join(`
|
|
@@ -11051,17 +11427,17 @@ ${lines.join(`
|
|
|
11051
11427
|
const { path: filePath, name: fileName, tags, to: fileTo } = args ?? {};
|
|
11052
11428
|
if (!filePath)
|
|
11053
11429
|
return text("share_file: `path` required", true);
|
|
11054
|
-
const { existsSync:
|
|
11055
|
-
if (!
|
|
11430
|
+
const { existsSync: existsSync20 } = await import("node:fs");
|
|
11431
|
+
if (!existsSync20(filePath))
|
|
11056
11432
|
return text(`share_file: file not found: ${filePath}`, true);
|
|
11057
11433
|
const client = allClients()[0];
|
|
11058
11434
|
if (!client)
|
|
11059
11435
|
return text("share_file: not connected", true);
|
|
11060
11436
|
if (fileTo) {
|
|
11061
11437
|
const { encryptFile: encryptFile2, sealKeyForPeer: sealKeyForPeer2 } = await Promise.resolve().then(() => (init_file_crypto(), exports_file_crypto));
|
|
11062
|
-
const { readFileSync: readFileSync13, writeFileSync: writeFileSync10, mkdtempSync: mkdtempSync2, unlinkSync:
|
|
11438
|
+
const { readFileSync: readFileSync13, writeFileSync: writeFileSync10, mkdtempSync: mkdtempSync2, unlinkSync: unlinkSync3, rmdirSync } = await import("node:fs");
|
|
11063
11439
|
const { tmpdir: tmpdir2 } = await import("node:os");
|
|
11064
|
-
const { join:
|
|
11440
|
+
const { join: join11, basename } = await import("node:path");
|
|
11065
11441
|
const peers = await client.listPeers();
|
|
11066
11442
|
const targetPeer = peers.find((p) => p.pubkey === fileTo || p.displayName === fileTo);
|
|
11067
11443
|
if (!targetPeer) {
|
|
@@ -11084,8 +11460,8 @@ ${lines.join(`
|
|
|
11084
11460
|
combined.set(ciphertext, nonceBytes.length);
|
|
11085
11461
|
const rawName = fileName ?? basename(filePath);
|
|
11086
11462
|
const baseName = basename(rawName).replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 255);
|
|
11087
|
-
const tmpDir = mkdtempSync2(
|
|
11088
|
-
const tmpPath =
|
|
11463
|
+
const tmpDir = mkdtempSync2(join11(tmpdir2(), "cm-"));
|
|
11464
|
+
const tmpPath = join11(tmpDir, baseName);
|
|
11089
11465
|
writeFileSync10(tmpPath, combined);
|
|
11090
11466
|
try {
|
|
11091
11467
|
const fileId = await client.uploadFile(tmpPath, client.meshId, client.meshSlug, {
|
|
@@ -11101,7 +11477,7 @@ ${lines.join(`
|
|
|
11101
11477
|
return text(`share_file: upload failed — ${e instanceof Error ? e.message : String(e)}`, true);
|
|
11102
11478
|
} finally {
|
|
11103
11479
|
try {
|
|
11104
|
-
|
|
11480
|
+
unlinkSync3(tmpPath);
|
|
11105
11481
|
} catch {}
|
|
11106
11482
|
try {
|
|
11107
11483
|
rmdirSync(tmpDir);
|
|
@@ -11161,9 +11537,9 @@ ${lines.join(`
|
|
|
11161
11537
|
const plaintext = await decryptFile2(ciphertext, nonce, kf);
|
|
11162
11538
|
if (!plaintext)
|
|
11163
11539
|
return text(genericErr, true);
|
|
11164
|
-
const { writeFileSync: writeFileSync11, mkdirSync:
|
|
11540
|
+
const { writeFileSync: writeFileSync11, mkdirSync: mkdirSync8 } = await import("node:fs");
|
|
11165
11541
|
const { dirname: dirname5 } = await import("node:path");
|
|
11166
|
-
|
|
11542
|
+
mkdirSync8(dirname5(save_to), { recursive: true });
|
|
11167
11543
|
writeFileSync11(save_to, plaintext);
|
|
11168
11544
|
return text(`Downloaded and decrypted: ${result.name} → ${save_to}`);
|
|
11169
11545
|
}
|
|
@@ -11174,9 +11550,9 @@ ${lines.join(`
|
|
|
11174
11550
|
}
|
|
11175
11551
|
if (!res.ok)
|
|
11176
11552
|
return text(`get_file: download failed (${res.status})`, true);
|
|
11177
|
-
const { writeFileSync: writeFileSync10, mkdirSync:
|
|
11553
|
+
const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync7 } = await import("node:fs");
|
|
11178
11554
|
const { dirname: dirname4 } = await import("node:path");
|
|
11179
|
-
|
|
11555
|
+
mkdirSync7(dirname4(save_to), { recursive: true });
|
|
11180
11556
|
writeFileSync10(save_to, Buffer.from(await res.arrayBuffer()));
|
|
11181
11557
|
return text(`Downloaded: ${result.name} → ${save_to}`);
|
|
11182
11558
|
}
|
|
@@ -11935,8 +12311,8 @@ ${lines.join(`
|
|
|
11935
12311
|
const entryType = vType ?? "env";
|
|
11936
12312
|
let plaintextBytes;
|
|
11937
12313
|
if (entryType === "file") {
|
|
11938
|
-
const { existsSync:
|
|
11939
|
-
if (!
|
|
12314
|
+
const { existsSync: existsSync20, readFileSync: readFileSync13 } = await import("node:fs");
|
|
12315
|
+
if (!existsSync20(value))
|
|
11940
12316
|
return text(`vault_set: file not found: ${value}`, true);
|
|
11941
12317
|
plaintextBytes = new Uint8Array(readFileSync13(value));
|
|
11942
12318
|
} else {
|
|
@@ -12195,8 +12571,14 @@ ${lines.join(`
|
|
|
12195
12571
|
});
|
|
12196
12572
|
const transport = new StdioServerTransport;
|
|
12197
12573
|
await server.connect(transport);
|
|
12574
|
+
const bridges = [];
|
|
12198
12575
|
startClients(config).then(() => {
|
|
12199
12576
|
wirePushHandlers().catch(() => {});
|
|
12577
|
+
for (const client of allClients()) {
|
|
12578
|
+
const bridge = startBridgeServer(client);
|
|
12579
|
+
if (bridge)
|
|
12580
|
+
bridges.push(bridge);
|
|
12581
|
+
}
|
|
12200
12582
|
}).catch(() => {
|
|
12201
12583
|
wirePushHandlers().catch(() => {});
|
|
12202
12584
|
});
|
|
@@ -12369,6 +12751,11 @@ ${lines.join(`
|
|
|
12369
12751
|
const keepalive = setInterval(() => {}, 1000);
|
|
12370
12752
|
const shutdown = () => {
|
|
12371
12753
|
clearInterval(keepalive);
|
|
12754
|
+
for (const b of bridges) {
|
|
12755
|
+
try {
|
|
12756
|
+
b.stop();
|
|
12757
|
+
} catch {}
|
|
12758
|
+
}
|
|
12372
12759
|
stopAll();
|
|
12373
12760
|
process.exit(0);
|
|
12374
12761
|
};
|
|
@@ -12490,10 +12877,11 @@ async function startServiceProxy(serviceName) {
|
|
|
12490
12877
|
process.on("SIGINT", shutdown);
|
|
12491
12878
|
}
|
|
12492
12879
|
var peerNameCache, peerNameCacheAge = 0, CACHE_TTL_MS = 30000, DEPRECATED_TOOL_HINTS, warnedTools;
|
|
12493
|
-
var
|
|
12880
|
+
var init_server2 = __esm(() => {
|
|
12494
12881
|
init_definitions();
|
|
12495
12882
|
init_facade();
|
|
12496
12883
|
init_facade8();
|
|
12884
|
+
init_server();
|
|
12497
12885
|
peerNameCache = new Map;
|
|
12498
12886
|
DEPRECATED_TOOL_HINTS = {
|
|
12499
12887
|
send_message: "claudemesh send <to> <msg> [--mesh X] [--priority Y]",
|
|
@@ -12537,7 +12925,7 @@ async function runMcp() {
|
|
|
12537
12925
|
process.exit(0);
|
|
12538
12926
|
}
|
|
12539
12927
|
var init_mcp = __esm(() => {
|
|
12540
|
-
|
|
12928
|
+
init_server2();
|
|
12541
12929
|
});
|
|
12542
12930
|
|
|
12543
12931
|
// src/commands/hook.ts
|
|
@@ -12993,12 +13381,12 @@ async function main() {
|
|
|
12993
13381
|
}
|
|
12994
13382
|
case "peers": {
|
|
12995
13383
|
const { runPeers: runPeers2 } = await Promise.resolve().then(() => (init_peers(), exports_peers));
|
|
12996
|
-
await runPeers2({ mesh: flags.mesh, json:
|
|
13384
|
+
await runPeers2({ mesh: flags.mesh, json: flags.json });
|
|
12997
13385
|
break;
|
|
12998
13386
|
}
|
|
12999
13387
|
case "send": {
|
|
13000
13388
|
const { runSend: runSend2 } = await Promise.resolve().then(() => (init_send(), exports_send));
|
|
13001
|
-
await runSend2({}, positionals[0] ?? "", positionals.slice(1).join(" "));
|
|
13389
|
+
await runSend2({ mesh: flags.mesh, priority: flags.priority, json: !!flags.json }, positionals[0] ?? "", positionals.slice(1).join(" "));
|
|
13002
13390
|
break;
|
|
13003
13391
|
}
|
|
13004
13392
|
case "inbox": {
|
|
@@ -13246,4 +13634,4 @@ main().catch((err) => {
|
|
|
13246
13634
|
process.exit(EXIT.INTERNAL_ERROR);
|
|
13247
13635
|
});
|
|
13248
13636
|
|
|
13249
|
-
//# debugId=
|
|
13637
|
+
//# debugId=25926A42D1A4B83764756E2164756E21
|