claudemesh-cli 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +139 -50
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -54773,7 +54773,7 @@ class StdioServerTransport {
|
|
|
54773
54773
|
var TOOLS = [
|
|
54774
54774
|
{
|
|
54775
54775
|
name: "send_message",
|
|
54776
|
-
description: "Send a message to a peer in one of your joined meshes. `to`
|
|
54776
|
+
description: "Send a message to a peer in one of your joined meshes. `to` can be a peer display name (resolved via list_peers), hex pubkey, `#channel`, or `*` for broadcast. `priority` controls delivery: `now` bypasses busy gates, `next` waits for idle (default), `low` is pull-only.",
|
|
54777
54777
|
inputSchema: {
|
|
54778
54778
|
type: "object",
|
|
54779
54779
|
properties: {
|
|
@@ -54990,6 +54990,7 @@ class BrokerClient {
|
|
|
54990
54990
|
outbound = [];
|
|
54991
54991
|
pushHandlers = new Set;
|
|
54992
54992
|
pushBuffer = [];
|
|
54993
|
+
listPeersResolvers = [];
|
|
54993
54994
|
closed = false;
|
|
54994
54995
|
reconnectAttempt = 0;
|
|
54995
54996
|
helloTimer = null;
|
|
@@ -55013,7 +55014,7 @@ class BrokerClient {
|
|
|
55013
55014
|
async connect() {
|
|
55014
55015
|
if (this.closed)
|
|
55015
55016
|
throw new Error("client is closed");
|
|
55016
|
-
this.
|
|
55017
|
+
this.setConnStatus("connecting");
|
|
55017
55018
|
const ws = new wrapper_default(this.mesh.brokerUrl);
|
|
55018
55019
|
this.ws = ws;
|
|
55019
55020
|
return new Promise((resolve, reject) => {
|
|
@@ -55053,7 +55054,7 @@ class BrokerClient {
|
|
|
55053
55054
|
if (this.helloTimer)
|
|
55054
55055
|
clearTimeout(this.helloTimer);
|
|
55055
55056
|
this.helloTimer = null;
|
|
55056
|
-
this.
|
|
55057
|
+
this.setConnStatus("open");
|
|
55057
55058
|
this.reconnectAttempt = 0;
|
|
55058
55059
|
this.flushOutbound();
|
|
55059
55060
|
resolve();
|
|
@@ -55072,7 +55073,7 @@ class BrokerClient {
|
|
|
55072
55073
|
if (!this.closed)
|
|
55073
55074
|
this.scheduleReconnect();
|
|
55074
55075
|
else
|
|
55075
|
-
this.
|
|
55076
|
+
this.setConnStatus("closed");
|
|
55076
55077
|
};
|
|
55077
55078
|
const onError = (err) => {
|
|
55078
55079
|
this.debug(`ws error: ${err.message}`);
|
|
@@ -55152,6 +55153,26 @@ class BrokerClient {
|
|
|
55152
55153
|
return;
|
|
55153
55154
|
this.ws.send(JSON.stringify({ type: "set_status", status }));
|
|
55154
55155
|
}
|
|
55156
|
+
async listPeers() {
|
|
55157
|
+
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
55158
|
+
return [];
|
|
55159
|
+
return new Promise((resolve) => {
|
|
55160
|
+
this.listPeersResolvers.push(resolve);
|
|
55161
|
+
this.ws.send(JSON.stringify({ type: "list_peers" }));
|
|
55162
|
+
setTimeout(() => {
|
|
55163
|
+
const idx = this.listPeersResolvers.indexOf(resolve);
|
|
55164
|
+
if (idx !== -1) {
|
|
55165
|
+
this.listPeersResolvers.splice(idx, 1);
|
|
55166
|
+
resolve([]);
|
|
55167
|
+
}
|
|
55168
|
+
}, 5000);
|
|
55169
|
+
});
|
|
55170
|
+
}
|
|
55171
|
+
async setSummary(summary) {
|
|
55172
|
+
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
55173
|
+
return;
|
|
55174
|
+
this.ws.send(JSON.stringify({ type: "set_summary", summary }));
|
|
55175
|
+
}
|
|
55155
55176
|
close() {
|
|
55156
55177
|
this.closed = true;
|
|
55157
55178
|
if (this.helloTimer)
|
|
@@ -55163,7 +55184,7 @@ class BrokerClient {
|
|
|
55163
55184
|
this.ws.close();
|
|
55164
55185
|
} catch {}
|
|
55165
55186
|
}
|
|
55166
|
-
this.
|
|
55187
|
+
this.setConnStatus("closed");
|
|
55167
55188
|
}
|
|
55168
55189
|
handleServerMessage(msg) {
|
|
55169
55190
|
if (msg.type === "ack") {
|
|
@@ -55177,6 +55198,13 @@ class BrokerClient {
|
|
|
55177
55198
|
}
|
|
55178
55199
|
return;
|
|
55179
55200
|
}
|
|
55201
|
+
if (msg.type === "peers_list") {
|
|
55202
|
+
const peers = msg.peers ?? [];
|
|
55203
|
+
const resolver = this.listPeersResolvers.shift();
|
|
55204
|
+
if (resolver)
|
|
55205
|
+
resolver(peers);
|
|
55206
|
+
return;
|
|
55207
|
+
}
|
|
55180
55208
|
if (msg.type === "push") {
|
|
55181
55209
|
const nonce = String(msg.nonce ?? "");
|
|
55182
55210
|
const ciphertext = String(msg.ciphertext ?? "");
|
|
@@ -55239,7 +55267,7 @@ class BrokerClient {
|
|
|
55239
55267
|
send();
|
|
55240
55268
|
}
|
|
55241
55269
|
scheduleReconnect() {
|
|
55242
|
-
this.
|
|
55270
|
+
this.setConnStatus("reconnecting");
|
|
55243
55271
|
const delay = BACKOFF_CAPS[Math.min(this.reconnectAttempt, BACKOFF_CAPS.length - 1)];
|
|
55244
55272
|
this.reconnectAttempt += 1;
|
|
55245
55273
|
this.debug(`reconnect in ${delay}ms (attempt ${this.reconnectAttempt})`);
|
|
@@ -55251,7 +55279,7 @@ class BrokerClient {
|
|
|
55251
55279
|
});
|
|
55252
55280
|
}, delay);
|
|
55253
55281
|
}
|
|
55254
|
-
|
|
55282
|
+
setConnStatus(s) {
|
|
55255
55283
|
if (this._status === s)
|
|
55256
55284
|
return;
|
|
55257
55285
|
this._status = s;
|
|
@@ -55311,26 +55339,51 @@ function text(msg, isError = false) {
|
|
|
55311
55339
|
...isError ? { isError: true } : {}
|
|
55312
55340
|
};
|
|
55313
55341
|
}
|
|
55314
|
-
function resolveClient(to) {
|
|
55342
|
+
async function resolveClient(to) {
|
|
55315
55343
|
const clients2 = allClients();
|
|
55316
55344
|
if (clients2.length === 0) {
|
|
55317
55345
|
return { client: null, targetSpec: to, error: "no meshes joined" };
|
|
55318
55346
|
}
|
|
55347
|
+
let targetClients = clients2;
|
|
55348
|
+
let target = to;
|
|
55319
55349
|
const colonIdx = to.indexOf(":");
|
|
55320
55350
|
if (colonIdx > 0 && colonIdx < to.length - 1) {
|
|
55321
55351
|
const slug = to.slice(0, colonIdx);
|
|
55322
55352
|
const rest = to.slice(colonIdx + 1);
|
|
55323
55353
|
const match = findClient(slug);
|
|
55354
|
+
if (match) {
|
|
55355
|
+
targetClients = [match];
|
|
55356
|
+
target = rest;
|
|
55357
|
+
}
|
|
55358
|
+
}
|
|
55359
|
+
if (/^[0-9a-f]{64}$/.test(target) || target.startsWith("#") || target === "*") {
|
|
55360
|
+
if (targetClients.length === 1) {
|
|
55361
|
+
return { client: targetClients[0], targetSpec: target };
|
|
55362
|
+
}
|
|
55363
|
+
return {
|
|
55364
|
+
client: null,
|
|
55365
|
+
targetSpec: target,
|
|
55366
|
+
error: `multiple meshes joined; prefix target with "<mesh-slug>:" (joined: ${clients2.map((c) => c.meshSlug).join(", ")})`
|
|
55367
|
+
};
|
|
55368
|
+
}
|
|
55369
|
+
const nameLower = target.toLowerCase();
|
|
55370
|
+
for (const c of targetClients) {
|
|
55371
|
+
const peers = await c.listPeers();
|
|
55372
|
+
const match = peers.find((p) => p.displayName.toLowerCase() === nameLower);
|
|
55324
55373
|
if (match)
|
|
55325
|
-
return { client:
|
|
55374
|
+
return { client: c, targetSpec: match.pubkey };
|
|
55375
|
+
const partials = peers.filter((p) => p.displayName.toLowerCase().includes(nameLower));
|
|
55376
|
+
if (partials.length === 1) {
|
|
55377
|
+
return { client: c, targetSpec: partials[0].pubkey };
|
|
55378
|
+
}
|
|
55326
55379
|
}
|
|
55327
|
-
if (
|
|
55328
|
-
return { client:
|
|
55380
|
+
if (targetClients.length === 1) {
|
|
55381
|
+
return { client: targetClients[0], targetSpec: target };
|
|
55329
55382
|
}
|
|
55330
55383
|
return {
|
|
55331
55384
|
client: null,
|
|
55332
|
-
targetSpec:
|
|
55333
|
-
error: `
|
|
55385
|
+
targetSpec: target,
|
|
55386
|
+
error: `peer "${target}" not found in any mesh (joined: ${clients2.map((c) => c.meshSlug).join(", ")})`
|
|
55334
55387
|
};
|
|
55335
55388
|
}
|
|
55336
55389
|
function decryptFailedWarning(senderPubkey) {
|
|
@@ -55357,7 +55410,7 @@ Read the from_id, from_name, mesh_slug, and priority attributes to understand co
|
|
|
55357
55410
|
|
|
55358
55411
|
Available tools:
|
|
55359
55412
|
- list_peers: see joined meshes + their connection status
|
|
55360
|
-
- send_message: send to a peer pubkey, channel, or broadcast (priority: now/next/low)
|
|
55413
|
+
- send_message: send to a peer by display name, pubkey, #channel, or * broadcast (priority: now/next/low)
|
|
55361
55414
|
- check_messages: drain buffered inbound messages (usually auto-pushed)
|
|
55362
55415
|
- set_summary: 1-2 sentence summary of what you're working on
|
|
55363
55416
|
- set_status: manually override your status (idle/working/dnd)
|
|
@@ -55382,7 +55435,7 @@ If you have multiple joined meshes, prefix the \`to\` argument of send_message w
|
|
|
55382
55435
|
const { to, message, priority } = args ?? {};
|
|
55383
55436
|
if (!to || !message)
|
|
55384
55437
|
return text("send_message: `to` and `message` required", true);
|
|
55385
|
-
const { client, targetSpec, error: error46 } = resolveClient(to);
|
|
55438
|
+
const { client, targetSpec, error: error46 } = await resolveClient(to);
|
|
55386
55439
|
if (!client)
|
|
55387
55440
|
return text(`send_message: ${error46 ?? "no client resolved"}`, true);
|
|
55388
55441
|
const result = await client.send(targetSpec, message, priority ?? "next");
|
|
@@ -55395,12 +55448,26 @@ If you have multiple joined meshes, prefix the \`to\` argument of send_message w
|
|
|
55395
55448
|
const clients2 = mesh_slug ? [findClient(mesh_slug)].filter(Boolean) : allClients();
|
|
55396
55449
|
if (clients2.length === 0)
|
|
55397
55450
|
return text(mesh_slug ? `list_peers: no joined mesh "${mesh_slug}"` : "list_peers: no joined meshes", true);
|
|
55398
|
-
const
|
|
55399
|
-
|
|
55400
|
-
|
|
55401
|
-
|
|
55451
|
+
const sections = [];
|
|
55452
|
+
for (const c of clients2) {
|
|
55453
|
+
const peers = await c.listPeers();
|
|
55454
|
+
const header = `## ${c.meshSlug} (${c.status}, mesh ${c.meshId.slice(0, 8)}…)`;
|
|
55455
|
+
if (peers.length === 0) {
|
|
55456
|
+
sections.push(`${header}
|
|
55457
|
+
No peers connected.`);
|
|
55458
|
+
} else {
|
|
55459
|
+
const peerLines = peers.map((p) => {
|
|
55460
|
+
const summary = p.summary ? ` — "${p.summary}"` : "";
|
|
55461
|
+
return `- **${p.displayName}** [${p.status}] (${p.pubkey.slice(0, 12)}…)${summary}`;
|
|
55462
|
+
});
|
|
55463
|
+
sections.push(`${header}
|
|
55464
|
+
${peerLines.join(`
|
|
55465
|
+
`)}`);
|
|
55466
|
+
}
|
|
55467
|
+
}
|
|
55468
|
+
return text(sections.join(`
|
|
55402
55469
|
|
|
55403
|
-
|
|
55470
|
+
`));
|
|
55404
55471
|
}
|
|
55405
55472
|
case "check_messages": {
|
|
55406
55473
|
const drained = [];
|
|
@@ -55423,7 +55490,9 @@ ${drained.join(`
|
|
|
55423
55490
|
const { summary } = args ?? {};
|
|
55424
55491
|
if (!summary)
|
|
55425
55492
|
return text("set_summary: `summary` required", true);
|
|
55426
|
-
|
|
55493
|
+
for (const c of allClients())
|
|
55494
|
+
await c.setSummary(summary);
|
|
55495
|
+
return text(`Summary set: "${summary}" (visible to ${allClients().length} mesh(es)).`);
|
|
55427
55496
|
}
|
|
55428
55497
|
case "set_status": {
|
|
55429
55498
|
const { status } = args ?? {};
|
|
@@ -55477,6 +55546,7 @@ ${drained.join(`
|
|
|
55477
55546
|
// src/commands/install.ts
|
|
55478
55547
|
import {
|
|
55479
55548
|
chmodSync as chmodSync2,
|
|
55549
|
+
copyFileSync,
|
|
55480
55550
|
existsSync as existsSync2,
|
|
55481
55551
|
mkdirSync as mkdirSync2,
|
|
55482
55552
|
readFileSync as readFileSync2,
|
|
@@ -55504,7 +55574,49 @@ function readClaudeConfig() {
|
|
|
55504
55574
|
throw new Error(`failed to parse ${CLAUDE_CONFIG}: ${e instanceof Error ? e.message : String(e)}`);
|
|
55505
55575
|
}
|
|
55506
55576
|
}
|
|
55507
|
-
function
|
|
55577
|
+
function backupClaudeConfig() {
|
|
55578
|
+
if (!existsSync2(CLAUDE_CONFIG))
|
|
55579
|
+
return;
|
|
55580
|
+
const backupDir = join2(dirname2(CLAUDE_CONFIG), ".claude", "backups");
|
|
55581
|
+
mkdirSync2(backupDir, { recursive: true });
|
|
55582
|
+
const ts = Date.now();
|
|
55583
|
+
const dest = join2(backupDir, `.claude.json.pre-claudemesh.${ts}`);
|
|
55584
|
+
copyFileSync(CLAUDE_CONFIG, dest);
|
|
55585
|
+
}
|
|
55586
|
+
function patchMcpServer(entry) {
|
|
55587
|
+
backupClaudeConfig();
|
|
55588
|
+
const cfg = readClaudeConfig();
|
|
55589
|
+
const servers = cfg.mcpServers ?? {};
|
|
55590
|
+
if (!cfg.mcpServers)
|
|
55591
|
+
cfg.mcpServers = servers;
|
|
55592
|
+
const existing = servers[MCP_NAME];
|
|
55593
|
+
let action;
|
|
55594
|
+
if (!existing) {
|
|
55595
|
+
servers[MCP_NAME] = entry;
|
|
55596
|
+
action = "added";
|
|
55597
|
+
} else if (entriesEqual(existing, entry)) {
|
|
55598
|
+
return "unchanged";
|
|
55599
|
+
} else {
|
|
55600
|
+
servers[MCP_NAME] = entry;
|
|
55601
|
+
action = "updated";
|
|
55602
|
+
}
|
|
55603
|
+
flushClaudeConfig(cfg);
|
|
55604
|
+
return action;
|
|
55605
|
+
}
|
|
55606
|
+
function removeMcpServer() {
|
|
55607
|
+
if (!existsSync2(CLAUDE_CONFIG))
|
|
55608
|
+
return false;
|
|
55609
|
+
backupClaudeConfig();
|
|
55610
|
+
const cfg = readClaudeConfig();
|
|
55611
|
+
const servers = cfg.mcpServers;
|
|
55612
|
+
if (!servers || !(MCP_NAME in servers))
|
|
55613
|
+
return false;
|
|
55614
|
+
delete servers[MCP_NAME];
|
|
55615
|
+
cfg.mcpServers = servers;
|
|
55616
|
+
flushClaudeConfig(cfg);
|
|
55617
|
+
return true;
|
|
55618
|
+
}
|
|
55619
|
+
function flushClaudeConfig(obj) {
|
|
55508
55620
|
mkdirSync2(dirname2(CLAUDE_CONFIG), { recursive: true });
|
|
55509
55621
|
writeFileSync2(CLAUDE_CONFIG, JSON.stringify(obj, null, 2) + `
|
|
55510
55622
|
`, "utf-8");
|
|
@@ -55616,22 +55728,8 @@ function runInstall(args = []) {
|
|
|
55616
55728
|
console.error(`✗ MCP entry not found at ${entry}`);
|
|
55617
55729
|
process.exit(1);
|
|
55618
55730
|
}
|
|
55619
|
-
const cfg = readClaudeConfig();
|
|
55620
|
-
const servers = (cfg.mcpServers ??= {}) ?? {};
|
|
55621
55731
|
const desired = buildMcpEntry(entry);
|
|
55622
|
-
const
|
|
55623
|
-
let action;
|
|
55624
|
-
if (!existing) {
|
|
55625
|
-
servers[MCP_NAME] = desired;
|
|
55626
|
-
action = "added";
|
|
55627
|
-
} else if (entriesEqual(existing, desired)) {
|
|
55628
|
-
action = "unchanged";
|
|
55629
|
-
} else {
|
|
55630
|
-
servers[MCP_NAME] = desired;
|
|
55631
|
-
action = "updated";
|
|
55632
|
-
}
|
|
55633
|
-
cfg.mcpServers = servers;
|
|
55634
|
-
writeClaudeConfig(cfg);
|
|
55732
|
+
const action = patchMcpServer(desired);
|
|
55635
55733
|
const verify = readClaudeConfig();
|
|
55636
55734
|
const verifyServers = verify.mcpServers ?? {};
|
|
55637
55735
|
const stored = verifyServers[MCP_NAME];
|
|
@@ -55674,19 +55772,10 @@ function runInstall(args = []) {
|
|
|
55674
55772
|
function runUninstall() {
|
|
55675
55773
|
console.log("claudemesh uninstall");
|
|
55676
55774
|
console.log("--------------------");
|
|
55677
|
-
if (
|
|
55678
|
-
|
|
55679
|
-
const servers = cfg.mcpServers;
|
|
55680
|
-
if (servers && MCP_NAME in servers) {
|
|
55681
|
-
delete servers[MCP_NAME];
|
|
55682
|
-
cfg.mcpServers = servers;
|
|
55683
|
-
writeClaudeConfig(cfg);
|
|
55684
|
-
console.log(`✓ MCP server "${MCP_NAME}" removed`);
|
|
55685
|
-
} else {
|
|
55686
|
-
console.log(`· MCP server "${MCP_NAME}" not present`);
|
|
55687
|
-
}
|
|
55775
|
+
if (removeMcpServer()) {
|
|
55776
|
+
console.log(`✓ MCP server "${MCP_NAME}" removed`);
|
|
55688
55777
|
} else {
|
|
55689
|
-
console.log(`·
|
|
55778
|
+
console.log(`· MCP server "${MCP_NAME}" not present`);
|
|
55690
55779
|
}
|
|
55691
55780
|
try {
|
|
55692
55781
|
const removed = uninstallHooks();
|
|
@@ -56086,7 +56175,7 @@ import { statSync, existsSync as existsSync3 } from "node:fs";
|
|
|
56086
56175
|
// package.json
|
|
56087
56176
|
var package_default = {
|
|
56088
56177
|
name: "claudemesh-cli",
|
|
56089
|
-
version: "0.1.
|
|
56178
|
+
version: "0.1.6",
|
|
56090
56179
|
description: "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
|
|
56091
56180
|
keywords: [
|
|
56092
56181
|
"claude-code",
|