claudemesh-cli 0.1.15 → 0.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/index.js +113 -12
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6514,7 +6514,7 @@ function loadConfig() {
|
|
|
6514
6514
|
if (!parsed || !Array.isArray(parsed.meshes)) {
|
|
6515
6515
|
return { version: 1, meshes: [] };
|
|
6516
6516
|
}
|
|
6517
|
-
return { version: 1, meshes: parsed.meshes, displayName: parsed.displayName };
|
|
6517
|
+
return { version: 1, meshes: parsed.meshes, displayName: parsed.displayName, groups: parsed.groups };
|
|
6518
6518
|
} catch (e) {
|
|
6519
6519
|
throw new Error(`Failed to load ${CONFIG_PATH}: ${e instanceof Error ? e.message : String(e)}`);
|
|
6520
6520
|
}
|
|
@@ -46245,13 +46245,13 @@ class StdioServerTransport {
|
|
|
46245
46245
|
var TOOLS = [
|
|
46246
46246
|
{
|
|
46247
46247
|
name: "send_message",
|
|
46248
|
-
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.",
|
|
46248
|
+
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, @group, `#channel`, or `*` for broadcast. `priority` controls delivery: `now` bypasses busy gates, `next` waits for idle (default), `low` is pull-only.",
|
|
46249
46249
|
inputSchema: {
|
|
46250
46250
|
type: "object",
|
|
46251
46251
|
properties: {
|
|
46252
46252
|
to: {
|
|
46253
46253
|
type: "string",
|
|
46254
|
-
description: "Peer name, pubkey, or #channel"
|
|
46254
|
+
description: "Peer name, pubkey, @group, or #channel"
|
|
46255
46255
|
},
|
|
46256
46256
|
message: { type: "string", description: "Message text" },
|
|
46257
46257
|
priority: {
|
|
@@ -46306,6 +46306,32 @@ var TOOLS = [
|
|
|
46306
46306
|
},
|
|
46307
46307
|
required: ["status"]
|
|
46308
46308
|
}
|
|
46309
|
+
},
|
|
46310
|
+
{
|
|
46311
|
+
name: "join_group",
|
|
46312
|
+
description: "Join a group with an optional role. Other peers see your group membership in list_peers.",
|
|
46313
|
+
inputSchema: {
|
|
46314
|
+
type: "object",
|
|
46315
|
+
properties: {
|
|
46316
|
+
name: { type: "string", description: "Group name (without @)" },
|
|
46317
|
+
role: {
|
|
46318
|
+
type: "string",
|
|
46319
|
+
description: "Your role in the group (e.g. lead, member, observer)"
|
|
46320
|
+
}
|
|
46321
|
+
},
|
|
46322
|
+
required: ["name"]
|
|
46323
|
+
}
|
|
46324
|
+
},
|
|
46325
|
+
{
|
|
46326
|
+
name: "leave_group",
|
|
46327
|
+
description: "Leave a group.",
|
|
46328
|
+
inputSchema: {
|
|
46329
|
+
type: "object",
|
|
46330
|
+
properties: {
|
|
46331
|
+
name: { type: "string", description: "Group name (without @)" }
|
|
46332
|
+
},
|
|
46333
|
+
required: ["name"]
|
|
46334
|
+
}
|
|
46309
46335
|
}
|
|
46310
46336
|
];
|
|
46311
46337
|
|
|
@@ -46590,6 +46616,16 @@ class BrokerClient {
|
|
|
46590
46616
|
return;
|
|
46591
46617
|
this.ws.send(JSON.stringify({ type: "set_summary", summary }));
|
|
46592
46618
|
}
|
|
46619
|
+
async joinGroup(name, role) {
|
|
46620
|
+
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
46621
|
+
return;
|
|
46622
|
+
this.ws.send(JSON.stringify({ type: "join_group", name, role }));
|
|
46623
|
+
}
|
|
46624
|
+
async leaveGroup(name) {
|
|
46625
|
+
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
46626
|
+
return;
|
|
46627
|
+
this.ws.send(JSON.stringify({ type: "leave_group", name }));
|
|
46628
|
+
}
|
|
46593
46629
|
close() {
|
|
46594
46630
|
this.closed = true;
|
|
46595
46631
|
if (this.helloTimer)
|
|
@@ -46786,7 +46822,7 @@ async function resolveClient(to) {
|
|
|
46786
46822
|
target = rest;
|
|
46787
46823
|
}
|
|
46788
46824
|
}
|
|
46789
|
-
if (/^[0-9a-f]{64}$/.test(target) || target.startsWith("#") || target === "*") {
|
|
46825
|
+
if (/^[0-9a-f]{64}$/.test(target) || target.startsWith("#") || target.startsWith("@") || target === "*") {
|
|
46790
46826
|
if (targetClients.length === 1) {
|
|
46791
46827
|
return { client: targetClients[0], targetSpec: target };
|
|
46792
46828
|
}
|
|
@@ -46852,14 +46888,16 @@ async function startMcpServer() {
|
|
|
46852
46888
|
|
|
46853
46889
|
IMPORTANT: When you receive a <channel source="claudemesh" ...> message, RESPOND IMMEDIATELY. Do not wait until your current task is finished. Pause what you are doing, reply to the message using send_message, then resume your work. Treat incoming peer messages like a coworker tapping you on the shoulder — answer right away, even if you're in the middle of something.
|
|
46854
46890
|
|
|
46855
|
-
Read the from_id, from_name, mesh_slug, and priority attributes to understand context. Reply by calling send_message with to set to the from_name (display name) of the sender.
|
|
46891
|
+
Read the from_id, from_name, mesh_slug, and priority attributes to understand context. Reply by calling send_message with to set to the from_name (display name) of the sender. The \`to\` field can be a peer name, pubkey, @group, or * for broadcast.
|
|
46856
46892
|
|
|
46857
46893
|
Available tools:
|
|
46858
46894
|
- list_peers: see joined meshes + their connection status
|
|
46859
|
-
- send_message: send to a peer by display name, pubkey, #channel, or * broadcast (priority: now/next/low)
|
|
46895
|
+
- send_message: send to a peer by display name, pubkey, @group, #channel, or * broadcast (priority: now/next/low)
|
|
46860
46896
|
- check_messages: drain buffered inbound messages (usually auto-pushed)
|
|
46861
46897
|
- set_summary: 1-2 sentence summary of what you're working on
|
|
46862
46898
|
- set_status: manually override your status (idle/working/dnd)
|
|
46899
|
+
- join_group: join a @group with optional role
|
|
46900
|
+
- leave_group: leave a @group
|
|
46863
46901
|
|
|
46864
46902
|
Message priority:
|
|
46865
46903
|
- "now": delivered immediately regardless of recipient status (use sparingly)
|
|
@@ -46904,7 +46942,8 @@ No peers connected.`);
|
|
|
46904
46942
|
} else {
|
|
46905
46943
|
const peerLines = peers.map((p) => {
|
|
46906
46944
|
const summary = p.summary ? ` — "${p.summary}"` : "";
|
|
46907
|
-
|
|
46945
|
+
const groupsStr = p.groups?.length ? ` [${p.groups.map((g) => `@${g.name}${g.role ? ":" + g.role : ""}`).join(", ")}]` : "";
|
|
46946
|
+
return `- **${p.displayName}** [${p.status}]${groupsStr} (${p.pubkey.slice(0, 12)}…)${summary}`;
|
|
46908
46947
|
});
|
|
46909
46948
|
sections.push(`${header}
|
|
46910
46949
|
${peerLines.join(`
|
|
@@ -46949,6 +46988,22 @@ ${drained.join(`
|
|
|
46949
46988
|
await c.setStatus(s);
|
|
46950
46989
|
return text(`Status set to ${s} across ${allClients().length} mesh(es).`);
|
|
46951
46990
|
}
|
|
46991
|
+
case "join_group": {
|
|
46992
|
+
const { name: groupName, role } = args ?? {};
|
|
46993
|
+
if (!groupName)
|
|
46994
|
+
return text("join_group: `name` required", true);
|
|
46995
|
+
for (const c of allClients())
|
|
46996
|
+
await c.joinGroup(groupName, role);
|
|
46997
|
+
return text(`Joined @${groupName}${role ? ` as ${role}` : ""}`);
|
|
46998
|
+
}
|
|
46999
|
+
case "leave_group": {
|
|
47000
|
+
const { name: groupName } = args ?? {};
|
|
47001
|
+
if (!groupName)
|
|
47002
|
+
return text("leave_group: `name` required", true);
|
|
47003
|
+
for (const c of allClients())
|
|
47004
|
+
await c.leaveGroup(groupName);
|
|
47005
|
+
return text(`Left @${groupName}`);
|
|
47006
|
+
}
|
|
46952
47007
|
default:
|
|
46953
47008
|
return text(`Unknown tool: ${name}`, true);
|
|
46954
47009
|
}
|
|
@@ -47582,6 +47637,8 @@ import { createInterface } from "node:readline";
|
|
|
47582
47637
|
function parseArgs(argv) {
|
|
47583
47638
|
const result = {
|
|
47584
47639
|
name: null,
|
|
47640
|
+
role: null,
|
|
47641
|
+
groups: null,
|
|
47585
47642
|
joinLink: null,
|
|
47586
47643
|
meshSlug: null,
|
|
47587
47644
|
quiet: false,
|
|
@@ -47595,6 +47652,14 @@ function parseArgs(argv) {
|
|
|
47595
47652
|
result.name = argv[++i];
|
|
47596
47653
|
} else if (arg.startsWith("--name=")) {
|
|
47597
47654
|
result.name = arg.slice("--name=".length);
|
|
47655
|
+
} else if (arg === "--role" && i + 1 < argv.length) {
|
|
47656
|
+
result.role = argv[++i];
|
|
47657
|
+
} else if (arg.startsWith("--role=")) {
|
|
47658
|
+
result.role = arg.slice("--role=".length);
|
|
47659
|
+
} else if (arg === "--groups" && i + 1 < argv.length) {
|
|
47660
|
+
result.groups = argv[++i];
|
|
47661
|
+
} else if (arg.startsWith("--groups=")) {
|
|
47662
|
+
result.groups = arg.slice("--groups=".length);
|
|
47598
47663
|
} else if (arg === "--join" && i + 1 < argv.length) {
|
|
47599
47664
|
result.joinLink = argv[++i];
|
|
47600
47665
|
} else if (arg.startsWith("--join=")) {
|
|
@@ -47640,6 +47705,23 @@ async function pickMesh(meshes) {
|
|
|
47640
47705
|
});
|
|
47641
47706
|
});
|
|
47642
47707
|
}
|
|
47708
|
+
function parseGroupsString(raw) {
|
|
47709
|
+
return raw.split(",").map((s) => s.trim()).filter(Boolean).map((token) => {
|
|
47710
|
+
const idx = token.indexOf(":");
|
|
47711
|
+
if (idx === -1)
|
|
47712
|
+
return { name: token };
|
|
47713
|
+
return { name: token.slice(0, idx), role: token.slice(idx + 1) };
|
|
47714
|
+
});
|
|
47715
|
+
}
|
|
47716
|
+
function askLine(prompt) {
|
|
47717
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
47718
|
+
return new Promise((resolve2) => {
|
|
47719
|
+
rl.question(prompt, (answer) => {
|
|
47720
|
+
rl.close();
|
|
47721
|
+
resolve2(answer.trim());
|
|
47722
|
+
});
|
|
47723
|
+
});
|
|
47724
|
+
}
|
|
47643
47725
|
async function confirmPermissions() {
|
|
47644
47726
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
47645
47727
|
const bold = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
@@ -47671,12 +47753,14 @@ async function confirmPermissions() {
|
|
|
47671
47753
|
});
|
|
47672
47754
|
});
|
|
47673
47755
|
}
|
|
47674
|
-
function printBanner(name, meshSlug) {
|
|
47756
|
+
function printBanner(name, meshSlug, role, groups) {
|
|
47675
47757
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
47676
47758
|
const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
47677
47759
|
const bold = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
47760
|
+
const roleSuffix = role ? ` (${role})` : "";
|
|
47761
|
+
const groupTags = groups.length ? " [" + groups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`).join(", ") + "]" : "";
|
|
47678
47762
|
const rule = "─".repeat(60);
|
|
47679
|
-
console.log(bold(`claudemesh launch`) + dim(` — as ${name} on ${meshSlug}`));
|
|
47763
|
+
console.log(bold(`claudemesh launch`) + dim(` — as ${name}${roleSuffix} on ${meshSlug}${groupTags}`));
|
|
47680
47764
|
console.log(rule);
|
|
47681
47765
|
console.log("Peer messages arrive as <channel> reminders in real-time.");
|
|
47682
47766
|
console.log("Peers send text only — they cannot call tools or read files.");
|
|
@@ -47731,6 +47815,22 @@ async function runLaunch(extraArgs) {
|
|
|
47731
47815
|
mesh = await pickMesh(config2.meshes);
|
|
47732
47816
|
}
|
|
47733
47817
|
const displayName = args.name ?? `${hostname2()}-${process.pid}`;
|
|
47818
|
+
let role = args.role;
|
|
47819
|
+
let parsedGroups = args.groups ? parseGroupsString(args.groups) : [];
|
|
47820
|
+
if (!args.quiet) {
|
|
47821
|
+
if (role === null) {
|
|
47822
|
+
const answer = await askLine(" Role (optional): ");
|
|
47823
|
+
if (answer)
|
|
47824
|
+
role = answer;
|
|
47825
|
+
}
|
|
47826
|
+
if (parsedGroups.length === 0 && args.groups === null) {
|
|
47827
|
+
const answer = await askLine(" Groups (comma-separated, optional): ");
|
|
47828
|
+
if (answer)
|
|
47829
|
+
parsedGroups = parseGroupsString(answer);
|
|
47830
|
+
}
|
|
47831
|
+
if (role || parsedGroups.length)
|
|
47832
|
+
console.log("");
|
|
47833
|
+
}
|
|
47734
47834
|
const tmpBase = tmpdir();
|
|
47735
47835
|
try {
|
|
47736
47836
|
for (const entry of readdirSync(tmpBase)) {
|
|
@@ -47746,12 +47846,13 @@ async function runLaunch(extraArgs) {
|
|
|
47746
47846
|
const sessionConfig = {
|
|
47747
47847
|
version: 1,
|
|
47748
47848
|
meshes: [mesh],
|
|
47749
|
-
displayName
|
|
47849
|
+
displayName,
|
|
47850
|
+
...parsedGroups.length > 0 ? { groups: parsedGroups } : {}
|
|
47750
47851
|
};
|
|
47751
47852
|
writeFileSync4(join4(tmpDir, "config.json"), JSON.stringify(sessionConfig, null, 2) + `
|
|
47752
47853
|
`, "utf-8");
|
|
47753
47854
|
if (!args.quiet) {
|
|
47754
|
-
printBanner(displayName, mesh.slug);
|
|
47855
|
+
printBanner(displayName, mesh.slug, role, parsedGroups);
|
|
47755
47856
|
if (!args.skipPermConfirm) {
|
|
47756
47857
|
await confirmPermissions();
|
|
47757
47858
|
}
|
|
@@ -47819,7 +47920,7 @@ init_config();
|
|
|
47819
47920
|
// package.json
|
|
47820
47921
|
var package_default = {
|
|
47821
47922
|
name: "claudemesh-cli",
|
|
47822
|
-
version: "0.
|
|
47923
|
+
version: "0.2.0",
|
|
47823
47924
|
description: "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
|
|
47824
47925
|
keywords: [
|
|
47825
47926
|
"claude-code",
|