claudemesh-cli 1.35.1 → 1.37.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 +366 -177
- package/dist/entrypoints/cli.js.map +8 -8
- package/dist/entrypoints/mcp.js +5 -2
- package/dist/entrypoints/mcp.js.map +3 -3
- package/package.json +1 -1
package/dist/entrypoints/cli.js
CHANGED
|
@@ -104,7 +104,7 @@ __export(exports_urls, {
|
|
|
104
104
|
VERSION: () => VERSION,
|
|
105
105
|
URLS: () => URLS
|
|
106
106
|
});
|
|
107
|
-
var URLS, VERSION = "1.
|
|
107
|
+
var URLS, VERSION = "1.37.0", env;
|
|
108
108
|
var init_urls = __esm(() => {
|
|
109
109
|
URLS = {
|
|
110
110
|
BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
|
|
@@ -3668,6 +3668,9 @@ var init_paths2 = __esm(() => {
|
|
|
3668
3668
|
},
|
|
3669
3669
|
get LOG_FILE() {
|
|
3670
3670
|
return join3(this.DAEMON_DIR, "daemon.log");
|
|
3671
|
+
},
|
|
3672
|
+
get SESSIONS_FILE() {
|
|
3673
|
+
return join3(this.DAEMON_DIR, "sessions.json");
|
|
3671
3674
|
}
|
|
3672
3675
|
};
|
|
3673
3676
|
});
|
|
@@ -8195,12 +8198,12 @@ async function runPeers(flags) {
|
|
|
8195
8198
|
for (const slug of slugs) {
|
|
8196
8199
|
try {
|
|
8197
8200
|
const peers = await listPeersForMesh(slug);
|
|
8201
|
+
const visible = flags.all ? peers : peers.filter((p) => p.peerRole !== "control-plane");
|
|
8198
8202
|
if (wantsJson) {
|
|
8199
|
-
const projected = fieldList ?
|
|
8203
|
+
const projected = fieldList ? visible.map((p) => projectFields(p, fieldList)) : visible;
|
|
8200
8204
|
allJson.push({ mesh: slug, peers: projected });
|
|
8201
8205
|
continue;
|
|
8202
8206
|
}
|
|
8203
|
-
const visible = flags.all ? peers : peers.filter((p) => p.peerRole !== "control-plane");
|
|
8204
8207
|
const sorted = visible.slice().sort((a, b) => {
|
|
8205
8208
|
const score = (p) => p.isThisSession ? 0 : p.isSelf ? 1 : 2;
|
|
8206
8209
|
return score(a) - score(b);
|
|
@@ -8274,37 +8277,64 @@ async function runSend(flags, to, message) {
|
|
|
8274
8277
|
}
|
|
8275
8278
|
const priority = flags.priority === "now" ? "now" : flags.priority === "low" ? "low" : "next";
|
|
8276
8279
|
const config = readConfig();
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8285
|
-
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
const
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8280
|
+
let meshSlug = flags.mesh ?? (config.meshes.length === 1 ? config.meshes[0].slug : null);
|
|
8281
|
+
const isDirect = !to.startsWith("@") && !to.startsWith("#") && to !== "*";
|
|
8282
|
+
const isFullPubkey = /^[0-9a-f]{64}$/i.test(to);
|
|
8283
|
+
const isPrefix = /^[0-9a-f]{4,63}$/i.test(to);
|
|
8284
|
+
const isName = isDirect && !isFullPubkey && !isPrefix;
|
|
8285
|
+
if (isDirect && (isPrefix || isName || isFullPubkey && !meshSlug)) {
|
|
8286
|
+
const { tryListPeersViaDaemon: tryListPeersViaDaemon2 } = await Promise.resolve().then(() => (init_daemon_route(), exports_daemon_route));
|
|
8287
|
+
const searchSlugs = meshSlug ? [meshSlug] : config.meshes.map((m) => m.slug);
|
|
8288
|
+
const lower = to.toLowerCase();
|
|
8289
|
+
let daemonReachable2 = false;
|
|
8290
|
+
const matches2 = [];
|
|
8291
|
+
for (const slug of searchSlugs) {
|
|
8292
|
+
const peers = await tryListPeersViaDaemon2(slug);
|
|
8293
|
+
if (peers === null)
|
|
8294
|
+
continue;
|
|
8295
|
+
daemonReachable2 = true;
|
|
8296
|
+
for (const p of peers) {
|
|
8297
|
+
if (p.peerRole === "control-plane")
|
|
8298
|
+
continue;
|
|
8299
|
+
const pk = (p.pubkey ?? "").toLowerCase();
|
|
8300
|
+
const mpk = (p.memberPubkey ?? "").toLowerCase();
|
|
8301
|
+
const dn = p.displayName ?? "?";
|
|
8302
|
+
const hit = isName ? dn.toLowerCase() === lower : pk.startsWith(lower) || mpk.startsWith(lower);
|
|
8303
|
+
if (hit)
|
|
8304
|
+
matches2.push({ slug, pubkey: p.pubkey ?? "", displayName: dn });
|
|
8305
|
+
}
|
|
8306
|
+
}
|
|
8307
|
+
if (daemonReachable2) {
|
|
8308
|
+
const byPubkey = new Map;
|
|
8309
|
+
for (const m of matches2)
|
|
8310
|
+
if (!byPubkey.has(m.pubkey))
|
|
8311
|
+
byPubkey.set(m.pubkey, m);
|
|
8312
|
+
const uniq = [...byPubkey.values()];
|
|
8313
|
+
const meshesHit = [...new Set(uniq.map((m) => m.slug))];
|
|
8314
|
+
if (uniq.length === 0) {
|
|
8315
|
+
if (!isFullPubkey) {
|
|
8316
|
+
render.err(`No peer matches "${to}"${flags.mesh ? ` on mesh "${flags.mesh}"` : " on any joined mesh"}.`);
|
|
8317
|
+
render.hint("Check `claudemesh peer list` (add --mesh <slug> to scope).");
|
|
8318
|
+
process.exit(1);
|
|
8319
|
+
}
|
|
8320
|
+
} else if (uniq.length > 1) {
|
|
8321
|
+
if (meshesHit.length > 1 && !meshSlug) {
|
|
8322
|
+
const where = uniq.map((m) => `${m.displayName} ${m.pubkey.slice(0, 12)}… @${m.slug}`).join(", ");
|
|
8323
|
+
render.err(`"${to}" matches peers on ${meshesHit.length} meshes — pick one with --mesh <slug>.`);
|
|
8324
|
+
render.hint(`candidates: ${where}`);
|
|
8325
|
+
process.exit(1);
|
|
8326
|
+
}
|
|
8327
|
+
const candidates = uniq.map((m) => `${m.displayName} ${m.pubkey.slice(0, 16)}…`).join(", ");
|
|
8328
|
+
render.err(`Ambiguous ${isName ? "name" : "prefix"} "${to}" — matches ${uniq.length} peers.`);
|
|
8302
8329
|
render.hint(`candidates: ${candidates}`);
|
|
8303
8330
|
render.hint("Use a longer prefix or paste the full 64-char pubkey.");
|
|
8304
8331
|
process.exit(1);
|
|
8332
|
+
} else {
|
|
8333
|
+
meshSlug = uniq[0].slug;
|
|
8334
|
+
if (!isFullPubkey)
|
|
8335
|
+
to = uniq[0].pubkey;
|
|
8305
8336
|
}
|
|
8306
|
-
|
|
8307
|
-
} catch {}
|
|
8337
|
+
}
|
|
8308
8338
|
}
|
|
8309
8339
|
if (meshSlug) {
|
|
8310
8340
|
const joined = config.meshes.find((m) => m.slug === meshSlug);
|
|
@@ -8327,7 +8357,7 @@ async function runSend(flags, to, message) {
|
|
|
8327
8357
|
return false;
|
|
8328
8358
|
if (ownSessionPk && r.pubkey.toLowerCase() === ownSessionPk)
|
|
8329
8359
|
return false;
|
|
8330
|
-
if (r.channel === "claudemesh-daemon")
|
|
8360
|
+
if (r.peerRole === "control-plane" || r.channel === "claudemesh-daemon")
|
|
8331
8361
|
return false;
|
|
8332
8362
|
return r.memberPubkey?.toLowerCase() === to.toLowerCase();
|
|
8333
8363
|
});
|
|
@@ -8374,14 +8404,40 @@ async function runSend(flags, to, message) {
|
|
|
8374
8404
|
}
|
|
8375
8405
|
}
|
|
8376
8406
|
}
|
|
8407
|
+
if (flags.self) {
|
|
8408
|
+
render.warn("--self had no effect: it only applies when the target is your own member pubkey (fan-out to your sibling sessions). Sending to this specific pubkey directly.");
|
|
8409
|
+
}
|
|
8410
|
+
let recipientOnline = null;
|
|
8411
|
+
let recipientName;
|
|
8412
|
+
if (isDirect && meshSlug) {
|
|
8413
|
+
const { tryListPeersViaDaemon: tryListPeersViaDaemon2 } = await Promise.resolve().then(() => (init_daemon_route(), exports_daemon_route));
|
|
8414
|
+
const peers = await tryListPeersViaDaemon2(meshSlug);
|
|
8415
|
+
if (peers !== null) {
|
|
8416
|
+
const lower = to.toLowerCase();
|
|
8417
|
+
const match = peers.find((p) => {
|
|
8418
|
+
const r = p;
|
|
8419
|
+
if (r.peerRole === "control-plane")
|
|
8420
|
+
return false;
|
|
8421
|
+
return r.pubkey?.toLowerCase() === lower || r.memberPubkey?.toLowerCase() === lower;
|
|
8422
|
+
});
|
|
8423
|
+
recipientOnline = !!match;
|
|
8424
|
+
recipientName = match ? match.displayName : undefined;
|
|
8425
|
+
}
|
|
8426
|
+
}
|
|
8427
|
+
const offlineHint = "Session pubkeys are ephemeral — a key from an ended session never reconnects, so the message can't be delivered. Re-fetch a live target with `claudemesh peer list --json`.";
|
|
8377
8428
|
{
|
|
8378
8429
|
const dr = await trySendViaDaemon({ to, message, priority, expectedMesh: meshSlug ?? undefined });
|
|
8379
8430
|
if (dr !== null) {
|
|
8380
8431
|
if (dr.ok) {
|
|
8381
|
-
if (flags.json)
|
|
8382
|
-
console.log(JSON.stringify({ ok: true, messageId: dr.messageId, target: to, via: "daemon", duplicate: !!dr.duplicate }));
|
|
8383
|
-
else
|
|
8384
|
-
render.
|
|
8432
|
+
if (flags.json) {
|
|
8433
|
+
console.log(JSON.stringify({ ok: true, messageId: dr.messageId, target: to, via: "daemon", duplicate: !!dr.duplicate, status: dr.status, recipientOnline }));
|
|
8434
|
+
} else if (recipientOnline === false) {
|
|
8435
|
+
render.warn(`queued for ${recipientName ?? to.slice(0, 16) + "…"} — no connected peer matches this key on "${meshSlug}".`);
|
|
8436
|
+
render.hint(offlineHint);
|
|
8437
|
+
} else {
|
|
8438
|
+
const who = recipientName ? `${recipientName} (${to.slice(0, 16)}…)` : to;
|
|
8439
|
+
render.ok(`sent to ${who}${recipientOnline === true ? " (online)" : " (daemon)"}`, dr.messageId ? dim(dr.messageId.slice(0, 8)) : undefined);
|
|
8440
|
+
}
|
|
8385
8441
|
return;
|
|
8386
8442
|
}
|
|
8387
8443
|
if (flags.json)
|
|
@@ -8391,7 +8447,7 @@ async function runSend(flags, to, message) {
|
|
|
8391
8447
|
process.exit(1);
|
|
8392
8448
|
}
|
|
8393
8449
|
}
|
|
8394
|
-
await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
|
|
8450
|
+
await withMesh({ meshSlug: meshSlug ?? flags.mesh ?? null }, async (client) => {
|
|
8395
8451
|
let targetSpec = to;
|
|
8396
8452
|
if (to.startsWith("#") && !/^#[0-9a-z_-]{20,}$/i.test(to)) {
|
|
8397
8453
|
const name = to.slice(1);
|
|
@@ -8416,9 +8472,13 @@ async function runSend(flags, to, message) {
|
|
|
8416
8472
|
const result = await client.send(targetSpec, message, priority);
|
|
8417
8473
|
if (result.ok) {
|
|
8418
8474
|
if (flags.json) {
|
|
8419
|
-
console.log(JSON.stringify({ ok: true, messageId: result.messageId, target: to }));
|
|
8475
|
+
console.log(JSON.stringify({ ok: true, messageId: result.messageId, target: to, recipientOnline }));
|
|
8476
|
+
} else if (recipientOnline === false) {
|
|
8477
|
+
render.warn(`queued for ${recipientName ?? to} — no connected peer matches this key on "${meshSlug ?? flags.mesh ?? "default"}".`);
|
|
8478
|
+
render.hint(offlineHint);
|
|
8420
8479
|
} else {
|
|
8421
|
-
|
|
8480
|
+
const who = recipientName ? `${recipientName} (${to.slice(0, 16)}…)` : to;
|
|
8481
|
+
render.ok(`sent to ${who}${recipientOnline === true ? " (online)" : ""}`, result.messageId ? dim(result.messageId.slice(0, 8)) : undefined);
|
|
8422
8482
|
}
|
|
8423
8483
|
} else {
|
|
8424
8484
|
if (flags.json) {
|
|
@@ -9924,6 +9984,12 @@ function bindSseStream(res, bus, filter = {}) {
|
|
|
9924
9984
|
}
|
|
9925
9985
|
|
|
9926
9986
|
// src/daemon/process-info.ts
|
|
9987
|
+
var exports_process_info = {};
|
|
9988
|
+
__export(exports_process_info, {
|
|
9989
|
+
isPidAlive: () => isPidAlive,
|
|
9990
|
+
getProcessStartTimes: () => getProcessStartTimes,
|
|
9991
|
+
getProcessStartTime: () => getProcessStartTime
|
|
9992
|
+
});
|
|
9927
9993
|
import { execFile as execFile2 } from "node:child_process";
|
|
9928
9994
|
import { promisify } from "node:util";
|
|
9929
9995
|
async function getProcessStartTime(pid) {
|
|
@@ -9979,6 +10045,37 @@ var init_process_info = __esm(() => {
|
|
|
9979
10045
|
});
|
|
9980
10046
|
|
|
9981
10047
|
// src/daemon/session-registry.ts
|
|
10048
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync10, renameSync as renameSync3, writeFileSync as writeFileSync11 } from "node:fs";
|
|
10049
|
+
import { dirname as dirname5 } from "node:path";
|
|
10050
|
+
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
10051
|
+
function toPersisted(info) {
|
|
10052
|
+
const { presence: _presence, ...rest } = info;
|
|
10053
|
+
return rest;
|
|
10054
|
+
}
|
|
10055
|
+
function setRegistryPersistence(path) {
|
|
10056
|
+
persistPath = path;
|
|
10057
|
+
}
|
|
10058
|
+
function persist() {
|
|
10059
|
+
if (!persistPath)
|
|
10060
|
+
return;
|
|
10061
|
+
try {
|
|
10062
|
+
mkdirSync7(dirname5(persistPath), { recursive: true, mode: 448 });
|
|
10063
|
+
const rows = [...byToken.values()].map(toPersisted);
|
|
10064
|
+
const tmp = `${persistPath}.${randomBytes7(6).toString("hex")}.tmp`;
|
|
10065
|
+
writeFileSync11(tmp, JSON.stringify({ version: 1, sessions: rows }), { mode: 384 });
|
|
10066
|
+
renameSync3(tmp, persistPath);
|
|
10067
|
+
} catch {}
|
|
10068
|
+
}
|
|
10069
|
+
function readPersistedSessions(path) {
|
|
10070
|
+
try {
|
|
10071
|
+
if (!existsSync11(path))
|
|
10072
|
+
return [];
|
|
10073
|
+
const parsed = JSON.parse(readFileSync10(path, "utf8"));
|
|
10074
|
+
return Array.isArray(parsed.sessions) ? parsed.sessions : [];
|
|
10075
|
+
} catch {
|
|
10076
|
+
return [];
|
|
10077
|
+
}
|
|
10078
|
+
}
|
|
9982
10079
|
function startReaper() {
|
|
9983
10080
|
if (reaperHandle)
|
|
9984
10081
|
return;
|
|
@@ -10004,6 +10101,7 @@ function registerSession(info) {
|
|
|
10004
10101
|
const stored = { ...info, registeredAt: Date.now() };
|
|
10005
10102
|
byToken.set(info.token, stored);
|
|
10006
10103
|
bySessionId.set(info.sessionId, info.token);
|
|
10104
|
+
persist();
|
|
10007
10105
|
try {
|
|
10008
10106
|
hooks.onRegister?.(stored);
|
|
10009
10107
|
} catch {}
|
|
@@ -10020,6 +10118,7 @@ async function captureStartTimeAsync(token, pid) {
|
|
|
10020
10118
|
if (!entry || entry.pid !== pid)
|
|
10021
10119
|
return;
|
|
10022
10120
|
entry.startTime = lstart;
|
|
10121
|
+
persist();
|
|
10023
10122
|
}
|
|
10024
10123
|
function deregisterByToken(token) {
|
|
10025
10124
|
const entry = byToken.get(token);
|
|
@@ -10028,6 +10127,7 @@ function deregisterByToken(token) {
|
|
|
10028
10127
|
byToken.delete(token);
|
|
10029
10128
|
if (bySessionId.get(entry.sessionId) === token)
|
|
10030
10129
|
bySessionId.delete(entry.sessionId);
|
|
10130
|
+
persist();
|
|
10031
10131
|
try {
|
|
10032
10132
|
hooks.onDeregister?.(entry);
|
|
10033
10133
|
} catch {}
|
|
@@ -10079,7 +10179,7 @@ async function reapDead() {
|
|
|
10079
10179
|
for (const t of dead)
|
|
10080
10180
|
deregisterByToken(t);
|
|
10081
10181
|
}
|
|
10082
|
-
var TTL_MS, REAPER_INTERVAL_MS, byToken, bySessionId, hooks, reaperHandle = null;
|
|
10182
|
+
var TTL_MS, REAPER_INTERVAL_MS, byToken, bySessionId, hooks, reaperHandle = null, persistPath = null;
|
|
10083
10183
|
var init_session_registry = __esm(() => {
|
|
10084
10184
|
init_process_info();
|
|
10085
10185
|
TTL_MS = 24 * 60 * 60 * 1000;
|
|
@@ -10091,7 +10191,7 @@ var init_session_registry = __esm(() => {
|
|
|
10091
10191
|
|
|
10092
10192
|
// src/daemon/ipc/server.ts
|
|
10093
10193
|
import { createServer as createServer2 } from "node:http";
|
|
10094
|
-
import { chmodSync as chmodSync3, existsSync as
|
|
10194
|
+
import { chmodSync as chmodSync3, existsSync as existsSync12, unlinkSync as unlinkSync4 } from "node:fs";
|
|
10095
10195
|
import { timingSafeEqual } from "node:crypto";
|
|
10096
10196
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
10097
10197
|
function startIpcServer(opts) {
|
|
@@ -10107,7 +10207,7 @@ function startIpcServer(opts) {
|
|
|
10107
10207
|
meshConfigs: opts.meshConfigs,
|
|
10108
10208
|
onPendingInserted: opts.onPendingInserted
|
|
10109
10209
|
});
|
|
10110
|
-
if (
|
|
10210
|
+
if (existsSync12(DAEMON_PATHS.SOCK_FILE)) {
|
|
10111
10211
|
try {
|
|
10112
10212
|
unlinkSync4(DAEMON_PATHS.SOCK_FILE);
|
|
10113
10213
|
} catch {}
|
|
@@ -10934,16 +11034,16 @@ function parseSendRequest(body, idempotencyHeader) {
|
|
|
10934
11034
|
}
|
|
10935
11035
|
async function resolveAndEncrypt(req, broker, meshSecretKey, meshSlug) {
|
|
10936
11036
|
const { encryptDirect: encryptDirect2 } = await Promise.resolve().then(() => (init_box(), exports_box));
|
|
10937
|
-
const { randomBytes:
|
|
11037
|
+
const { randomBytes: randomBytes8 } = await import("node:crypto");
|
|
10938
11038
|
const to = req.to.trim();
|
|
10939
11039
|
if (to.startsWith("#") && /^#[0-9a-z_-]{20,}$/i.test(to)) {
|
|
10940
11040
|
const ciphertext = Buffer.from(req.message, "utf8").toString("base64");
|
|
10941
|
-
const nonce =
|
|
11041
|
+
const nonce = randomBytes8(24).toString("base64");
|
|
10942
11042
|
return { target_spec: to, ciphertext, nonce, mesh: meshSlug ?? "" };
|
|
10943
11043
|
}
|
|
10944
11044
|
if (to.startsWith("@") || to === "*") {
|
|
10945
11045
|
const ciphertext = Buffer.from(req.message, "utf8").toString("base64");
|
|
10946
|
-
const nonce =
|
|
11046
|
+
const nonce = randomBytes8(24).toString("base64");
|
|
10947
11047
|
return { target_spec: to, ciphertext, nonce, mesh: meshSlug ?? "" };
|
|
10948
11048
|
}
|
|
10949
11049
|
if (/^[0-9a-f]{64}$/i.test(to)) {
|
|
@@ -11635,13 +11735,23 @@ class SessionBrokerClient {
|
|
|
11635
11735
|
sessionPubkey: this.opts.sessionPubkey,
|
|
11636
11736
|
sessionSecretKey: this.opts.sessionSecretKey
|
|
11637
11737
|
});
|
|
11738
|
+
let parentAttestation = this.opts.parentAttestation;
|
|
11739
|
+
try {
|
|
11740
|
+
parentAttestation = await signParentAttestation({
|
|
11741
|
+
parentMemberPubkey: this.opts.mesh.pubkey,
|
|
11742
|
+
parentSecretKey: this.opts.mesh.secretKey,
|
|
11743
|
+
sessionPubkey: this.opts.sessionPubkey
|
|
11744
|
+
});
|
|
11745
|
+
} catch (e) {
|
|
11746
|
+
this.log("warn", "parent attestation re-mint failed; reusing stored token (may be expired)", { err: String(e) });
|
|
11747
|
+
}
|
|
11638
11748
|
return {
|
|
11639
11749
|
type: "session_hello",
|
|
11640
11750
|
meshId: this.opts.mesh.meshId,
|
|
11641
11751
|
parentMemberId: this.opts.mesh.memberId,
|
|
11642
11752
|
parentMemberPubkey: this.opts.mesh.pubkey,
|
|
11643
11753
|
sessionPubkey: this.opts.sessionPubkey,
|
|
11644
|
-
parentAttestation
|
|
11754
|
+
parentAttestation,
|
|
11645
11755
|
displayName: this.opts.displayName,
|
|
11646
11756
|
sessionId: this.opts.sessionId,
|
|
11647
11757
|
pid: this.opts.pid,
|
|
@@ -11964,8 +12074,8 @@ function bufferToHex(b) {
|
|
|
11964
12074
|
return s;
|
|
11965
12075
|
}
|
|
11966
12076
|
async function randomNonce2() {
|
|
11967
|
-
const { randomBytes:
|
|
11968
|
-
return
|
|
12077
|
+
const { randomBytes: randomBytes8 } = await import("node:crypto");
|
|
12078
|
+
return randomBytes8(24).toString("base64");
|
|
11969
12079
|
}
|
|
11970
12080
|
function defaultLog4(level, msg, meta) {
|
|
11971
12081
|
const line = JSON.stringify({ level, msg, ...meta, ts: new Date().toISOString() });
|
|
@@ -12140,7 +12250,7 @@ __export(exports_identity, {
|
|
|
12140
12250
|
__resetHostIdCacheForTests: () => __resetHostIdCacheForTests,
|
|
12141
12251
|
__computeV1FingerprintForTests: () => __computeV1FingerprintForTests
|
|
12142
12252
|
});
|
|
12143
|
-
import { existsSync as
|
|
12253
|
+
import { existsSync as existsSync13, readFileSync as readFileSync11, writeFileSync as writeFileSync12 } from "node:fs";
|
|
12144
12254
|
import { join as join8 } from "node:path";
|
|
12145
12255
|
import { createHash as createHash2 } from "node:crypto";
|
|
12146
12256
|
import { execFileSync } from "node:child_process";
|
|
@@ -12161,13 +12271,13 @@ function computeCurrentFingerprint() {
|
|
|
12161
12271
|
}
|
|
12162
12272
|
function checkFingerprint() {
|
|
12163
12273
|
const current = computeCurrentFingerprint();
|
|
12164
|
-
if (!
|
|
12165
|
-
|
|
12274
|
+
if (!existsSync13(path())) {
|
|
12275
|
+
writeFileSync12(path(), JSON.stringify(current, null, 2), { mode: 384 });
|
|
12166
12276
|
return { result: "first_run", current };
|
|
12167
12277
|
}
|
|
12168
12278
|
let stored;
|
|
12169
12279
|
try {
|
|
12170
|
-
stored = JSON.parse(
|
|
12280
|
+
stored = JSON.parse(readFileSync11(path(), "utf8"));
|
|
12171
12281
|
} catch {
|
|
12172
12282
|
return { result: "unavailable", current };
|
|
12173
12283
|
}
|
|
@@ -12175,7 +12285,7 @@ function checkFingerprint() {
|
|
|
12175
12285
|
if (stored.fingerprint === current.fingerprint)
|
|
12176
12286
|
return { result: "match", current, stored };
|
|
12177
12287
|
if (stored.host_id && stored.host_id === current.host_id) {
|
|
12178
|
-
|
|
12288
|
+
writeFileSync12(path(), JSON.stringify(current, null, 2), { mode: 384 });
|
|
12179
12289
|
return { result: "match", current, stored };
|
|
12180
12290
|
}
|
|
12181
12291
|
return { result: "mismatch", current, stored };
|
|
@@ -12183,7 +12293,7 @@ function checkFingerprint() {
|
|
|
12183
12293
|
if (stored.schema_version === 1) {
|
|
12184
12294
|
const v1 = computeCurrentFingerprintV1();
|
|
12185
12295
|
if (stored.fingerprint === v1.fingerprint) {
|
|
12186
|
-
|
|
12296
|
+
writeFileSync12(path(), JSON.stringify(current, null, 2), { mode: 384 });
|
|
12187
12297
|
return { result: "match", current, stored };
|
|
12188
12298
|
}
|
|
12189
12299
|
return { result: "mismatch", current, stored };
|
|
@@ -12192,7 +12302,7 @@ function checkFingerprint() {
|
|
|
12192
12302
|
}
|
|
12193
12303
|
function acceptCurrentHost() {
|
|
12194
12304
|
const current = computeCurrentFingerprint();
|
|
12195
|
-
|
|
12305
|
+
writeFileSync12(path(), JSON.stringify(current, null, 2), { mode: 384 });
|
|
12196
12306
|
return current;
|
|
12197
12307
|
}
|
|
12198
12308
|
function fingerprintV2(host_id, stable_mac) {
|
|
@@ -12242,7 +12352,7 @@ function readHostIdV1() {
|
|
|
12242
12352
|
if (process.platform === "linux") {
|
|
12243
12353
|
for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
12244
12354
|
try {
|
|
12245
|
-
const raw =
|
|
12355
|
+
const raw = readFileSync11(p, "utf8").trim();
|
|
12246
12356
|
if (raw)
|
|
12247
12357
|
return `linux:${raw}`;
|
|
12248
12358
|
} catch {}
|
|
@@ -12288,7 +12398,7 @@ function readHostIdV2Uncached() {
|
|
|
12288
12398
|
if (process.platform === "linux") {
|
|
12289
12399
|
for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
12290
12400
|
try {
|
|
12291
|
-
const raw =
|
|
12401
|
+
const raw = readFileSync11(p, "utf8").trim();
|
|
12292
12402
|
if (raw)
|
|
12293
12403
|
return `linux:${raw}`;
|
|
12294
12404
|
} catch {}
|
|
@@ -12331,23 +12441,23 @@ var init_identity = __esm(() => {
|
|
|
12331
12441
|
});
|
|
12332
12442
|
|
|
12333
12443
|
// src/daemon/run.ts
|
|
12334
|
-
import { existsSync as
|
|
12444
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync8, readFileSync as readFileSync12 } from "node:fs";
|
|
12335
12445
|
function detectContainer() {
|
|
12336
12446
|
if (process.env.KUBERNETES_SERVICE_HOST)
|
|
12337
12447
|
return true;
|
|
12338
12448
|
if (process.env.CONTAINER === "1")
|
|
12339
12449
|
return true;
|
|
12340
12450
|
try {
|
|
12341
|
-
if (
|
|
12451
|
+
if (existsSync14("/.dockerenv"))
|
|
12342
12452
|
return true;
|
|
12343
|
-
const cg =
|
|
12453
|
+
const cg = readFileSync12("/proc/1/cgroup", "utf8");
|
|
12344
12454
|
if (/(docker|kubepods|containerd)/.test(cg))
|
|
12345
12455
|
return true;
|
|
12346
12456
|
} catch {}
|
|
12347
12457
|
return false;
|
|
12348
12458
|
}
|
|
12349
12459
|
async function runDaemon(opts = {}) {
|
|
12350
|
-
|
|
12460
|
+
mkdirSync8(DAEMON_PATHS.DAEMON_DIR, { recursive: true, mode: 448 });
|
|
12351
12461
|
const lock = acquireSingletonLock();
|
|
12352
12462
|
if (lock.result === "already-running") {
|
|
12353
12463
|
process.stderr.write(`daemon already running (pid ${lock.pid})
|
|
@@ -12549,6 +12659,85 @@ async function runDaemon(opts = {}) {
|
|
|
12549
12659
|
}
|
|
12550
12660
|
});
|
|
12551
12661
|
startReaper();
|
|
12662
|
+
try {
|
|
12663
|
+
const persisted = readPersistedSessions(DAEMON_PATHS.SESSIONS_FILE);
|
|
12664
|
+
if (persisted.length > 0) {
|
|
12665
|
+
const { loadOrCreateSessionKeypair: loadOrCreateSessionKeypair2 } = await Promise.resolve().then(() => (init_keypair_store(), exports_keypair_store));
|
|
12666
|
+
const { signParentAttestation: signParentAttestation2 } = await Promise.resolve().then(() => (init_session_hello_sig(), exports_session_hello_sig));
|
|
12667
|
+
const { isPidAlive: isPidAlive2, getProcessStartTimes: getProcessStartTimes2 } = await Promise.resolve().then(() => (init_process_info(), exports_process_info));
|
|
12668
|
+
const liveStartTimes = await getProcessStartTimes2(persisted.map((p) => p.pid)).catch(() => new Map);
|
|
12669
|
+
let revived = 0;
|
|
12670
|
+
for (const s of persisted) {
|
|
12671
|
+
if (!isPidAlive2(s.pid))
|
|
12672
|
+
continue;
|
|
12673
|
+
if (s.startTime !== undefined) {
|
|
12674
|
+
const live = liveStartTimes.get(s.pid);
|
|
12675
|
+
if (live !== undefined && live !== s.startTime)
|
|
12676
|
+
continue;
|
|
12677
|
+
}
|
|
12678
|
+
const meshConfig = meshConfigs.get(s.mesh);
|
|
12679
|
+
if (!meshConfig)
|
|
12680
|
+
continue;
|
|
12681
|
+
try {
|
|
12682
|
+
const kp = await loadOrCreateSessionKeypair2(meshConfig.slug, s.sessionId);
|
|
12683
|
+
const att = await signParentAttestation2({
|
|
12684
|
+
parentMemberPubkey: meshConfig.pubkey,
|
|
12685
|
+
parentSecretKey: meshConfig.secretKey,
|
|
12686
|
+
sessionPubkey: kp.publicKey
|
|
12687
|
+
});
|
|
12688
|
+
registerSession({
|
|
12689
|
+
token: s.token,
|
|
12690
|
+
sessionId: s.sessionId,
|
|
12691
|
+
mesh: s.mesh,
|
|
12692
|
+
displayName: s.displayName,
|
|
12693
|
+
pid: s.pid,
|
|
12694
|
+
...s.cwd ? { cwd: s.cwd } : {},
|
|
12695
|
+
...s.role ? { role: s.role } : {},
|
|
12696
|
+
...s.groups ? { groups: s.groups } : {},
|
|
12697
|
+
...s.startTime ? { startTime: s.startTime } : {},
|
|
12698
|
+
presence: {
|
|
12699
|
+
sessionPubkey: kp.publicKey,
|
|
12700
|
+
sessionSecretKey: kp.secretKey,
|
|
12701
|
+
parentAttestation: {
|
|
12702
|
+
sessionPubkey: att.sessionPubkey,
|
|
12703
|
+
parentMemberPubkey: att.parentMemberPubkey,
|
|
12704
|
+
expiresAt: att.expiresAt,
|
|
12705
|
+
signature: att.signature
|
|
12706
|
+
}
|
|
12707
|
+
}
|
|
12708
|
+
});
|
|
12709
|
+
revived++;
|
|
12710
|
+
} catch (err) {
|
|
12711
|
+
process.stderr.write(JSON.stringify({
|
|
12712
|
+
level: "warn",
|
|
12713
|
+
msg: "session_rehydrate_failed",
|
|
12714
|
+
token: s.token.slice(0, 8),
|
|
12715
|
+
mesh: s.mesh,
|
|
12716
|
+
err: String(err),
|
|
12717
|
+
ts: new Date().toISOString()
|
|
12718
|
+
}) + `
|
|
12719
|
+
`);
|
|
12720
|
+
}
|
|
12721
|
+
}
|
|
12722
|
+
process.stderr.write(JSON.stringify({
|
|
12723
|
+
level: "info",
|
|
12724
|
+
msg: "sessions_rehydrated",
|
|
12725
|
+
revived,
|
|
12726
|
+
persisted: persisted.length,
|
|
12727
|
+
ts: new Date().toISOString()
|
|
12728
|
+
}) + `
|
|
12729
|
+
`);
|
|
12730
|
+
}
|
|
12731
|
+
} catch (err) {
|
|
12732
|
+
process.stderr.write(JSON.stringify({
|
|
12733
|
+
level: "warn",
|
|
12734
|
+
msg: "session_rehydrate_scan_failed",
|
|
12735
|
+
err: String(err),
|
|
12736
|
+
ts: new Date().toISOString()
|
|
12737
|
+
}) + `
|
|
12738
|
+
`);
|
|
12739
|
+
}
|
|
12740
|
+
setRegistryPersistence(DAEMON_PATHS.SESSIONS_FILE);
|
|
12552
12741
|
const ipc2 = startIpcServer({
|
|
12553
12742
|
localToken,
|
|
12554
12743
|
tcpEnabled,
|
|
@@ -12637,10 +12826,10 @@ __export(exports_service_install, {
|
|
|
12637
12826
|
installService: () => installService,
|
|
12638
12827
|
detectPlatform: () => detectPlatform
|
|
12639
12828
|
});
|
|
12640
|
-
import { existsSync as
|
|
12829
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync9, writeFileSync as writeFileSync13, unlinkSync as unlinkSync5, readFileSync as readFileSync13 } from "node:fs";
|
|
12641
12830
|
import { execSync as execSync2 } from "node:child_process";
|
|
12642
12831
|
import { homedir as homedir8 } from "node:os";
|
|
12643
|
-
import { join as join9, dirname as
|
|
12832
|
+
import { join as join9, dirname as dirname6 } from "node:path";
|
|
12644
12833
|
function detectPlatform() {
|
|
12645
12834
|
if (process.platform === "darwin")
|
|
12646
12835
|
return "darwin";
|
|
@@ -12658,10 +12847,10 @@ function installService(args) {
|
|
|
12658
12847
|
if (isCi() && !args.allowCi) {
|
|
12659
12848
|
throw new Error("Refusing to install persistent service in CI; pass --allow-ci-persistent to override.");
|
|
12660
12849
|
}
|
|
12661
|
-
if (!
|
|
12850
|
+
if (!existsSync15(args.binaryPath)) {
|
|
12662
12851
|
throw new Error(`binary not found at ${args.binaryPath}`);
|
|
12663
12852
|
}
|
|
12664
|
-
|
|
12853
|
+
mkdirSync9(DAEMON_PATHS.DAEMON_DIR, { recursive: true, mode: 448 });
|
|
12665
12854
|
if (platform5 === "darwin")
|
|
12666
12855
|
return installDarwin(args);
|
|
12667
12856
|
return installLinux(args);
|
|
@@ -12674,7 +12863,7 @@ function uninstallService() {
|
|
|
12674
12863
|
try {
|
|
12675
12864
|
execSync2(`launchctl bootout gui/$(id -u)/${SERVICE_LABEL2}`, { stdio: "ignore" });
|
|
12676
12865
|
} catch {}
|
|
12677
|
-
if (
|
|
12866
|
+
if (existsSync15(p)) {
|
|
12678
12867
|
unlinkSync5(p);
|
|
12679
12868
|
removed.push(p);
|
|
12680
12869
|
}
|
|
@@ -12683,7 +12872,7 @@ function uninstallService() {
|
|
|
12683
12872
|
try {
|
|
12684
12873
|
execSync2(`systemctl --user disable --now ${SYSTEMD_UNIT2}`, { stdio: "ignore" });
|
|
12685
12874
|
} catch {}
|
|
12686
|
-
if (
|
|
12875
|
+
if (existsSync15(p)) {
|
|
12687
12876
|
unlinkSync5(p);
|
|
12688
12877
|
removed.push(p);
|
|
12689
12878
|
}
|
|
@@ -12695,7 +12884,7 @@ function darwinPlistPath() {
|
|
|
12695
12884
|
}
|
|
12696
12885
|
function installDarwin(args) {
|
|
12697
12886
|
const plist = darwinPlistPath();
|
|
12698
|
-
|
|
12887
|
+
mkdirSync9(dirname6(plist), { recursive: true });
|
|
12699
12888
|
const log2 = DAEMON_PATHS.LOG_FILE;
|
|
12700
12889
|
const nodeBin = process.execPath;
|
|
12701
12890
|
const meshArgs = [
|
|
@@ -12738,14 +12927,14 @@ function installDarwin(args) {
|
|
|
12738
12927
|
</dict>
|
|
12739
12928
|
</plist>
|
|
12740
12929
|
`;
|
|
12741
|
-
|
|
12930
|
+
writeFileSync13(plist, xml, { mode: 420 });
|
|
12742
12931
|
try {
|
|
12743
12932
|
execSync2(`launchctl bootout gui/$(id -u)/${SERVICE_LABEL2}`, { stdio: "ignore" });
|
|
12744
12933
|
} catch {}
|
|
12745
12934
|
try {
|
|
12746
12935
|
const pidPath = DAEMON_PATHS.PID_FILE;
|
|
12747
|
-
if (
|
|
12748
|
-
const pid = parseInt(
|
|
12936
|
+
if (existsSync15(pidPath)) {
|
|
12937
|
+
const pid = parseInt(readFileSync13(pidPath, "utf8").trim(), 10);
|
|
12749
12938
|
if (Number.isFinite(pid) && pid > 0) {
|
|
12750
12939
|
try {
|
|
12751
12940
|
process.kill(pid, "SIGTERM");
|
|
@@ -12764,7 +12953,7 @@ function linuxUnitPath() {
|
|
|
12764
12953
|
}
|
|
12765
12954
|
function installLinux(args) {
|
|
12766
12955
|
const unit = linuxUnitPath();
|
|
12767
|
-
|
|
12956
|
+
mkdirSync9(dirname6(unit), { recursive: true });
|
|
12768
12957
|
const nodeBin = process.execPath;
|
|
12769
12958
|
const execArgs = [
|
|
12770
12959
|
"daemon",
|
|
@@ -12790,14 +12979,14 @@ Environment=PATH=/usr/local/bin:/usr/bin:/bin
|
|
|
12790
12979
|
[Install]
|
|
12791
12980
|
WantedBy=default.target
|
|
12792
12981
|
`;
|
|
12793
|
-
|
|
12982
|
+
writeFileSync13(unit, content, { mode: 420 });
|
|
12794
12983
|
try {
|
|
12795
12984
|
execSync2(`systemctl --user stop ${SYSTEMD_UNIT2}`, { stdio: "ignore" });
|
|
12796
12985
|
} catch {}
|
|
12797
12986
|
try {
|
|
12798
12987
|
const pidPath = DAEMON_PATHS.PID_FILE;
|
|
12799
|
-
if (
|
|
12800
|
-
const pid = parseInt(
|
|
12988
|
+
if (existsSync15(pidPath)) {
|
|
12989
|
+
const pid = parseInt(readFileSync13(pidPath, "utf8").trim(), 10);
|
|
12801
12990
|
if (Number.isFinite(pid) && pid > 0) {
|
|
12802
12991
|
try {
|
|
12803
12992
|
process.kill(pid, "SIGTERM");
|
|
@@ -12824,10 +13013,10 @@ function readInstalledUnit() {
|
|
|
12824
13013
|
if (!platform5)
|
|
12825
13014
|
return { platform: null, path: null, content: null };
|
|
12826
13015
|
const path2 = platform5 === "darwin" ? darwinPlistPath() : linuxUnitPath();
|
|
12827
|
-
if (!
|
|
13016
|
+
if (!existsSync15(path2))
|
|
12828
13017
|
return { platform: platform5, path: null, content: null };
|
|
12829
13018
|
try {
|
|
12830
|
-
return { platform: platform5, path: path2, content:
|
|
13019
|
+
return { platform: platform5, path: path2, content: readFileSync13(path2, "utf8") };
|
|
12831
13020
|
} catch {
|
|
12832
13021
|
return { platform: platform5, path: path2, content: null };
|
|
12833
13022
|
}
|
|
@@ -12843,7 +13032,7 @@ __export(exports_daemon, {
|
|
|
12843
13032
|
runDaemonCommand: () => runDaemonCommand
|
|
12844
13033
|
});
|
|
12845
13034
|
import { spawn } from "node:child_process";
|
|
12846
|
-
import { existsSync as
|
|
13035
|
+
import { existsSync as existsSync16, openSync as openSync3, mkdirSync as mkdirSync10 } from "node:fs";
|
|
12847
13036
|
import { join as join10 } from "node:path";
|
|
12848
13037
|
async function runDaemonCommand(sub, opts, rest = []) {
|
|
12849
13038
|
switch (sub) {
|
|
@@ -13166,7 +13355,7 @@ async function runStop(opts) {
|
|
|
13166
13355
|
return 1;
|
|
13167
13356
|
}
|
|
13168
13357
|
async function spawnDetachedDaemon(opts) {
|
|
13169
|
-
|
|
13358
|
+
mkdirSync10(DAEMON_PATHS.DAEMON_DIR, { recursive: true, mode: 448 });
|
|
13170
13359
|
const logPath = join10(DAEMON_PATHS.DAEMON_DIR, "daemon.log");
|
|
13171
13360
|
const binary = process.argv[1] ?? "claudemesh";
|
|
13172
13361
|
const args = ["daemon", "up", "--foreground"];
|
|
@@ -13185,7 +13374,7 @@ async function spawnDetachedDaemon(opts) {
|
|
|
13185
13374
|
const sockPath = DAEMON_PATHS.SOCK_FILE;
|
|
13186
13375
|
const startedAt = Date.now();
|
|
13187
13376
|
while (Date.now() - startedAt < 3000) {
|
|
13188
|
-
if (
|
|
13377
|
+
if (existsSync16(sockPath)) {
|
|
13189
13378
|
if (opts.json) {
|
|
13190
13379
|
process.stdout.write(JSON.stringify({ ok: true, detached: true, pid: child.pid, log: logPath }) + `
|
|
13191
13380
|
`);
|
|
@@ -13230,19 +13419,19 @@ __export(exports_install, {
|
|
|
13230
13419
|
import {
|
|
13231
13420
|
chmodSync as chmodSync4,
|
|
13232
13421
|
copyFileSync,
|
|
13233
|
-
existsSync as
|
|
13234
|
-
mkdirSync as
|
|
13235
|
-
readFileSync as
|
|
13236
|
-
writeFileSync as
|
|
13422
|
+
existsSync as existsSync17,
|
|
13423
|
+
mkdirSync as mkdirSync11,
|
|
13424
|
+
readFileSync as readFileSync14,
|
|
13425
|
+
writeFileSync as writeFileSync14
|
|
13237
13426
|
} from "node:fs";
|
|
13238
13427
|
import { homedir as homedir9, platform as platform5 } from "node:os";
|
|
13239
|
-
import { dirname as
|
|
13428
|
+
import { dirname as dirname7, join as join11, resolve } from "node:path";
|
|
13240
13429
|
import { fileURLToPath } from "node:url";
|
|
13241
13430
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
13242
13431
|
function readClaudeConfig() {
|
|
13243
|
-
if (!
|
|
13432
|
+
if (!existsSync17(CLAUDE_CONFIG))
|
|
13244
13433
|
return {};
|
|
13245
|
-
const text =
|
|
13434
|
+
const text = readFileSync14(CLAUDE_CONFIG, "utf-8").trim();
|
|
13246
13435
|
if (!text)
|
|
13247
13436
|
return {};
|
|
13248
13437
|
try {
|
|
@@ -13252,10 +13441,10 @@ function readClaudeConfig() {
|
|
|
13252
13441
|
}
|
|
13253
13442
|
}
|
|
13254
13443
|
function backupClaudeConfig() {
|
|
13255
|
-
if (!
|
|
13444
|
+
if (!existsSync17(CLAUDE_CONFIG))
|
|
13256
13445
|
return;
|
|
13257
|
-
const backupDir = join11(
|
|
13258
|
-
|
|
13446
|
+
const backupDir = join11(dirname7(CLAUDE_CONFIG), ".claude", "backups");
|
|
13447
|
+
mkdirSync11(backupDir, { recursive: true });
|
|
13259
13448
|
const ts = Date.now();
|
|
13260
13449
|
const dest = join11(backupDir, `.claude.json.pre-claudemesh.${ts}`);
|
|
13261
13450
|
copyFileSync(CLAUDE_CONFIG, dest);
|
|
@@ -13281,7 +13470,7 @@ function patchMcpServer(entry) {
|
|
|
13281
13470
|
return action;
|
|
13282
13471
|
}
|
|
13283
13472
|
function removeMcpServer() {
|
|
13284
|
-
if (!
|
|
13473
|
+
if (!existsSync17(CLAUDE_CONFIG))
|
|
13285
13474
|
return false;
|
|
13286
13475
|
backupClaudeConfig();
|
|
13287
13476
|
const cfg = readClaudeConfig();
|
|
@@ -13294,8 +13483,8 @@ function removeMcpServer() {
|
|
|
13294
13483
|
return true;
|
|
13295
13484
|
}
|
|
13296
13485
|
function flushClaudeConfig(obj) {
|
|
13297
|
-
|
|
13298
|
-
|
|
13486
|
+
mkdirSync11(dirname7(CLAUDE_CONFIG), { recursive: true });
|
|
13487
|
+
writeFileSync14(CLAUDE_CONFIG, JSON.stringify(obj, null, 2) + `
|
|
13299
13488
|
`, "utf-8");
|
|
13300
13489
|
try {
|
|
13301
13490
|
chmodSync4(CLAUDE_CONFIG, 384);
|
|
@@ -13312,13 +13501,13 @@ function resolveEntry() {
|
|
|
13312
13501
|
const here = fileURLToPath(import.meta.url);
|
|
13313
13502
|
if (isBundledFile(here))
|
|
13314
13503
|
return here;
|
|
13315
|
-
return resolve(
|
|
13504
|
+
return resolve(dirname7(here), "..", "index.ts");
|
|
13316
13505
|
}
|
|
13317
13506
|
function resolveBundledSkillsDir() {
|
|
13318
13507
|
const here = fileURLToPath(import.meta.url);
|
|
13319
|
-
const pkgRoot = resolve(
|
|
13508
|
+
const pkgRoot = resolve(dirname7(here), "..", "..");
|
|
13320
13509
|
const skillsDir = join11(pkgRoot, "skills");
|
|
13321
|
-
if (
|
|
13510
|
+
if (existsSync17(skillsDir))
|
|
13322
13511
|
return skillsDir;
|
|
13323
13512
|
return null;
|
|
13324
13513
|
}
|
|
@@ -13333,7 +13522,7 @@ function installSkills() {
|
|
|
13333
13522
|
continue;
|
|
13334
13523
|
const srcDir = join11(src, entry.name);
|
|
13335
13524
|
const dstDir = join11(CLAUDE_SKILLS_ROOT, entry.name);
|
|
13336
|
-
|
|
13525
|
+
mkdirSync11(dstDir, { recursive: true });
|
|
13337
13526
|
for (const file of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
13338
13527
|
if (!file.isFile())
|
|
13339
13528
|
continue;
|
|
@@ -13353,7 +13542,7 @@ function uninstallSkills() {
|
|
|
13353
13542
|
if (!entry.isDirectory())
|
|
13354
13543
|
continue;
|
|
13355
13544
|
const dstDir = join11(CLAUDE_SKILLS_ROOT, entry.name);
|
|
13356
|
-
if (
|
|
13545
|
+
if (existsSync17(dstDir)) {
|
|
13357
13546
|
try {
|
|
13358
13547
|
fs.rmSync(dstDir, { recursive: true, force: true });
|
|
13359
13548
|
removed.push(entry.name);
|
|
@@ -13378,9 +13567,9 @@ function entriesEqual(a, b) {
|
|
|
13378
13567
|
return a.command === b.command && JSON.stringify(a.args ?? []) === JSON.stringify(b.args ?? []);
|
|
13379
13568
|
}
|
|
13380
13569
|
function readClaudeSettings() {
|
|
13381
|
-
if (!
|
|
13570
|
+
if (!existsSync17(CLAUDE_SETTINGS))
|
|
13382
13571
|
return {};
|
|
13383
|
-
const text =
|
|
13572
|
+
const text = readFileSync14(CLAUDE_SETTINGS, "utf-8").trim();
|
|
13384
13573
|
if (!text)
|
|
13385
13574
|
return {};
|
|
13386
13575
|
try {
|
|
@@ -13390,8 +13579,8 @@ function readClaudeSettings() {
|
|
|
13390
13579
|
}
|
|
13391
13580
|
}
|
|
13392
13581
|
function writeClaudeSettings(obj) {
|
|
13393
|
-
|
|
13394
|
-
|
|
13582
|
+
mkdirSync11(dirname7(CLAUDE_SETTINGS), { recursive: true });
|
|
13583
|
+
writeFileSync14(CLAUDE_SETTINGS, JSON.stringify(obj, null, 2) + `
|
|
13395
13584
|
`, "utf-8");
|
|
13396
13585
|
}
|
|
13397
13586
|
function installAllowedTools() {
|
|
@@ -13405,7 +13594,7 @@ function installAllowedTools() {
|
|
|
13405
13594
|
return { added: toAdd, unchanged: CLAUDEMESH_TOOLS.length - toAdd.length };
|
|
13406
13595
|
}
|
|
13407
13596
|
function uninstallAllowedTools() {
|
|
13408
|
-
if (!
|
|
13597
|
+
if (!existsSync17(CLAUDE_SETTINGS))
|
|
13409
13598
|
return 0;
|
|
13410
13599
|
const settings = readClaudeSettings();
|
|
13411
13600
|
const existing = settings.allowedTools ?? [];
|
|
@@ -13440,7 +13629,7 @@ function installHooks() {
|
|
|
13440
13629
|
return { added, unchanged };
|
|
13441
13630
|
}
|
|
13442
13631
|
function uninstallHooks() {
|
|
13443
|
-
if (!
|
|
13632
|
+
if (!existsSync17(CLAUDE_SETTINGS))
|
|
13444
13633
|
return 0;
|
|
13445
13634
|
const settings = readClaudeSettings();
|
|
13446
13635
|
const hooks2 = settings.hooks;
|
|
@@ -13490,7 +13679,7 @@ async function runInstall(args = []) {
|
|
|
13490
13679
|
render.err("`bun` is not on PATH.", "Install Bun first: https://bun.com");
|
|
13491
13680
|
process.exit(1);
|
|
13492
13681
|
}
|
|
13493
|
-
if (!
|
|
13682
|
+
if (!existsSync17(entry)) {
|
|
13494
13683
|
render.err(`MCP entry not found at ${entry}`);
|
|
13495
13684
|
process.exit(1);
|
|
13496
13685
|
}
|
|
@@ -13761,35 +13950,35 @@ var exports_uninstall = {};
|
|
|
13761
13950
|
__export(exports_uninstall, {
|
|
13762
13951
|
uninstall: () => uninstall
|
|
13763
13952
|
});
|
|
13764
|
-
import { readFileSync as
|
|
13765
|
-
import { join as join12, dirname as
|
|
13953
|
+
import { readFileSync as readFileSync15, writeFileSync as writeFileSync15, existsSync as existsSync18, rmSync as rmSync3, readdirSync as readdirSync2 } from "node:fs";
|
|
13954
|
+
import { join as join12, dirname as dirname8 } from "node:path";
|
|
13766
13955
|
import { homedir as homedir10 } from "node:os";
|
|
13767
13956
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
13768
13957
|
function bundledSkillsDir() {
|
|
13769
13958
|
const here = fileURLToPath2(import.meta.url);
|
|
13770
|
-
const pkgRoot = join12(
|
|
13959
|
+
const pkgRoot = join12(dirname8(here), "..", "..");
|
|
13771
13960
|
const skillsDir = join12(pkgRoot, "skills");
|
|
13772
|
-
return
|
|
13961
|
+
return existsSync18(skillsDir) ? skillsDir : null;
|
|
13773
13962
|
}
|
|
13774
13963
|
async function uninstall() {
|
|
13775
13964
|
let removed = 0;
|
|
13776
|
-
if (
|
|
13965
|
+
if (existsSync18(PATHS.CLAUDE_JSON)) {
|
|
13777
13966
|
try {
|
|
13778
|
-
const raw =
|
|
13967
|
+
const raw = readFileSync15(PATHS.CLAUDE_JSON, "utf-8");
|
|
13779
13968
|
const config = JSON.parse(raw);
|
|
13780
13969
|
const servers = config.mcpServers;
|
|
13781
13970
|
if (servers && "claudemesh" in servers) {
|
|
13782
13971
|
delete servers.claudemesh;
|
|
13783
|
-
|
|
13972
|
+
writeFileSync15(PATHS.CLAUDE_JSON, JSON.stringify(config, null, 2) + `
|
|
13784
13973
|
`, "utf-8");
|
|
13785
13974
|
render.ok("removed MCP server", dim("~/.claude.json"));
|
|
13786
13975
|
removed++;
|
|
13787
13976
|
}
|
|
13788
13977
|
} catch {}
|
|
13789
13978
|
}
|
|
13790
|
-
if (
|
|
13979
|
+
if (existsSync18(PATHS.CLAUDE_SETTINGS)) {
|
|
13791
13980
|
try {
|
|
13792
|
-
const raw =
|
|
13981
|
+
const raw = readFileSync15(PATHS.CLAUDE_SETTINGS, "utf-8");
|
|
13793
13982
|
const config = JSON.parse(raw);
|
|
13794
13983
|
const hooks2 = config.hooks;
|
|
13795
13984
|
if (hooks2) {
|
|
@@ -13810,7 +13999,7 @@ async function uninstall() {
|
|
|
13810
13999
|
}
|
|
13811
14000
|
}
|
|
13812
14001
|
if (removedHooks > 0) {
|
|
13813
|
-
|
|
14002
|
+
writeFileSync15(PATHS.CLAUDE_SETTINGS, JSON.stringify(config, null, 2) + `
|
|
13814
14003
|
`, "utf-8");
|
|
13815
14004
|
render.ok(`removed ${removedHooks} claudemesh hook${removedHooks === 1 ? "" : "s"}`, dim("settings.json"));
|
|
13816
14005
|
removed++;
|
|
@@ -13826,7 +14015,7 @@ async function uninstall() {
|
|
|
13826
14015
|
if (!entry.isDirectory())
|
|
13827
14016
|
continue;
|
|
13828
14017
|
const dst = join12(CLAUDE_SKILLS_ROOT2, entry.name);
|
|
13829
|
-
if (
|
|
14018
|
+
if (existsSync18(dst)) {
|
|
13830
14019
|
try {
|
|
13831
14020
|
rmSync3(dst, { recursive: true, force: true });
|
|
13832
14021
|
removedSkills.push(entry.name);
|
|
@@ -13858,7 +14047,7 @@ var exports_doctor = {};
|
|
|
13858
14047
|
__export(exports_doctor, {
|
|
13859
14048
|
runDoctor: () => runDoctor
|
|
13860
14049
|
});
|
|
13861
|
-
import { existsSync as
|
|
14050
|
+
import { existsSync as existsSync19, readFileSync as readFileSync16, statSync as statSync3 } from "node:fs";
|
|
13862
14051
|
import { homedir as homedir11, platform as platform6 } from "node:os";
|
|
13863
14052
|
import { join as join13 } from "node:path";
|
|
13864
14053
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
@@ -13885,7 +14074,7 @@ function checkClaudeOnPath() {
|
|
|
13885
14074
|
}
|
|
13886
14075
|
function checkMcpRegistered() {
|
|
13887
14076
|
const claudeConfig = join13(homedir11(), ".claude.json");
|
|
13888
|
-
if (!
|
|
14077
|
+
if (!existsSync19(claudeConfig)) {
|
|
13889
14078
|
return {
|
|
13890
14079
|
name: "claudemesh MCP registered in ~/.claude.json",
|
|
13891
14080
|
pass: false,
|
|
@@ -13893,7 +14082,7 @@ function checkMcpRegistered() {
|
|
|
13893
14082
|
};
|
|
13894
14083
|
}
|
|
13895
14084
|
try {
|
|
13896
|
-
const cfg = JSON.parse(
|
|
14085
|
+
const cfg = JSON.parse(readFileSync16(claudeConfig, "utf-8"));
|
|
13897
14086
|
const registered = Boolean(cfg.mcpServers?.["claudemesh"]);
|
|
13898
14087
|
return {
|
|
13899
14088
|
name: "claudemesh MCP registered in ~/.claude.json",
|
|
@@ -13911,7 +14100,7 @@ function checkMcpRegistered() {
|
|
|
13911
14100
|
}
|
|
13912
14101
|
function checkHooksRegistered() {
|
|
13913
14102
|
const settings = join13(homedir11(), ".claude", "settings.json");
|
|
13914
|
-
if (!
|
|
14103
|
+
if (!existsSync19(settings)) {
|
|
13915
14104
|
return {
|
|
13916
14105
|
name: "Status hooks registered in ~/.claude/settings.json",
|
|
13917
14106
|
pass: false,
|
|
@@ -13919,7 +14108,7 @@ function checkHooksRegistered() {
|
|
|
13919
14108
|
};
|
|
13920
14109
|
}
|
|
13921
14110
|
try {
|
|
13922
|
-
const raw =
|
|
14111
|
+
const raw = readFileSync16(settings, "utf-8");
|
|
13923
14112
|
const has = raw.includes("claudemesh hook ");
|
|
13924
14113
|
return {
|
|
13925
14114
|
name: "Status hooks registered in ~/.claude/settings.json",
|
|
@@ -13936,7 +14125,7 @@ function checkHooksRegistered() {
|
|
|
13936
14125
|
}
|
|
13937
14126
|
function checkConfigFile() {
|
|
13938
14127
|
const path2 = getConfigPath();
|
|
13939
|
-
if (!
|
|
14128
|
+
if (!existsSync19(path2)) {
|
|
13940
14129
|
return {
|
|
13941
14130
|
name: "~/.claudemesh/config.json exists and parses",
|
|
13942
14131
|
pass: true,
|
|
@@ -14119,7 +14308,7 @@ var exports_status = {};
|
|
|
14119
14308
|
__export(exports_status, {
|
|
14120
14309
|
runStatus: () => runStatus2
|
|
14121
14310
|
});
|
|
14122
|
-
import { statSync as statSync4, existsSync as
|
|
14311
|
+
import { statSync as statSync4, existsSync as existsSync20 } from "node:fs";
|
|
14123
14312
|
import WebSocket3 from "ws";
|
|
14124
14313
|
async function probeBroker(url, timeoutMs = 4000) {
|
|
14125
14314
|
return new Promise((resolve2) => {
|
|
@@ -14149,7 +14338,7 @@ async function runStatus2() {
|
|
|
14149
14338
|
render.section(`status (v${VERSION})`);
|
|
14150
14339
|
const configPath = getConfigPath();
|
|
14151
14340
|
let configPermsNote = "missing";
|
|
14152
|
-
if (
|
|
14341
|
+
if (existsSync20(configPath)) {
|
|
14153
14342
|
const mode = (statSync4(configPath).mode & 511).toString(8).padStart(4, "0");
|
|
14154
14343
|
configPermsNote = mode === "0600" ? `${mode}` : `${mode} — expected 0600`;
|
|
14155
14344
|
}
|
|
@@ -14295,13 +14484,13 @@ var init_check_claude_binary = __esm(() => {
|
|
|
14295
14484
|
});
|
|
14296
14485
|
|
|
14297
14486
|
// src/services/health/check-mcp-registered.ts
|
|
14298
|
-
import { existsSync as
|
|
14487
|
+
import { existsSync as existsSync21, readFileSync as readFileSync17 } from "node:fs";
|
|
14299
14488
|
function checkMcpRegistered2() {
|
|
14300
14489
|
try {
|
|
14301
|
-
if (!
|
|
14490
|
+
if (!existsSync21(PATHS.CLAUDE_JSON)) {
|
|
14302
14491
|
return { name: "mcp-registered", ok: false, message: "~/.claude.json not found" };
|
|
14303
14492
|
}
|
|
14304
|
-
const raw =
|
|
14493
|
+
const raw = readFileSync17(PATHS.CLAUDE_JSON, "utf-8");
|
|
14305
14494
|
const config = JSON.parse(raw);
|
|
14306
14495
|
if (config.mcpServers && "claudemesh" in config.mcpServers) {
|
|
14307
14496
|
return { name: "mcp-registered", ok: true, message: "MCP server registered" };
|
|
@@ -14316,13 +14505,13 @@ var init_check_mcp_registered = __esm(() => {
|
|
|
14316
14505
|
});
|
|
14317
14506
|
|
|
14318
14507
|
// src/services/health/check-hooks-registered.ts
|
|
14319
|
-
import { existsSync as
|
|
14508
|
+
import { existsSync as existsSync22, readFileSync as readFileSync18 } from "node:fs";
|
|
14320
14509
|
function checkHooksRegistered2() {
|
|
14321
14510
|
try {
|
|
14322
|
-
if (!
|
|
14511
|
+
if (!existsSync22(PATHS.CLAUDE_SETTINGS)) {
|
|
14323
14512
|
return { name: "hooks-registered", ok: false, message: "~/.claude/settings.json not found" };
|
|
14324
14513
|
}
|
|
14325
|
-
const raw =
|
|
14514
|
+
const raw = readFileSync18(PATHS.CLAUDE_SETTINGS, "utf-8");
|
|
14326
14515
|
const config = JSON.parse(raw);
|
|
14327
14516
|
if (config.hooks) {
|
|
14328
14517
|
return { name: "hooks-registered", ok: true, message: "Hooks configured" };
|
|
@@ -14337,10 +14526,10 @@ var init_check_hooks_registered = __esm(() => {
|
|
|
14337
14526
|
});
|
|
14338
14527
|
|
|
14339
14528
|
// src/services/health/check-config-perms.ts
|
|
14340
|
-
import { existsSync as
|
|
14529
|
+
import { existsSync as existsSync23, statSync as statSync5 } from "node:fs";
|
|
14341
14530
|
function checkConfigPerms() {
|
|
14342
14531
|
const configFile = PATHS.CONFIG_FILE;
|
|
14343
|
-
if (!
|
|
14532
|
+
if (!existsSync23(configFile)) {
|
|
14344
14533
|
return { name: "config-perms", ok: true, message: "No config file yet (first run)" };
|
|
14345
14534
|
}
|
|
14346
14535
|
try {
|
|
@@ -14358,13 +14547,13 @@ var init_check_config_perms = __esm(() => {
|
|
|
14358
14547
|
});
|
|
14359
14548
|
|
|
14360
14549
|
// src/services/health/check-keypairs-valid.ts
|
|
14361
|
-
import { existsSync as
|
|
14550
|
+
import { existsSync as existsSync24, readFileSync as readFileSync19 } from "node:fs";
|
|
14362
14551
|
function checkKeypairsValid() {
|
|
14363
|
-
if (!
|
|
14552
|
+
if (!existsSync24(PATHS.CONFIG_FILE)) {
|
|
14364
14553
|
return { name: "keypairs-valid", ok: true, message: "No config (first run)" };
|
|
14365
14554
|
}
|
|
14366
14555
|
try {
|
|
14367
|
-
const raw =
|
|
14556
|
+
const raw = readFileSync19(PATHS.CONFIG_FILE, "utf-8");
|
|
14368
14557
|
const config = JSON.parse(raw);
|
|
14369
14558
|
const meshes = config.meshes ?? [];
|
|
14370
14559
|
if (meshes.length === 0) {
|
|
@@ -14845,7 +15034,7 @@ __export(exports_url_handler, {
|
|
|
14845
15034
|
runUrlHandler: () => runUrlHandler
|
|
14846
15035
|
});
|
|
14847
15036
|
import { platform as platform7, homedir as homedir12 } from "node:os";
|
|
14848
|
-
import { existsSync as
|
|
15037
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync12, writeFileSync as writeFileSync16, rmSync as rmSync4, chmodSync as chmodSync5 } from "node:fs";
|
|
14849
15038
|
import { join as join14 } from "node:path";
|
|
14850
15039
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
14851
15040
|
function resolveClaudemeshBin() {
|
|
@@ -14856,7 +15045,7 @@ function installDarwin2() {
|
|
|
14856
15045
|
const appDir = join14(homedir12(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
|
|
14857
15046
|
const contents = join14(appDir, "Contents");
|
|
14858
15047
|
const macOS = join14(contents, "MacOS");
|
|
14859
|
-
|
|
15048
|
+
mkdirSync12(macOS, { recursive: true });
|
|
14860
15049
|
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
14861
15050
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
14862
15051
|
<plist version="1.0">
|
|
@@ -14879,7 +15068,7 @@ function installDarwin2() {
|
|
|
14879
15068
|
</array>
|
|
14880
15069
|
</dict>
|
|
14881
15070
|
</plist>`;
|
|
14882
|
-
|
|
15071
|
+
writeFileSync16(join14(contents, "Info.plist"), plist);
|
|
14883
15072
|
const shim = `#!/bin/sh
|
|
14884
15073
|
URL="$1"
|
|
14885
15074
|
CODE=\${URL#claudemesh://}
|
|
@@ -14894,7 +15083,7 @@ end tell
|
|
|
14894
15083
|
EOF
|
|
14895
15084
|
`;
|
|
14896
15085
|
const shimPath = join14(macOS, "open-url");
|
|
14897
|
-
|
|
15086
|
+
writeFileSync16(shimPath, shim);
|
|
14898
15087
|
chmodSync5(shimPath, 493);
|
|
14899
15088
|
const lsreg = spawnSync5("/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister", ["-f", appDir], { encoding: "utf-8" });
|
|
14900
15089
|
if (lsreg.status !== 0) {
|
|
@@ -14906,7 +15095,7 @@ EOF
|
|
|
14906
15095
|
function installLinux2() {
|
|
14907
15096
|
const binPath = resolveClaudemeshBin();
|
|
14908
15097
|
const appsDir = join14(homedir12(), ".local", "share", "applications");
|
|
14909
|
-
|
|
15098
|
+
mkdirSync12(appsDir, { recursive: true });
|
|
14910
15099
|
const desktop = `[Desktop Entry]
|
|
14911
15100
|
Type=Application
|
|
14912
15101
|
Name=Claudemesh
|
|
@@ -14918,7 +15107,7 @@ MimeType=x-scheme-handler/claudemesh;
|
|
|
14918
15107
|
NoDisplay=true
|
|
14919
15108
|
`;
|
|
14920
15109
|
const desktopPath = join14(appsDir, "claudemesh.desktop");
|
|
14921
|
-
|
|
15110
|
+
writeFileSync16(desktopPath, desktop);
|
|
14922
15111
|
const xdg1 = spawnSync5("xdg-mime", ["default", "claudemesh.desktop", "x-scheme-handler/claudemesh"], { encoding: "utf-8" });
|
|
14923
15112
|
if (xdg1.status !== 0) {
|
|
14924
15113
|
render.warn("xdg-mime not available — skipped mime default registration");
|
|
@@ -14941,7 +15130,7 @@ function installWindows() {
|
|
|
14941
15130
|
`@="\\"${binPath.replace(/\\/g, "\\\\")}\\" \\"%1\\""`
|
|
14942
15131
|
];
|
|
14943
15132
|
const regPath = join14(homedir12(), "claudemesh-handler.reg");
|
|
14944
|
-
|
|
15133
|
+
writeFileSync16(regPath, lines.join(`\r
|
|
14945
15134
|
`));
|
|
14946
15135
|
const res = spawnSync5("reg.exe", ["import", regPath], { encoding: "utf-8" });
|
|
14947
15136
|
if (res.status !== 0) {
|
|
@@ -14953,14 +15142,14 @@ function installWindows() {
|
|
|
14953
15142
|
}
|
|
14954
15143
|
function uninstallDarwin() {
|
|
14955
15144
|
const appDir = join14(homedir12(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
|
|
14956
|
-
if (
|
|
15145
|
+
if (existsSync25(appDir))
|
|
14957
15146
|
rmSync4(appDir, { recursive: true, force: true });
|
|
14958
15147
|
render.ok("removed claudemesh:// handler on macOS");
|
|
14959
15148
|
return EXIT.SUCCESS;
|
|
14960
15149
|
}
|
|
14961
15150
|
function uninstallLinux() {
|
|
14962
15151
|
const desktopPath = join14(homedir12(), ".local", "share", "applications", "claudemesh.desktop");
|
|
14963
|
-
if (
|
|
15152
|
+
if (existsSync25(desktopPath))
|
|
14964
15153
|
rmSync4(desktopPath, { force: true });
|
|
14965
15154
|
render.ok("removed claudemesh:// handler on Linux");
|
|
14966
15155
|
return EXIT.SUCCESS;
|
|
@@ -15005,7 +15194,7 @@ var exports_status_line = {};
|
|
|
15005
15194
|
__export(exports_status_line, {
|
|
15006
15195
|
runStatusLine: () => runStatusLine
|
|
15007
15196
|
});
|
|
15008
|
-
import { existsSync as
|
|
15197
|
+
import { existsSync as existsSync26, readFileSync as readFileSync20 } from "node:fs";
|
|
15009
15198
|
import { join as join15 } from "node:path";
|
|
15010
15199
|
import { homedir as homedir13 } from "node:os";
|
|
15011
15200
|
async function runStatusLine() {
|
|
@@ -15017,9 +15206,9 @@ async function runStatusLine() {
|
|
|
15017
15206
|
}
|
|
15018
15207
|
const cachePath = join15(homedir13(), ".claudemesh", "peer-cache.json");
|
|
15019
15208
|
let cache = {};
|
|
15020
|
-
if (
|
|
15209
|
+
if (existsSync26(cachePath)) {
|
|
15021
15210
|
try {
|
|
15022
|
-
cache = JSON.parse(
|
|
15211
|
+
cache = JSON.parse(readFileSync20(cachePath, "utf-8"));
|
|
15023
15212
|
} catch {}
|
|
15024
15213
|
}
|
|
15025
15214
|
const pick = config.meshes[0];
|
|
@@ -15050,7 +15239,7 @@ __export(exports_backup, {
|
|
|
15050
15239
|
runRestore: () => runRestore,
|
|
15051
15240
|
runBackup: () => runBackup
|
|
15052
15241
|
});
|
|
15053
|
-
import { readFileSync as
|
|
15242
|
+
import { readFileSync as readFileSync21, writeFileSync as writeFileSync17, existsSync as existsSync27 } from "node:fs";
|
|
15054
15243
|
import { createInterface as createInterface11 } from "node:readline";
|
|
15055
15244
|
function readHidden(prompt5) {
|
|
15056
15245
|
return new Promise((resolve2) => {
|
|
@@ -15092,11 +15281,11 @@ async function deriveKey(pass, salt, s) {
|
|
|
15092
15281
|
}
|
|
15093
15282
|
async function runBackup(outPath) {
|
|
15094
15283
|
const configPath = getConfigPath();
|
|
15095
|
-
if (!
|
|
15284
|
+
if (!existsSync27(configPath)) {
|
|
15096
15285
|
console.error(" No config found — nothing to back up. Join a mesh first.");
|
|
15097
15286
|
return EXIT.NOT_FOUND;
|
|
15098
15287
|
}
|
|
15099
|
-
const plaintext =
|
|
15288
|
+
const plaintext = readFileSync21(configPath);
|
|
15100
15289
|
const pass = await readHidden(" Passphrase (min 12 chars): ");
|
|
15101
15290
|
if (pass.length < 12) {
|
|
15102
15291
|
console.error(" ✗ Passphrase too short.");
|
|
@@ -15114,7 +15303,7 @@ async function runBackup(outPath) {
|
|
|
15114
15303
|
const ciphertext = Buffer.from(s.crypto_aead_xchacha20poly1305_ietf_encrypt(plaintext, null, null, nonce, key));
|
|
15115
15304
|
const blob = Buffer.concat([MAGIC, salt, nonce, ciphertext]);
|
|
15116
15305
|
const file = outPath ?? `claudemesh-backup-${new Date().toISOString().replace(/[:.]/g, "-")}.cmb`;
|
|
15117
|
-
|
|
15306
|
+
writeFileSync17(file, blob, { mode: 384 });
|
|
15118
15307
|
console.log(`
|
|
15119
15308
|
✓ Backup saved: ${file}`);
|
|
15120
15309
|
console.log(` Size: ${blob.length} bytes. Guard the passphrase — there is no recovery.
|
|
@@ -15126,11 +15315,11 @@ async function runRestore(inPath) {
|
|
|
15126
15315
|
console.error(" Usage: claudemesh restore <backup-file>");
|
|
15127
15316
|
return EXIT.INVALID_ARGS;
|
|
15128
15317
|
}
|
|
15129
|
-
if (!
|
|
15318
|
+
if (!existsSync27(inPath)) {
|
|
15130
15319
|
console.error(` ✗ File not found: ${inPath}`);
|
|
15131
15320
|
return EXIT.NOT_FOUND;
|
|
15132
15321
|
}
|
|
15133
|
-
const blob =
|
|
15322
|
+
const blob = readFileSync21(inPath);
|
|
15134
15323
|
if (blob.length < 4 + 16 + 24 + 17 || !blob.subarray(0, 4).equals(MAGIC)) {
|
|
15135
15324
|
console.error(" ✗ Not a claudemesh backup file (bad magic).");
|
|
15136
15325
|
return EXIT.INVALID_ARGS;
|
|
@@ -15149,12 +15338,12 @@ async function runRestore(inPath) {
|
|
|
15149
15338
|
return EXIT.INTERNAL_ERROR;
|
|
15150
15339
|
}
|
|
15151
15340
|
const configPath = getConfigPath();
|
|
15152
|
-
if (
|
|
15341
|
+
if (existsSync27(configPath)) {
|
|
15153
15342
|
const backupOld = `${configPath}.before-restore.${Date.now()}`;
|
|
15154
|
-
|
|
15343
|
+
writeFileSync17(backupOld, readFileSync21(configPath), { mode: 384 });
|
|
15155
15344
|
console.log(` ↻ Existing config saved to ${backupOld}`);
|
|
15156
15345
|
}
|
|
15157
|
-
|
|
15346
|
+
writeFileSync17(configPath, Buffer.from(plaintext), { mode: 384 });
|
|
15158
15347
|
console.log(`
|
|
15159
15348
|
✓ Config restored to ${configPath}`);
|
|
15160
15349
|
console.log(" Run `claudemesh list` to verify your meshes.\n");
|
|
@@ -15174,8 +15363,8 @@ __export(exports_upgrade, {
|
|
|
15174
15363
|
runUpgrade: () => runUpgrade
|
|
15175
15364
|
});
|
|
15176
15365
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
15177
|
-
import { existsSync as
|
|
15178
|
-
import { dirname as
|
|
15366
|
+
import { existsSync as existsSync28 } from "node:fs";
|
|
15367
|
+
import { dirname as dirname9, join as join16, resolve as resolve2 } from "node:path";
|
|
15179
15368
|
async function latestVersion() {
|
|
15180
15369
|
try {
|
|
15181
15370
|
const res = await fetch(URLS.NPM_REGISTRY, { signal: AbortSignal.timeout(8000) });
|
|
@@ -15189,14 +15378,14 @@ async function latestVersion() {
|
|
|
15189
15378
|
}
|
|
15190
15379
|
function findNpm() {
|
|
15191
15380
|
const portable = join16(process.env.HOME ?? "", ".claudemesh", "node", "bin", "npm");
|
|
15192
|
-
if (
|
|
15381
|
+
if (existsSync28(portable)) {
|
|
15193
15382
|
return { npm: portable, prefix: join16(process.env.HOME ?? "", ".claudemesh") };
|
|
15194
15383
|
}
|
|
15195
15384
|
let cur = resolve2(process.argv[1] ?? ".");
|
|
15196
15385
|
for (let i = 0;i < 6; i++) {
|
|
15197
|
-
cur =
|
|
15386
|
+
cur = dirname9(cur);
|
|
15198
15387
|
const candidate = join16(cur, "bin", "npm");
|
|
15199
|
-
if (
|
|
15388
|
+
if (existsSync28(candidate))
|
|
15200
15389
|
return { npm: candidate };
|
|
15201
15390
|
}
|
|
15202
15391
|
return { npm: "npm" };
|
|
@@ -15258,7 +15447,7 @@ __export(exports_grants, {
|
|
|
15258
15447
|
runBlock: () => runBlock,
|
|
15259
15448
|
isAllowed: () => isAllowed
|
|
15260
15449
|
});
|
|
15261
|
-
import { existsSync as
|
|
15450
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync13, readFileSync as readFileSync22, writeFileSync as writeFileSync18 } from "node:fs";
|
|
15262
15451
|
import { homedir as homedir14 } from "node:os";
|
|
15263
15452
|
import { join as join17 } from "node:path";
|
|
15264
15453
|
async function syncToBroker(meshSlug, grants) {
|
|
@@ -15278,19 +15467,19 @@ async function syncToBroker(meshSlug, grants) {
|
|
|
15278
15467
|
}
|
|
15279
15468
|
}
|
|
15280
15469
|
function readGrants() {
|
|
15281
|
-
if (!
|
|
15470
|
+
if (!existsSync29(GRANT_FILE))
|
|
15282
15471
|
return {};
|
|
15283
15472
|
try {
|
|
15284
|
-
return JSON.parse(
|
|
15473
|
+
return JSON.parse(readFileSync22(GRANT_FILE, "utf-8"));
|
|
15285
15474
|
} catch {
|
|
15286
15475
|
return {};
|
|
15287
15476
|
}
|
|
15288
15477
|
}
|
|
15289
15478
|
function writeGrants(g) {
|
|
15290
15479
|
const dir = join17(homedir14(), ".claudemesh");
|
|
15291
|
-
if (!
|
|
15292
|
-
|
|
15293
|
-
|
|
15480
|
+
if (!existsSync29(dir))
|
|
15481
|
+
mkdirSync13(dir, { recursive: true });
|
|
15482
|
+
writeFileSync18(GRANT_FILE, JSON.stringify(g, null, 2), { mode: 384 });
|
|
15294
15483
|
}
|
|
15295
15484
|
function resolveCaps(input) {
|
|
15296
15485
|
if (input.includes("all"))
|
|
@@ -17166,8 +17355,8 @@ __export(exports_file, {
|
|
|
17166
17355
|
runFileGet: () => runFileGet
|
|
17167
17356
|
});
|
|
17168
17357
|
import { hostname as osHostname2 } from "node:os";
|
|
17169
|
-
import { resolve as resolvePath, basename, dirname as
|
|
17170
|
-
import { statSync as statSync7, existsSync as
|
|
17358
|
+
import { resolve as resolvePath, basename, dirname as dirname10 } from "node:path";
|
|
17359
|
+
import { statSync as statSync7, existsSync as existsSync30, writeFileSync as writeFileSync19, mkdirSync as mkdirSync14 } from "node:fs";
|
|
17171
17360
|
function emitJson2(data) {
|
|
17172
17361
|
console.log(JSON.stringify(data, null, 2));
|
|
17173
17362
|
}
|
|
@@ -17184,7 +17373,7 @@ async function runFileShare(filePath, opts) {
|
|
|
17184
17373
|
return EXIT.INVALID_ARGS;
|
|
17185
17374
|
}
|
|
17186
17375
|
const absPath = resolvePath(filePath);
|
|
17187
|
-
if (!
|
|
17376
|
+
if (!existsSync30(absPath)) {
|
|
17188
17377
|
render.err(`File not found: ${absPath}`);
|
|
17189
17378
|
return EXIT.INVALID_ARGS;
|
|
17190
17379
|
}
|
|
@@ -17263,8 +17452,8 @@ async function runFileGet(fileId, opts) {
|
|
|
17263
17452
|
}
|
|
17264
17453
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
17265
17454
|
const outPath = opts.out ? resolvePath(opts.out) : resolvePath(process.cwd(), meta.name);
|
|
17266
|
-
|
|
17267
|
-
|
|
17455
|
+
mkdirSync14(dirname10(outPath), { recursive: true });
|
|
17456
|
+
writeFileSync19(outPath, buf);
|
|
17268
17457
|
if (opts.json) {
|
|
17269
17458
|
emitJson2({ fileId, name: meta.name, savedTo: outPath, sizeBytes: buf.length });
|
|
17270
17459
|
} else {
|
|
@@ -17874,7 +18063,7 @@ __export(exports_bridge, {
|
|
|
17874
18063
|
runBridge: () => runBridge,
|
|
17875
18064
|
bridgeConfigTemplate: () => bridgeConfigTemplate
|
|
17876
18065
|
});
|
|
17877
|
-
import { readFileSync as
|
|
18066
|
+
import { readFileSync as readFileSync23, existsSync as existsSync31 } from "node:fs";
|
|
17878
18067
|
function parseConfig(text) {
|
|
17879
18068
|
const trimmed = text.trim();
|
|
17880
18069
|
if (trimmed.startsWith("{"))
|
|
@@ -17918,13 +18107,13 @@ async function runBridge(configPath) {
|
|
|
17918
18107
|
render.err("Usage: claudemesh bridge run <config.yaml>");
|
|
17919
18108
|
return EXIT.INVALID_ARGS;
|
|
17920
18109
|
}
|
|
17921
|
-
if (!
|
|
18110
|
+
if (!existsSync31(configPath)) {
|
|
17922
18111
|
render.err(`config file not found: ${configPath}`);
|
|
17923
18112
|
return EXIT.NOT_FOUND;
|
|
17924
18113
|
}
|
|
17925
18114
|
let cfg;
|
|
17926
18115
|
try {
|
|
17927
|
-
cfg = parseConfig(
|
|
18116
|
+
cfg = parseConfig(readFileSync23(configPath, "utf-8"));
|
|
17928
18117
|
} catch (e) {
|
|
17929
18118
|
render.err(`failed to parse ${configPath}: ${e instanceof Error ? e.message : String(e)}`);
|
|
17930
18119
|
return EXIT.INVALID_ARGS;
|
|
@@ -18898,12 +19087,12 @@ import {
|
|
|
18898
19087
|
ListResourcesRequestSchema,
|
|
18899
19088
|
ReadResourceRequestSchema
|
|
18900
19089
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
18901
|
-
import { existsSync as
|
|
19090
|
+
import { existsSync as existsSync32, appendFileSync as appendFileSync2 } from "node:fs";
|
|
18902
19091
|
import { request as httpRequest2 } from "node:http";
|
|
18903
19092
|
import { join as join18 } from "node:path";
|
|
18904
19093
|
async function daemonReady() {
|
|
18905
19094
|
for (let i = 0;i < DAEMON_BOOT_RETRIES; i++) {
|
|
18906
|
-
if (
|
|
19095
|
+
if (existsSync32(DAEMON_PATHS.SOCK_FILE))
|
|
18907
19096
|
return true;
|
|
18908
19097
|
await new Promise((r) => setTimeout(r, DAEMON_BOOT_RETRY_MS));
|
|
18909
19098
|
}
|
|
@@ -21504,4 +21693,4 @@ main().catch((err) => {
|
|
|
21504
21693
|
process.exit(EXIT.INTERNAL_ERROR);
|
|
21505
21694
|
});
|
|
21506
21695
|
|
|
21507
|
-
//# debugId=
|
|
21696
|
+
//# debugId=2228CF546341C88264756E2164756E21
|