claudemesh-cli 1.0.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -88,7 +88,7 @@ __export(exports_urls, {
88
88
  VERSION: () => VERSION,
89
89
  URLS: () => URLS
90
90
  });
91
- var URLS, VERSION = "1.0.3", env;
91
+ var URLS, VERSION = "1.2.0", env;
92
92
  var init_urls = __esm(() => {
93
93
  URLS = {
94
94
  BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
@@ -6392,11 +6392,136 @@ var init_ban = __esm(() => {
6392
6392
  init_exit_codes();
6393
6393
  });
6394
6394
 
6395
+ // src/services/bridge/protocol.ts
6396
+ import { homedir as homedir4 } from "node:os";
6397
+ import { join as join4 } from "node:path";
6398
+ function socketPath(meshSlug) {
6399
+ return join4(homedir4(), ".claudemesh", "sockets", `${meshSlug}.sock`);
6400
+ }
6401
+ function socketDir() {
6402
+ return join4(homedir4(), ".claudemesh", "sockets");
6403
+ }
6404
+ function frame(obj) {
6405
+ return JSON.stringify(obj) + `
6406
+ `;
6407
+ }
6408
+
6409
+ class LineParser {
6410
+ buf = "";
6411
+ feed(chunk) {
6412
+ this.buf += typeof chunk === "string" ? chunk : chunk.toString("utf-8");
6413
+ const lines = [];
6414
+ let nl = this.buf.indexOf(`
6415
+ `);
6416
+ while (nl !== -1) {
6417
+ lines.push(this.buf.slice(0, nl));
6418
+ this.buf = this.buf.slice(nl + 1);
6419
+ nl = this.buf.indexOf(`
6420
+ `);
6421
+ }
6422
+ return lines;
6423
+ }
6424
+ }
6425
+ var init_protocol = () => {};
6426
+
6427
+ // src/services/bridge/client.ts
6428
+ import { createConnection } from "node:net";
6429
+ import { existsSync as existsSync5 } from "node:fs";
6430
+ import { randomUUID as randomUUID2 } from "node:crypto";
6431
+ async function tryBridge(meshSlug, verb, args = {}, timeoutMs = DEFAULT_TIMEOUT_MS) {
6432
+ const path = socketPath(meshSlug);
6433
+ if (!existsSync5(path))
6434
+ return null;
6435
+ return new Promise((resolve) => {
6436
+ const id = randomUUID2();
6437
+ const req = { id, verb, args };
6438
+ const parser = new LineParser;
6439
+ let settled = false;
6440
+ const finish = (value) => {
6441
+ if (settled)
6442
+ return;
6443
+ settled = true;
6444
+ try {
6445
+ socket.destroy();
6446
+ } catch {}
6447
+ clearTimeout(timer);
6448
+ resolve(value);
6449
+ };
6450
+ const socket = createConnection({ path });
6451
+ const timer = setTimeout(() => {
6452
+ finish(null);
6453
+ }, timeoutMs);
6454
+ socket.on("connect", () => {
6455
+ try {
6456
+ socket.write(frame(req));
6457
+ } catch {
6458
+ finish(null);
6459
+ }
6460
+ });
6461
+ socket.on("data", (chunk) => {
6462
+ const lines = parser.feed(chunk);
6463
+ for (const line of lines) {
6464
+ if (!line.trim())
6465
+ continue;
6466
+ let res;
6467
+ try {
6468
+ res = JSON.parse(line);
6469
+ } catch {
6470
+ continue;
6471
+ }
6472
+ if (res.id !== id)
6473
+ continue;
6474
+ if (res.ok)
6475
+ finish({ ok: true, result: res.result });
6476
+ else
6477
+ finish({ ok: false, error: res.error });
6478
+ return;
6479
+ }
6480
+ });
6481
+ socket.on("error", (err) => {
6482
+ const code = err.code;
6483
+ if (code === "ECONNREFUSED" || code === "ENOENT" || code === "EPERM") {
6484
+ finish(null);
6485
+ } else {
6486
+ finish(null);
6487
+ }
6488
+ });
6489
+ socket.on("close", () => {
6490
+ finish(null);
6491
+ });
6492
+ });
6493
+ }
6494
+ var DEFAULT_TIMEOUT_MS = 5000;
6495
+ var init_client3 = __esm(() => {
6496
+ init_protocol();
6497
+ });
6498
+
6395
6499
  // src/commands/peers.ts
6396
6500
  var exports_peers = {};
6397
6501
  __export(exports_peers, {
6398
6502
  runPeers: () => runPeers
6399
6503
  });
6504
+ function projectFields(record, fields) {
6505
+ const out = {};
6506
+ for (const f of fields) {
6507
+ const sourceKey = FIELD_ALIAS[f] ?? f;
6508
+ out[f] = record[sourceKey];
6509
+ }
6510
+ return out;
6511
+ }
6512
+ async function listPeersForMesh(slug) {
6513
+ const bridged = await tryBridge(slug, "peers");
6514
+ if (bridged && bridged.ok) {
6515
+ return bridged.result;
6516
+ }
6517
+ let result = [];
6518
+ await withMesh({ meshSlug: slug }, async (client) => {
6519
+ const all = await client.listPeers();
6520
+ const selfPubkey = client.getSessionPubkey();
6521
+ result = selfPubkey ? all.filter((p) => p.pubkey !== selfPubkey) : all;
6522
+ });
6523
+ return result;
6524
+ }
6400
6525
  async function runPeers(flags) {
6401
6526
  const config = readConfig();
6402
6527
  const slugs = flags.mesh ? [flags.mesh] : config.meshes.map((m) => m.slug);
@@ -6405,55 +6530,59 @@ async function runPeers(flags) {
6405
6530
  render.hint("claudemesh <invite-url> # join + launch");
6406
6531
  process.exit(1);
6407
6532
  }
6533
+ const fieldList = typeof flags.json === "string" && flags.json.length > 0 ? flags.json.split(",").map((s) => s.trim()).filter(Boolean) : null;
6534
+ const wantsJson = flags.json !== undefined && flags.json !== false;
6408
6535
  const allJson = [];
6409
6536
  for (const slug of slugs) {
6410
6537
  try {
6411
- await withMesh({ meshSlug: slug }, async (client, mesh) => {
6412
- const allPeers = await client.listPeers();
6413
- const selfPubkey = client.getSessionPubkey();
6414
- const peers = selfPubkey ? allPeers.filter((p) => p.pubkey !== selfPubkey) : allPeers;
6415
- if (flags.json) {
6416
- allJson.push({ mesh: mesh.slug, peers });
6417
- return;
6418
- }
6419
- render.section(`peers on ${mesh.slug} (${peers.length})`);
6420
- if (peers.length === 0) {
6421
- render.info(dim(" (no peers connected)"));
6422
- return;
6423
- }
6424
- for (const p of peers) {
6425
- const groups = p.groups.length ? " [" + p.groups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`).join(", ") + "]" : "";
6426
- const statusDot = p.status === "working" ? yellow("●") : green("●");
6427
- const name = bold(p.displayName);
6428
- const meta = [];
6429
- if (p.peerType)
6430
- meta.push(p.peerType);
6431
- if (p.channel)
6432
- meta.push(p.channel);
6433
- if (p.model)
6434
- meta.push(p.model);
6435
- const metaStr = meta.length ? dim(` (${meta.join(", ")})`) : "";
6436
- const summary = p.summary ? dim(` — ${p.summary}`) : "";
6437
- const pubkeyTag = dim(` · ${p.pubkey.slice(0, 16)}…`);
6438
- render.info(`${statusDot} ${name}${groups}${metaStr}${pubkeyTag}${summary}`);
6439
- if (p.cwd)
6440
- render.info(dim(` cwd: ${p.cwd}`));
6441
- }
6442
- });
6538
+ const peers = await listPeersForMesh(slug);
6539
+ if (wantsJson) {
6540
+ const projected = fieldList ? peers.map((p) => projectFields(p, fieldList)) : peers;
6541
+ allJson.push({ mesh: slug, peers: projected });
6542
+ continue;
6543
+ }
6544
+ render.section(`peers on ${slug} (${peers.length})`);
6545
+ if (peers.length === 0) {
6546
+ render.info(dim(" (no peers connected)"));
6547
+ continue;
6548
+ }
6549
+ for (const p of peers) {
6550
+ const groups = p.groups.length ? " [" + p.groups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`).join(", ") + "]" : "";
6551
+ const statusDot = p.status === "working" ? yellow("●") : green("●");
6552
+ const name = bold(p.displayName);
6553
+ const meta = [];
6554
+ if (p.peerType)
6555
+ meta.push(p.peerType);
6556
+ if (p.channel)
6557
+ meta.push(p.channel);
6558
+ if (p.model)
6559
+ meta.push(p.model);
6560
+ const metaStr = meta.length ? dim(` (${meta.join(", ")})`) : "";
6561
+ const summary = p.summary ? dim(` — ${p.summary}`) : "";
6562
+ const pubkeyTag = dim(` · ${p.pubkey.slice(0, 16)}…`);
6563
+ render.info(`${statusDot} ${name}${groups}${metaStr}${pubkeyTag}${summary}`);
6564
+ if (p.cwd)
6565
+ render.info(dim(` cwd: ${p.cwd}`));
6566
+ }
6443
6567
  } catch (e) {
6444
6568
  render.err(`${slug}: ${e instanceof Error ? e.message : String(e)}`);
6445
6569
  }
6446
6570
  }
6447
- if (flags.json) {
6571
+ if (wantsJson) {
6448
6572
  process.stdout.write(JSON.stringify(slugs.length === 1 ? allJson[0]?.peers : allJson, null, 2) + `
6449
6573
  `);
6450
6574
  }
6451
6575
  }
6576
+ var FIELD_ALIAS;
6452
6577
  var init_peers = __esm(() => {
6453
6578
  init_connect();
6454
6579
  init_facade();
6580
+ init_client3();
6455
6581
  init_render();
6456
6582
  init_styles();
6583
+ FIELD_ALIAS = {
6584
+ name: "displayName"
6585
+ };
6457
6586
  });
6458
6587
 
6459
6588
  // src/commands/send.ts
@@ -6462,7 +6591,33 @@ __export(exports_send, {
6462
6591
  runSend: () => runSend
6463
6592
  });
6464
6593
  async function runSend(flags, to, message) {
6594
+ if (!to || !message) {
6595
+ render.err("Usage: claudemesh send <to> <message>");
6596
+ process.exit(1);
6597
+ }
6465
6598
  const priority = flags.priority === "now" ? "now" : flags.priority === "low" ? "low" : "next";
6599
+ const config = readConfig();
6600
+ const meshSlug = flags.mesh ?? (config.meshes.length === 1 ? config.meshes[0].slug : null);
6601
+ if (meshSlug) {
6602
+ const bridged = await tryBridge(meshSlug, "send", { to, message, priority });
6603
+ if (bridged !== null) {
6604
+ if (bridged.ok) {
6605
+ const r = bridged.result;
6606
+ if (flags.json) {
6607
+ console.log(JSON.stringify({ ok: true, messageId: r.messageId, target: to }));
6608
+ } else {
6609
+ render.ok(`sent to ${to}`, r.messageId ? dim(r.messageId.slice(0, 8)) : undefined);
6610
+ }
6611
+ return;
6612
+ }
6613
+ if (flags.json) {
6614
+ console.log(JSON.stringify({ ok: false, error: bridged.error }));
6615
+ } else {
6616
+ render.err(`send failed: ${bridged.error}`);
6617
+ }
6618
+ process.exit(1);
6619
+ }
6620
+ }
6466
6621
  await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
6467
6622
  let targetSpec = to;
6468
6623
  if (!to.startsWith("@") && to !== "*" && !/^[0-9a-f]{64}$/i.test(to)) {
@@ -6470,22 +6625,34 @@ async function runSend(flags, to, message) {
6470
6625
  const match = peers.find((p) => p.displayName.toLowerCase() === to.toLowerCase());
6471
6626
  if (!match) {
6472
6627
  const names = peers.map((p) => p.displayName).join(", ");
6473
- console.error(`Peer "${to}" not found. Online: ${names || "(none)"}`);
6628
+ render.err(`Peer "${to}" not found.`, `online: ${names || "(none)"}`);
6474
6629
  process.exit(1);
6475
6630
  }
6476
6631
  targetSpec = match.pubkey;
6477
6632
  }
6478
6633
  const result = await client.send(targetSpec, message, priority);
6479
6634
  if (result.ok) {
6480
- console.log(`✓ Sent to ${to}${result.messageId ? ` (${result.messageId.slice(0, 8)})` : ""}`);
6635
+ if (flags.json) {
6636
+ console.log(JSON.stringify({ ok: true, messageId: result.messageId, target: to }));
6637
+ } else {
6638
+ render.ok(`sent to ${to}`, result.messageId ? dim(result.messageId.slice(0, 8)) : undefined);
6639
+ }
6481
6640
  } else {
6482
- console.error(`✗ Send failed: ${result.error ?? "unknown error"}`);
6641
+ if (flags.json) {
6642
+ console.log(JSON.stringify({ ok: false, error: result.error ?? "unknown" }));
6643
+ } else {
6644
+ render.err(`send failed: ${result.error ?? "unknown error"}`);
6645
+ }
6483
6646
  process.exit(1);
6484
6647
  }
6485
6648
  });
6486
6649
  }
6487
6650
  var init_send = __esm(() => {
6488
6651
  init_connect();
6652
+ init_facade();
6653
+ init_client3();
6654
+ init_render();
6655
+ init_styles();
6489
6656
  });
6490
6657
 
6491
6658
  // src/commands/inbox.ts
@@ -6715,6 +6882,313 @@ var init_recall = __esm(() => {
6715
6882
  init_exit_codes();
6716
6883
  });
6717
6884
 
6885
+ // src/commands/broker-actions.ts
6886
+ var exports_broker_actions = {};
6887
+ __export(exports_broker_actions, {
6888
+ runVisible: () => runVisible,
6889
+ runTaskComplete: () => runTaskComplete,
6890
+ runTaskClaim: () => runTaskClaim,
6891
+ runSummary: () => runSummary,
6892
+ runStatusSet: () => runStatusSet,
6893
+ runStats: () => runStats,
6894
+ runPing: () => runPing,
6895
+ runMsgStatus: () => runMsgStatus,
6896
+ runGroupLeave: () => runGroupLeave,
6897
+ runGroupJoin: () => runGroupJoin,
6898
+ runForget: () => runForget,
6899
+ runClock: () => runClock
6900
+ });
6901
+ function unambiguousMesh(opts) {
6902
+ if (opts.mesh)
6903
+ return opts.mesh;
6904
+ const config = readConfig();
6905
+ return config.meshes.length === 1 ? config.meshes[0].slug : null;
6906
+ }
6907
+ async function runStatusSet(state, opts) {
6908
+ const valid = ["idle", "working", "dnd"];
6909
+ if (!valid.includes(state)) {
6910
+ render.err(`Invalid status: ${state}`, `must be one of: ${valid.join(", ")}`);
6911
+ return EXIT.INVALID_ARGS;
6912
+ }
6913
+ const meshSlug = unambiguousMesh(opts);
6914
+ if (meshSlug) {
6915
+ const bridged = await tryBridge(meshSlug, "status_set", { status: state });
6916
+ if (bridged !== null) {
6917
+ if (bridged.ok) {
6918
+ if (opts.json)
6919
+ console.log(JSON.stringify({ status: state }));
6920
+ else
6921
+ render.ok(`status set to ${bold(state)}`);
6922
+ return EXIT.SUCCESS;
6923
+ }
6924
+ render.err(bridged.error);
6925
+ return EXIT.INTERNAL_ERROR;
6926
+ }
6927
+ }
6928
+ await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
6929
+ await client.setStatus(state);
6930
+ });
6931
+ if (opts.json)
6932
+ console.log(JSON.stringify({ status: state }));
6933
+ else
6934
+ render.ok(`status set to ${bold(state)}`);
6935
+ return EXIT.SUCCESS;
6936
+ }
6937
+ async function runSummary(text, opts) {
6938
+ if (!text) {
6939
+ render.err("Usage: claudemesh summary <text>");
6940
+ return EXIT.INVALID_ARGS;
6941
+ }
6942
+ const meshSlug = unambiguousMesh(opts);
6943
+ if (meshSlug) {
6944
+ const bridged = await tryBridge(meshSlug, "summary", { summary: text });
6945
+ if (bridged !== null) {
6946
+ if (bridged.ok) {
6947
+ if (opts.json)
6948
+ console.log(JSON.stringify({ summary: text }));
6949
+ else
6950
+ render.ok("summary set", dim(text));
6951
+ return EXIT.SUCCESS;
6952
+ }
6953
+ render.err(bridged.error);
6954
+ return EXIT.INTERNAL_ERROR;
6955
+ }
6956
+ }
6957
+ await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
6958
+ await client.setSummary(text);
6959
+ });
6960
+ if (opts.json)
6961
+ console.log(JSON.stringify({ summary: text }));
6962
+ else
6963
+ render.ok("summary set", dim(text));
6964
+ return EXIT.SUCCESS;
6965
+ }
6966
+ async function runVisible(value, opts) {
6967
+ let visible;
6968
+ if (value === "true" || value === "1" || value === "yes")
6969
+ visible = true;
6970
+ else if (value === "false" || value === "0" || value === "no")
6971
+ visible = false;
6972
+ else {
6973
+ render.err("Usage: claudemesh visible <true|false>");
6974
+ return EXIT.INVALID_ARGS;
6975
+ }
6976
+ const meshSlug = unambiguousMesh(opts);
6977
+ if (meshSlug) {
6978
+ const bridged = await tryBridge(meshSlug, "visible", { visible });
6979
+ if (bridged !== null) {
6980
+ if (bridged.ok) {
6981
+ if (opts.json)
6982
+ console.log(JSON.stringify({ visible }));
6983
+ else
6984
+ render.ok(visible ? "you are now visible to peers" : "you are now hidden", visible ? undefined : "direct messages still reach you");
6985
+ return EXIT.SUCCESS;
6986
+ }
6987
+ render.err(bridged.error);
6988
+ return EXIT.INTERNAL_ERROR;
6989
+ }
6990
+ }
6991
+ await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
6992
+ await client.setVisible(visible);
6993
+ });
6994
+ if (opts.json)
6995
+ console.log(JSON.stringify({ visible }));
6996
+ else
6997
+ render.ok(visible ? "you are now visible to peers" : "you are now hidden", visible ? undefined : "direct messages still reach you");
6998
+ return EXIT.SUCCESS;
6999
+ }
7000
+ async function runGroupJoin(name, opts) {
7001
+ if (!name) {
7002
+ render.err("Usage: claudemesh group join @<name> [--role X]");
7003
+ return EXIT.INVALID_ARGS;
7004
+ }
7005
+ const cleanName = name.startsWith("@") ? name.slice(1) : name;
7006
+ await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
7007
+ await client.joinGroup(cleanName, opts.role);
7008
+ });
7009
+ if (opts.json) {
7010
+ console.log(JSON.stringify({ group: cleanName, role: opts.role ?? null }));
7011
+ return EXIT.SUCCESS;
7012
+ }
7013
+ render.ok(`joined ${clay("@" + cleanName)}`, opts.role ? `as ${opts.role}` : undefined);
7014
+ return EXIT.SUCCESS;
7015
+ }
7016
+ async function runGroupLeave(name, opts) {
7017
+ if (!name) {
7018
+ render.err("Usage: claudemesh group leave @<name>");
7019
+ return EXIT.INVALID_ARGS;
7020
+ }
7021
+ const cleanName = name.startsWith("@") ? name.slice(1) : name;
7022
+ await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
7023
+ await client.leaveGroup(cleanName);
7024
+ });
7025
+ if (opts.json) {
7026
+ console.log(JSON.stringify({ group: cleanName, left: true }));
7027
+ return EXIT.SUCCESS;
7028
+ }
7029
+ render.ok(`left ${clay("@" + cleanName)}`);
7030
+ return EXIT.SUCCESS;
7031
+ }
7032
+ async function runForget(id, opts) {
7033
+ if (!id) {
7034
+ render.err("Usage: claudemesh forget <memory-id>");
7035
+ return EXIT.INVALID_ARGS;
7036
+ }
7037
+ await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
7038
+ await client.forget(id);
7039
+ });
7040
+ if (opts.json) {
7041
+ console.log(JSON.stringify({ id, forgotten: true }));
7042
+ return EXIT.SUCCESS;
7043
+ }
7044
+ render.ok(`forgot ${dim(id.slice(0, 8))}`);
7045
+ return EXIT.SUCCESS;
7046
+ }
7047
+ async function runMsgStatus(id, opts) {
7048
+ if (!id) {
7049
+ render.err("Usage: claudemesh msg-status <message-id>");
7050
+ return EXIT.INVALID_ARGS;
7051
+ }
7052
+ return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
7053
+ const result = await client.messageStatus(id);
7054
+ if (!result) {
7055
+ if (opts.json)
7056
+ console.log(JSON.stringify({ id, found: false }));
7057
+ else
7058
+ render.err(`Message ${id} not found or timed out.`);
7059
+ return EXIT.NOT_FOUND;
7060
+ }
7061
+ if (opts.json) {
7062
+ console.log(JSON.stringify(result, null, 2));
7063
+ return EXIT.SUCCESS;
7064
+ }
7065
+ render.section(`message ${id.slice(0, 12)}…`);
7066
+ render.kv([
7067
+ ["target", result.targetSpec],
7068
+ ["delivered", result.delivered ? "yes" : "no"],
7069
+ ["delivered_at", result.deliveredAt ?? dim("—")]
7070
+ ]);
7071
+ if (result.recipients.length > 0) {
7072
+ render.blank();
7073
+ render.heading("recipients");
7074
+ for (const r of result.recipients) {
7075
+ process.stdout.write(` ${bold(r.name)} ${dim(r.pubkey.slice(0, 12) + "…")} ${dim("·")} ${r.status}
7076
+ `);
7077
+ }
7078
+ }
7079
+ return EXIT.SUCCESS;
7080
+ });
7081
+ }
7082
+ async function runClock(opts) {
7083
+ return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
7084
+ const result = await client.getClock();
7085
+ if (!result) {
7086
+ if (opts.json)
7087
+ console.log(JSON.stringify({ error: "timed out" }));
7088
+ else
7089
+ render.err("Clock query timed out");
7090
+ return EXIT.INTERNAL_ERROR;
7091
+ }
7092
+ if (opts.json) {
7093
+ console.log(JSON.stringify(result, null, 2));
7094
+ return EXIT.SUCCESS;
7095
+ }
7096
+ const statusLabel = result.speed === 0 ? "not started" : result.paused ? "paused" : "running";
7097
+ render.section(`mesh clock — ${statusLabel}`);
7098
+ render.kv([
7099
+ ["speed", `x${result.speed}`],
7100
+ ["tick", String(result.tick)],
7101
+ ["sim_time", result.simTime],
7102
+ ["started_at", result.startedAt]
7103
+ ]);
7104
+ return EXIT.SUCCESS;
7105
+ });
7106
+ }
7107
+ async function runStats(opts) {
7108
+ return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
7109
+ const peers = await client.listPeers();
7110
+ if (opts.json) {
7111
+ console.log(JSON.stringify({
7112
+ mesh: client.meshSlug,
7113
+ peers: peers.map((p) => ({ name: p.displayName, pubkey: p.pubkey, stats: p.stats ?? null }))
7114
+ }, null, 2));
7115
+ return EXIT.SUCCESS;
7116
+ }
7117
+ render.section(client.meshSlug);
7118
+ for (const p of peers) {
7119
+ const s = p.stats;
7120
+ if (!s) {
7121
+ process.stdout.write(` ${bold(p.displayName)} ${dim("(no stats)")}
7122
+ `);
7123
+ continue;
7124
+ }
7125
+ const up = s.uptime != null ? `${Math.floor(s.uptime / 60)}m` : "—";
7126
+ process.stdout.write(` ${bold(p.displayName)} ${dim(`in:${s.messagesIn ?? 0} out:${s.messagesOut ?? 0} tools:${s.toolCalls ?? 0} up:${up} err:${s.errors ?? 0}`)}
7127
+ `);
7128
+ }
7129
+ return EXIT.SUCCESS;
7130
+ });
7131
+ }
7132
+ async function runPing(opts) {
7133
+ return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
7134
+ const peers = await client.listPeers();
7135
+ if (opts.json) {
7136
+ console.log(JSON.stringify({
7137
+ mesh: client.meshSlug,
7138
+ ws_status: client.status,
7139
+ peers_online: peers.length,
7140
+ push_buffer: client.pushHistory.length
7141
+ }, null, 2));
7142
+ return EXIT.SUCCESS;
7143
+ }
7144
+ render.section(`ping ${client.meshSlug}`);
7145
+ render.kv([
7146
+ ["ws_status", client.status],
7147
+ ["peers_online", String(peers.length)],
7148
+ ["push_buffer", String(client.pushHistory.length)]
7149
+ ]);
7150
+ return EXIT.SUCCESS;
7151
+ });
7152
+ }
7153
+ async function runTaskClaim(id, opts) {
7154
+ if (!id) {
7155
+ render.err("Usage: claudemesh task claim <id>");
7156
+ return EXIT.INVALID_ARGS;
7157
+ }
7158
+ await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
7159
+ await client.claimTask(id);
7160
+ });
7161
+ if (opts.json) {
7162
+ console.log(JSON.stringify({ id, claimed: true }));
7163
+ return EXIT.SUCCESS;
7164
+ }
7165
+ render.ok(`claimed ${dim(id.slice(0, 8))}`);
7166
+ return EXIT.SUCCESS;
7167
+ }
7168
+ async function runTaskComplete(id, result, opts) {
7169
+ if (!id) {
7170
+ render.err("Usage: claudemesh task complete <id> [result]");
7171
+ return EXIT.INVALID_ARGS;
7172
+ }
7173
+ await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
7174
+ await client.completeTask(id, result);
7175
+ });
7176
+ if (opts.json) {
7177
+ console.log(JSON.stringify({ id, completed: true, result: result ?? null }));
7178
+ return EXIT.SUCCESS;
7179
+ }
7180
+ render.ok(`completed ${dim(id.slice(0, 8))}`, result);
7181
+ return EXIT.SUCCESS;
7182
+ }
7183
+ var init_broker_actions = __esm(() => {
7184
+ init_connect();
7185
+ init_facade();
7186
+ init_client3();
7187
+ init_render();
7188
+ init_styles();
7189
+ init_exit_codes();
7190
+ });
7191
+
6718
7192
  // src/commands/remind.ts
6719
7193
  var exports_remind = {};
6720
7194
  __export(exports_remind, {
@@ -7021,17 +7495,17 @@ __export(exports_install, {
7021
7495
  import {
7022
7496
  chmodSync as chmodSync3,
7023
7497
  copyFileSync,
7024
- existsSync as existsSync5,
7498
+ existsSync as existsSync6,
7025
7499
  mkdirSync as mkdirSync3,
7026
7500
  readFileSync as readFileSync4,
7027
7501
  writeFileSync as writeFileSync5
7028
7502
  } from "node:fs";
7029
- import { homedir as homedir4, platform as platform5 } from "node:os";
7030
- import { dirname as dirname2, join as join4, resolve } from "node:path";
7503
+ import { homedir as homedir5, platform as platform5 } from "node:os";
7504
+ import { dirname as dirname2, join as join5, resolve } from "node:path";
7031
7505
  import { fileURLToPath } from "node:url";
7032
7506
  import { spawnSync as spawnSync3 } from "node:child_process";
7033
7507
  function readClaudeConfig() {
7034
- if (!existsSync5(CLAUDE_CONFIG))
7508
+ if (!existsSync6(CLAUDE_CONFIG))
7035
7509
  return {};
7036
7510
  const text = readFileSync4(CLAUDE_CONFIG, "utf-8").trim();
7037
7511
  if (!text)
@@ -7043,12 +7517,12 @@ function readClaudeConfig() {
7043
7517
  }
7044
7518
  }
7045
7519
  function backupClaudeConfig() {
7046
- if (!existsSync5(CLAUDE_CONFIG))
7520
+ if (!existsSync6(CLAUDE_CONFIG))
7047
7521
  return;
7048
- const backupDir = join4(dirname2(CLAUDE_CONFIG), ".claude", "backups");
7522
+ const backupDir = join5(dirname2(CLAUDE_CONFIG), ".claude", "backups");
7049
7523
  mkdirSync3(backupDir, { recursive: true });
7050
7524
  const ts = Date.now();
7051
- const dest = join4(backupDir, `.claude.json.pre-claudemesh.${ts}`);
7525
+ const dest = join5(backupDir, `.claude.json.pre-claudemesh.${ts}`);
7052
7526
  copyFileSync(CLAUDE_CONFIG, dest);
7053
7527
  }
7054
7528
  function patchMcpServer(entry) {
@@ -7072,7 +7546,7 @@ function patchMcpServer(entry) {
7072
7546
  return action;
7073
7547
  }
7074
7548
  function removeMcpServer() {
7075
- if (!existsSync5(CLAUDE_CONFIG))
7549
+ if (!existsSync6(CLAUDE_CONFIG))
7076
7550
  return false;
7077
7551
  backupClaudeConfig();
7078
7552
  const cfg = readClaudeConfig();
@@ -7120,7 +7594,7 @@ function entriesEqual(a, b) {
7120
7594
  return a.command === b.command && JSON.stringify(a.args ?? []) === JSON.stringify(b.args ?? []);
7121
7595
  }
7122
7596
  function readClaudeSettings() {
7123
- if (!existsSync5(CLAUDE_SETTINGS))
7597
+ if (!existsSync6(CLAUDE_SETTINGS))
7124
7598
  return {};
7125
7599
  const text = readFileSync4(CLAUDE_SETTINGS, "utf-8").trim();
7126
7600
  if (!text)
@@ -7147,7 +7621,7 @@ function installAllowedTools() {
7147
7621
  return { added: toAdd, unchanged: CLAUDEMESH_TOOLS.length - toAdd.length };
7148
7622
  }
7149
7623
  function uninstallAllowedTools() {
7150
- if (!existsSync5(CLAUDE_SETTINGS))
7624
+ if (!existsSync6(CLAUDE_SETTINGS))
7151
7625
  return 0;
7152
7626
  const settings = readClaudeSettings();
7153
7627
  const existing = settings.allowedTools ?? [];
@@ -7182,7 +7656,7 @@ function installHooks() {
7182
7656
  return { added, unchanged };
7183
7657
  }
7184
7658
  function uninstallHooks() {
7185
- if (!existsSync5(CLAUDE_SETTINGS))
7659
+ if (!existsSync6(CLAUDE_SETTINGS))
7186
7660
  return 0;
7187
7661
  const settings = readClaudeSettings();
7188
7662
  const hooks = settings.hooks;
@@ -7230,7 +7704,7 @@ function runInstall(args = []) {
7230
7704
  render.err("`bun` is not on PATH.", "Install Bun first: https://bun.com");
7231
7705
  process.exit(1);
7232
7706
  }
7233
- if (!existsSync5(entry)) {
7707
+ if (!existsSync6(entry)) {
7234
7708
  render.err(`MCP entry not found at ${entry}`);
7235
7709
  process.exit(1);
7236
7710
  }
@@ -7346,8 +7820,8 @@ var init_install = __esm(() => {
7346
7820
  init_facade();
7347
7821
  init_render();
7348
7822
  init_styles();
7349
- CLAUDE_CONFIG = join4(homedir4(), ".claude.json");
7350
- CLAUDE_SETTINGS = join4(homedir4(), ".claude", "settings.json");
7823
+ CLAUDE_CONFIG = join5(homedir5(), ".claude.json");
7824
+ CLAUDE_SETTINGS = join5(homedir5(), ".claude", "settings.json");
7351
7825
  CLAUDEMESH_TOOLS = [
7352
7826
  "mcp__claudemesh__cancel_scheduled",
7353
7827
  "mcp__claudemesh__check_messages",
@@ -7402,10 +7876,10 @@ var exports_uninstall = {};
7402
7876
  __export(exports_uninstall, {
7403
7877
  uninstall: () => uninstall
7404
7878
  });
7405
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync6, existsSync as existsSync6 } from "node:fs";
7879
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync6, existsSync as existsSync7 } from "node:fs";
7406
7880
  async function uninstall() {
7407
7881
  let removed = 0;
7408
- if (existsSync6(PATHS.CLAUDE_JSON)) {
7882
+ if (existsSync7(PATHS.CLAUDE_JSON)) {
7409
7883
  try {
7410
7884
  const raw = readFileSync5(PATHS.CLAUDE_JSON, "utf-8");
7411
7885
  const config = JSON.parse(raw);
@@ -7419,7 +7893,7 @@ async function uninstall() {
7419
7893
  }
7420
7894
  } catch {}
7421
7895
  }
7422
- if (existsSync6(PATHS.CLAUDE_SETTINGS)) {
7896
+ if (existsSync7(PATHS.CLAUDE_SETTINGS)) {
7423
7897
  try {
7424
7898
  const raw = readFileSync5(PATHS.CLAUDE_SETTINGS, "utf-8");
7425
7899
  const config = JSON.parse(raw);
@@ -7467,9 +7941,9 @@ var exports_doctor = {};
7467
7941
  __export(exports_doctor, {
7468
7942
  runDoctor: () => runDoctor
7469
7943
  });
7470
- import { existsSync as existsSync7, readFileSync as readFileSync6, statSync as statSync2 } from "node:fs";
7471
- import { homedir as homedir5, platform as platform6 } from "node:os";
7472
- import { join as join5 } from "node:path";
7944
+ import { existsSync as existsSync8, readFileSync as readFileSync6, statSync as statSync2 } from "node:fs";
7945
+ import { homedir as homedir6, platform as platform6 } from "node:os";
7946
+ import { join as join6 } from "node:path";
7473
7947
  import { spawnSync as spawnSync4 } from "node:child_process";
7474
7948
  function checkNode() {
7475
7949
  const major = Number(process.versions.node.split(".")[0]);
@@ -7493,8 +7967,8 @@ function checkClaudeOnPath() {
7493
7967
  };
7494
7968
  }
7495
7969
  function checkMcpRegistered() {
7496
- const claudeConfig = join5(homedir5(), ".claude.json");
7497
- if (!existsSync7(claudeConfig)) {
7970
+ const claudeConfig = join6(homedir6(), ".claude.json");
7971
+ if (!existsSync8(claudeConfig)) {
7498
7972
  return {
7499
7973
  name: "claudemesh MCP registered in ~/.claude.json",
7500
7974
  pass: false,
@@ -7519,8 +7993,8 @@ function checkMcpRegistered() {
7519
7993
  }
7520
7994
  }
7521
7995
  function checkHooksRegistered() {
7522
- const settings = join5(homedir5(), ".claude", "settings.json");
7523
- if (!existsSync7(settings)) {
7996
+ const settings = join6(homedir6(), ".claude", "settings.json");
7997
+ if (!existsSync8(settings)) {
7524
7998
  return {
7525
7999
  name: "Status hooks registered in ~/.claude/settings.json",
7526
8000
  pass: false,
@@ -7545,7 +8019,7 @@ function checkHooksRegistered() {
7545
8019
  }
7546
8020
  function checkConfigFile() {
7547
8021
  const path = getConfigPath();
7548
- if (!existsSync7(path)) {
8022
+ if (!existsSync8(path)) {
7549
8023
  return {
7550
8024
  name: "~/.claudemesh/config.json exists and parses",
7551
8025
  pass: true,
@@ -7728,7 +8202,7 @@ var exports_status = {};
7728
8202
  __export(exports_status, {
7729
8203
  runStatus: () => runStatus
7730
8204
  });
7731
- import { statSync as statSync3, existsSync as existsSync8 } from "node:fs";
8205
+ import { statSync as statSync3, existsSync as existsSync9 } from "node:fs";
7732
8206
  import WebSocket2 from "ws";
7733
8207
  async function probeBroker(url, timeoutMs = 4000) {
7734
8208
  return new Promise((resolve2) => {
@@ -7758,7 +8232,7 @@ async function runStatus() {
7758
8232
  render.section(`status (v${VERSION})`);
7759
8233
  const configPath = getConfigPath();
7760
8234
  let configPermsNote = "missing";
7761
- if (existsSync8(configPath)) {
8235
+ if (existsSync9(configPath)) {
7762
8236
  const mode = (statSync3(configPath).mode & 511).toString(8).padStart(4, "0");
7763
8237
  configPermsNote = mode === "0600" ? `${mode}` : `${mode} — expected 0600`;
7764
8238
  }
@@ -7904,10 +8378,10 @@ var init_check_claude_binary = __esm(() => {
7904
8378
  });
7905
8379
 
7906
8380
  // src/services/health/check-mcp-registered.ts
7907
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:fs";
8381
+ import { existsSync as existsSync10, readFileSync as readFileSync7 } from "node:fs";
7908
8382
  function checkMcpRegistered2() {
7909
8383
  try {
7910
- if (!existsSync9(PATHS.CLAUDE_JSON)) {
8384
+ if (!existsSync10(PATHS.CLAUDE_JSON)) {
7911
8385
  return { name: "mcp-registered", ok: false, message: "~/.claude.json not found" };
7912
8386
  }
7913
8387
  const raw = readFileSync7(PATHS.CLAUDE_JSON, "utf-8");
@@ -7925,10 +8399,10 @@ var init_check_mcp_registered = __esm(() => {
7925
8399
  });
7926
8400
 
7927
8401
  // src/services/health/check-hooks-registered.ts
7928
- import { existsSync as existsSync10, readFileSync as readFileSync8 } from "node:fs";
8402
+ import { existsSync as existsSync11, readFileSync as readFileSync8 } from "node:fs";
7929
8403
  function checkHooksRegistered2() {
7930
8404
  try {
7931
- if (!existsSync10(PATHS.CLAUDE_SETTINGS)) {
8405
+ if (!existsSync11(PATHS.CLAUDE_SETTINGS)) {
7932
8406
  return { name: "hooks-registered", ok: false, message: "~/.claude/settings.json not found" };
7933
8407
  }
7934
8408
  const raw = readFileSync8(PATHS.CLAUDE_SETTINGS, "utf-8");
@@ -7946,10 +8420,10 @@ var init_check_hooks_registered = __esm(() => {
7946
8420
  });
7947
8421
 
7948
8422
  // src/services/health/check-config-perms.ts
7949
- import { existsSync as existsSync11, statSync as statSync4 } from "node:fs";
8423
+ import { existsSync as existsSync12, statSync as statSync4 } from "node:fs";
7950
8424
  function checkConfigPerms() {
7951
8425
  const configFile = PATHS.CONFIG_FILE;
7952
- if (!existsSync11(configFile)) {
8426
+ if (!existsSync12(configFile)) {
7953
8427
  return { name: "config-perms", ok: true, message: "No config file yet (first run)" };
7954
8428
  }
7955
8429
  try {
@@ -7967,9 +8441,9 @@ var init_check_config_perms = __esm(() => {
7967
8441
  });
7968
8442
 
7969
8443
  // src/services/health/check-keypairs-valid.ts
7970
- import { existsSync as existsSync12, readFileSync as readFileSync9 } from "node:fs";
8444
+ import { existsSync as existsSync13, readFileSync as readFileSync9 } from "node:fs";
7971
8445
  function checkKeypairsValid() {
7972
- if (!existsSync12(PATHS.CONFIG_FILE)) {
8446
+ if (!existsSync13(PATHS.CONFIG_FILE)) {
7973
8447
  return { name: "keypairs-valid", ok: true, message: "No config (first run)" };
7974
8448
  }
7975
8449
  try {
@@ -8453,18 +8927,18 @@ var exports_url_handler = {};
8453
8927
  __export(exports_url_handler, {
8454
8928
  runUrlHandler: () => runUrlHandler
8455
8929
  });
8456
- import { platform as platform7, homedir as homedir6 } from "node:os";
8457
- import { existsSync as existsSync13, mkdirSync as mkdirSync4, writeFileSync as writeFileSync7, rmSync as rmSync2, chmodSync as chmodSync4 } from "node:fs";
8458
- import { join as join6 } from "node:path";
8930
+ import { platform as platform7, homedir as homedir7 } from "node:os";
8931
+ import { existsSync as existsSync14, mkdirSync as mkdirSync4, writeFileSync as writeFileSync7, rmSync as rmSync2, chmodSync as chmodSync4 } from "node:fs";
8932
+ import { join as join7 } from "node:path";
8459
8933
  import { spawnSync as spawnSync5 } from "node:child_process";
8460
8934
  function resolveClaudemeshBin() {
8461
8935
  return process.argv[1] ?? "claudemesh";
8462
8936
  }
8463
8937
  function installDarwin() {
8464
8938
  const binPath = resolveClaudemeshBin();
8465
- const appDir = join6(homedir6(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
8466
- const contents = join6(appDir, "Contents");
8467
- const macOS = join6(contents, "MacOS");
8939
+ const appDir = join7(homedir7(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
8940
+ const contents = join7(appDir, "Contents");
8941
+ const macOS = join7(contents, "MacOS");
8468
8942
  mkdirSync4(macOS, { recursive: true });
8469
8943
  const plist = `<?xml version="1.0" encoding="UTF-8"?>
8470
8944
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -8488,7 +8962,7 @@ function installDarwin() {
8488
8962
  </array>
8489
8963
  </dict>
8490
8964
  </plist>`;
8491
- writeFileSync7(join6(contents, "Info.plist"), plist);
8965
+ writeFileSync7(join7(contents, "Info.plist"), plist);
8492
8966
  const shim = `#!/bin/sh
8493
8967
  URL="$1"
8494
8968
  CODE=\${URL#claudemesh://}
@@ -8502,7 +8976,7 @@ tell application "Terminal"
8502
8976
  end tell
8503
8977
  EOF
8504
8978
  `;
8505
- const shimPath = join6(macOS, "open-url");
8979
+ const shimPath = join7(macOS, "open-url");
8506
8980
  writeFileSync7(shimPath, shim);
8507
8981
  chmodSync4(shimPath, 493);
8508
8982
  const lsreg = spawnSync5("/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister", ["-f", appDir], { encoding: "utf-8" });
@@ -8514,7 +8988,7 @@ EOF
8514
8988
  }
8515
8989
  function installLinux() {
8516
8990
  const binPath = resolveClaudemeshBin();
8517
- const appsDir = join6(homedir6(), ".local", "share", "applications");
8991
+ const appsDir = join7(homedir7(), ".local", "share", "applications");
8518
8992
  mkdirSync4(appsDir, { recursive: true });
8519
8993
  const desktop = `[Desktop Entry]
8520
8994
  Type=Application
@@ -8526,7 +9000,7 @@ Terminal=true
8526
9000
  MimeType=x-scheme-handler/claudemesh;
8527
9001
  NoDisplay=true
8528
9002
  `;
8529
- const desktopPath = join6(appsDir, "claudemesh.desktop");
9003
+ const desktopPath = join7(appsDir, "claudemesh.desktop");
8530
9004
  writeFileSync7(desktopPath, desktop);
8531
9005
  const xdg1 = spawnSync5("xdg-mime", ["default", "claudemesh.desktop", "x-scheme-handler/claudemesh"], { encoding: "utf-8" });
8532
9006
  if (xdg1.status !== 0) {
@@ -8549,7 +9023,7 @@ function installWindows() {
8549
9023
  `[HKEY_CURRENT_USER\\Software\\Classes\\claudemesh\\shell\\open\\command]`,
8550
9024
  `@="\\"${binPath.replace(/\\/g, "\\\\")}\\" \\"%1\\""`
8551
9025
  ];
8552
- const regPath = join6(homedir6(), "claudemesh-handler.reg");
9026
+ const regPath = join7(homedir7(), "claudemesh-handler.reg");
8553
9027
  writeFileSync7(regPath, lines.join(`\r
8554
9028
  `));
8555
9029
  const res = spawnSync5("reg.exe", ["import", regPath], { encoding: "utf-8" });
@@ -8561,15 +9035,15 @@ function installWindows() {
8561
9035
  return EXIT.SUCCESS;
8562
9036
  }
8563
9037
  function uninstallDarwin() {
8564
- const appDir = join6(homedir6(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
8565
- if (existsSync13(appDir))
9038
+ const appDir = join7(homedir7(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
9039
+ if (existsSync14(appDir))
8566
9040
  rmSync2(appDir, { recursive: true, force: true });
8567
9041
  render.ok("removed claudemesh:// handler on macOS");
8568
9042
  return EXIT.SUCCESS;
8569
9043
  }
8570
9044
  function uninstallLinux() {
8571
- const desktopPath = join6(homedir6(), ".local", "share", "applications", "claudemesh.desktop");
8572
- if (existsSync13(desktopPath))
9045
+ const desktopPath = join7(homedir7(), ".local", "share", "applications", "claudemesh.desktop");
9046
+ if (existsSync14(desktopPath))
8573
9047
  rmSync2(desktopPath, { force: true });
8574
9048
  render.ok("removed claudemesh:// handler on Linux");
8575
9049
  return EXIT.SUCCESS;
@@ -8614,9 +9088,9 @@ var exports_status_line = {};
8614
9088
  __export(exports_status_line, {
8615
9089
  runStatusLine: () => runStatusLine
8616
9090
  });
8617
- import { existsSync as existsSync14, readFileSync as readFileSync10 } from "node:fs";
8618
- import { join as join7 } from "node:path";
8619
- import { homedir as homedir7 } from "node:os";
9091
+ import { existsSync as existsSync15, readFileSync as readFileSync10 } from "node:fs";
9092
+ import { join as join8 } from "node:path";
9093
+ import { homedir as homedir8 } from "node:os";
8620
9094
  async function runStatusLine() {
8621
9095
  try {
8622
9096
  const config = readConfig();
@@ -8624,9 +9098,9 @@ async function runStatusLine() {
8624
9098
  process.stdout.write("◇ claudemesh (not joined)");
8625
9099
  return EXIT.SUCCESS;
8626
9100
  }
8627
- const cachePath = join7(homedir7(), ".claudemesh", "peer-cache.json");
9101
+ const cachePath = join8(homedir8(), ".claudemesh", "peer-cache.json");
8628
9102
  let cache = {};
8629
- if (existsSync14(cachePath)) {
9103
+ if (existsSync15(cachePath)) {
8630
9104
  try {
8631
9105
  cache = JSON.parse(readFileSync10(cachePath, "utf-8"));
8632
9106
  } catch {}
@@ -8659,7 +9133,7 @@ __export(exports_backup, {
8659
9133
  runRestore: () => runRestore,
8660
9134
  runBackup: () => runBackup
8661
9135
  });
8662
- import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, existsSync as existsSync15 } from "node:fs";
9136
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync8, existsSync as existsSync16 } from "node:fs";
8663
9137
  import { createInterface as createInterface10 } from "node:readline";
8664
9138
  function readHidden(prompt5) {
8665
9139
  return new Promise((resolve2) => {
@@ -8701,7 +9175,7 @@ async function deriveKey(pass, salt, s) {
8701
9175
  }
8702
9176
  async function runBackup(outPath) {
8703
9177
  const configPath = getConfigPath();
8704
- if (!existsSync15(configPath)) {
9178
+ if (!existsSync16(configPath)) {
8705
9179
  console.error(" No config found — nothing to back up. Join a mesh first.");
8706
9180
  return EXIT.NOT_FOUND;
8707
9181
  }
@@ -8735,7 +9209,7 @@ async function runRestore(inPath) {
8735
9209
  console.error(" Usage: claudemesh restore <backup-file>");
8736
9210
  return EXIT.INVALID_ARGS;
8737
9211
  }
8738
- if (!existsSync15(inPath)) {
9212
+ if (!existsSync16(inPath)) {
8739
9213
  console.error(` ✗ File not found: ${inPath}`);
8740
9214
  return EXIT.NOT_FOUND;
8741
9215
  }
@@ -8758,7 +9232,7 @@ async function runRestore(inPath) {
8758
9232
  return EXIT.INTERNAL_ERROR;
8759
9233
  }
8760
9234
  const configPath = getConfigPath();
8761
- if (existsSync15(configPath)) {
9235
+ if (existsSync16(configPath)) {
8762
9236
  const backupOld = `${configPath}.before-restore.${Date.now()}`;
8763
9237
  writeFileSync8(backupOld, readFileSync11(configPath), { mode: 384 });
8764
9238
  console.log(` ↻ Existing config saved to ${backupOld}`);
@@ -8783,8 +9257,8 @@ __export(exports_upgrade, {
8783
9257
  runUpgrade: () => runUpgrade
8784
9258
  });
8785
9259
  import { spawnSync as spawnSync6 } from "node:child_process";
8786
- import { existsSync as existsSync16 } from "node:fs";
8787
- import { dirname as dirname3, join as join8, resolve as resolve2 } from "node:path";
9260
+ import { existsSync as existsSync17 } from "node:fs";
9261
+ import { dirname as dirname3, join as join9, resolve as resolve2 } from "node:path";
8788
9262
  async function latestVersion() {
8789
9263
  try {
8790
9264
  const res = await fetch(URLS.NPM_REGISTRY, { signal: AbortSignal.timeout(8000) });
@@ -8797,15 +9271,15 @@ async function latestVersion() {
8797
9271
  }
8798
9272
  }
8799
9273
  function findNpm() {
8800
- const portable = join8(process.env.HOME ?? "", ".claudemesh", "node", "bin", "npm");
8801
- if (existsSync16(portable)) {
8802
- return { npm: portable, prefix: join8(process.env.HOME ?? "", ".claudemesh") };
9274
+ const portable = join9(process.env.HOME ?? "", ".claudemesh", "node", "bin", "npm");
9275
+ if (existsSync17(portable)) {
9276
+ return { npm: portable, prefix: join9(process.env.HOME ?? "", ".claudemesh") };
8803
9277
  }
8804
9278
  let cur = resolve2(process.argv[1] ?? ".");
8805
9279
  for (let i = 0;i < 6; i++) {
8806
9280
  cur = dirname3(cur);
8807
- const candidate = join8(cur, "bin", "npm");
8808
- if (existsSync16(candidate))
9281
+ const candidate = join9(cur, "bin", "npm");
9282
+ if (existsSync17(candidate))
8809
9283
  return { npm: candidate };
8810
9284
  }
8811
9285
  return { npm: "npm" };
@@ -8867,9 +9341,9 @@ __export(exports_grants, {
8867
9341
  runBlock: () => runBlock,
8868
9342
  isAllowed: () => isAllowed
8869
9343
  });
8870
- import { existsSync as existsSync17, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
8871
- import { homedir as homedir8 } from "node:os";
8872
- import { join as join9 } from "node:path";
9344
+ import { existsSync as existsSync18, mkdirSync as mkdirSync5, readFileSync as readFileSync12, writeFileSync as writeFileSync9 } from "node:fs";
9345
+ import { homedir as homedir9 } from "node:os";
9346
+ import { join as join10 } from "node:path";
8873
9347
  async function syncToBroker(meshSlug, grants) {
8874
9348
  const auth = getStoredToken();
8875
9349
  if (!auth)
@@ -8887,7 +9361,7 @@ async function syncToBroker(meshSlug, grants) {
8887
9361
  }
8888
9362
  }
8889
9363
  function readGrants() {
8890
- if (!existsSync17(GRANT_FILE))
9364
+ if (!existsSync18(GRANT_FILE))
8891
9365
  return {};
8892
9366
  try {
8893
9367
  return JSON.parse(readFileSync12(GRANT_FILE, "utf-8"));
@@ -8896,8 +9370,8 @@ function readGrants() {
8896
9370
  }
8897
9371
  }
8898
9372
  function writeGrants(g) {
8899
- const dir = join9(homedir8(), ".claudemesh");
8900
- if (!existsSync17(dir))
9373
+ const dir = join10(homedir9(), ".claudemesh");
9374
+ if (!existsSync18(dir))
8901
9375
  mkdirSync5(dir, { recursive: true });
8902
9376
  writeFileSync9(GRANT_FILE, JSON.stringify(g, null, 2), { mode: 384 });
8903
9377
  }
@@ -9055,7 +9529,7 @@ var init_grants = __esm(() => {
9055
9529
  BROKER_HTTP7 = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
9056
9530
  ALL_CAPS = ["read", "dm", "broadcast", "state-read", "state-write", "file-read"];
9057
9531
  DEFAULT_CAPS = ["read", "dm", "broadcast", "state-read"];
9058
- GRANT_FILE = join9(homedir8(), ".claudemesh", "grants.json");
9532
+ GRANT_FILE = join10(homedir9(), ".claudemesh", "grants.json");
9059
9533
  });
9060
9534
 
9061
9535
  // src/mcp/tools/definitions.ts
@@ -9981,6 +10455,165 @@ var init_definitions = __esm(() => {
9981
10455
  ];
9982
10456
  });
9983
10457
 
10458
+ // src/services/bridge/server.ts
10459
+ import { createServer as createServer2 } from "node:net";
10460
+ import { mkdirSync as mkdirSync6, unlinkSync as unlinkSync2, existsSync as existsSync19, chmodSync as chmodSync5 } from "node:fs";
10461
+ async function resolveTarget2(client, to) {
10462
+ if (to.startsWith("@") || to === "*" || /^[0-9a-f]{64}$/i.test(to)) {
10463
+ return { ok: true, spec: to };
10464
+ }
10465
+ const peers = await client.listPeers();
10466
+ const match = peers.find((p) => p.displayName.toLowerCase() === to.toLowerCase());
10467
+ if (!match) {
10468
+ return {
10469
+ ok: false,
10470
+ error: `peer "${to}" not found. online: ${peers.map((p) => p.displayName).join(", ") || "(none)"}`
10471
+ };
10472
+ }
10473
+ return { ok: true, spec: match.pubkey };
10474
+ }
10475
+ async function dispatch(client, req) {
10476
+ const args = req.args ?? {};
10477
+ try {
10478
+ switch (req.verb) {
10479
+ case "ping": {
10480
+ const peers = await client.listPeers();
10481
+ return {
10482
+ id: req.id,
10483
+ ok: true,
10484
+ result: {
10485
+ mesh: client.meshSlug,
10486
+ ws_status: client.status,
10487
+ peers_online: peers.length,
10488
+ push_buffer: client.pushHistory.length
10489
+ }
10490
+ };
10491
+ }
10492
+ case "peers": {
10493
+ const peers = await client.listPeers();
10494
+ return { id: req.id, ok: true, result: peers };
10495
+ }
10496
+ case "send": {
10497
+ const to = String(args.to ?? "");
10498
+ const message = String(args.message ?? "");
10499
+ const priority = args.priority ?? "next";
10500
+ if (!to || !message) {
10501
+ return { id: req.id, ok: false, error: "send: `to` and `message` required" };
10502
+ }
10503
+ const resolved = await resolveTarget2(client, to);
10504
+ if (!resolved.ok)
10505
+ return { id: req.id, ok: false, error: resolved.error };
10506
+ const result = await client.send(resolved.spec, message, priority);
10507
+ if (!result.ok) {
10508
+ return { id: req.id, ok: false, error: result.error ?? "send failed" };
10509
+ }
10510
+ return {
10511
+ id: req.id,
10512
+ ok: true,
10513
+ result: { messageId: result.messageId, target: resolved.spec }
10514
+ };
10515
+ }
10516
+ case "summary": {
10517
+ const text = String(args.summary ?? "");
10518
+ if (!text)
10519
+ return { id: req.id, ok: false, error: "summary: `summary` required" };
10520
+ await client.setSummary(text);
10521
+ return { id: req.id, ok: true, result: { summary: text } };
10522
+ }
10523
+ case "status_set": {
10524
+ const state = String(args.status ?? "");
10525
+ if (!["idle", "working", "dnd"].includes(state)) {
10526
+ return { id: req.id, ok: false, error: "status_set: must be idle | working | dnd" };
10527
+ }
10528
+ await client.setStatus(state);
10529
+ return { id: req.id, ok: true, result: { status: state } };
10530
+ }
10531
+ case "visible": {
10532
+ const visible = Boolean(args.visible);
10533
+ await client.setVisible(visible);
10534
+ return { id: req.id, ok: true, result: { visible } };
10535
+ }
10536
+ default:
10537
+ return { id: req.id, ok: false, error: `unknown verb: ${req.verb}` };
10538
+ }
10539
+ } catch (err) {
10540
+ return {
10541
+ id: req.id,
10542
+ ok: false,
10543
+ error: err instanceof Error ? err.message : String(err)
10544
+ };
10545
+ }
10546
+ }
10547
+ function handleConnection(socket, client) {
10548
+ const parser = new LineParser;
10549
+ socket.on("data", (chunk) => {
10550
+ const lines = parser.feed(chunk);
10551
+ for (const line of lines) {
10552
+ if (!line.trim())
10553
+ continue;
10554
+ let req;
10555
+ try {
10556
+ req = JSON.parse(line);
10557
+ } catch {
10558
+ continue;
10559
+ }
10560
+ if (!req || typeof req !== "object" || !req.id || !req.verb)
10561
+ continue;
10562
+ dispatch(client, req).then((res) => {
10563
+ try {
10564
+ socket.write(frame(res));
10565
+ } catch {}
10566
+ });
10567
+ }
10568
+ });
10569
+ socket.on("error", () => {});
10570
+ }
10571
+ function startBridgeServer(client) {
10572
+ const path = socketPath(client.meshSlug);
10573
+ const dir = socketDir();
10574
+ if (!existsSync19(dir)) {
10575
+ mkdirSync6(dir, { recursive: true, mode: 448 });
10576
+ }
10577
+ if (existsSync19(path)) {
10578
+ try {
10579
+ unlinkSync2(path);
10580
+ } catch {}
10581
+ }
10582
+ const server = createServer2((socket) => handleConnection(socket, client));
10583
+ try {
10584
+ server.listen(path);
10585
+ } catch (err) {
10586
+ process.stderr.write(`[claudemesh] bridge: failed to bind ${path}: ${String(err)}
10587
+ `);
10588
+ return null;
10589
+ }
10590
+ server.on("error", (err) => {
10591
+ process.stderr.write(`[claudemesh] bridge: ${String(err)}
10592
+ `);
10593
+ });
10594
+ try {
10595
+ chmodSync5(path, 384);
10596
+ } catch {}
10597
+ let stopped = false;
10598
+ return {
10599
+ path,
10600
+ stop() {
10601
+ if (stopped)
10602
+ return;
10603
+ stopped = true;
10604
+ try {
10605
+ server.close();
10606
+ } catch {}
10607
+ try {
10608
+ unlinkSync2(path);
10609
+ } catch {}
10610
+ }
10611
+ };
10612
+ }
10613
+ var init_server = __esm(() => {
10614
+ init_protocol();
10615
+ });
10616
+
9984
10617
  // src/mcp/server.ts
9985
10618
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
9986
10619
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -10163,6 +10796,16 @@ function formatPush(p, meshSlug) {
10163
10796
  return `[${meshSlug}]${tag} from ${p.senderPubkey.slice(0, 12)}… (${p.priority}, ${p.createdAt}):
10164
10797
  ${body}`;
10165
10798
  }
10799
+ function maybeWarnDeprecated(toolName) {
10800
+ const hint = DEPRECATED_TOOL_HINTS[toolName];
10801
+ if (!hint)
10802
+ return;
10803
+ if (warnedTools.has(toolName))
10804
+ return;
10805
+ warnedTools.add(toolName);
10806
+ process.stderr.write(`[claudemesh] mcp tool "${toolName}" is soft-deprecated in 1.1.0 ` + `and will be removed in 2.0.0. Use \`${hint}\` instead.
10807
+ `);
10808
+ }
10166
10809
  async function startMcpServer() {
10167
10810
  const serviceIdx = process.argv.indexOf("--service");
10168
10811
  if (serviceIdx !== -1 && process.argv[serviceIdx + 1]) {
@@ -10458,6 +11101,7 @@ ${manifest.allowed_tools.map((t) => ` - ${t}`).join(`
10458
11101
  if (config.meshes.length === 0) {
10459
11102
  return text("No meshes joined. Run `claudemesh join https://claudemesh.com/join/<token>` first.", true);
10460
11103
  }
11104
+ maybeWarnDeprecated(name);
10461
11105
  switch (name) {
10462
11106
  case "send_message": {
10463
11107
  const { to, message, priority } = args ?? {};
@@ -10535,12 +11179,12 @@ ${peerLines.join(`
10535
11179
  }
10536
11180
  }
10537
11181
  try {
10538
- const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync6, existsSync: existsSync18 } = await import("node:fs");
11182
+ const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync7, existsSync: existsSync20 } = await import("node:fs");
10539
11183
  const { join: joinPath } = await import("node:path");
10540
- const { homedir: homedir9 } = await import("node:os");
10541
- const dir = joinPath(homedir9(), ".claudemesh");
10542
- if (!existsSync18(dir))
10543
- mkdirSync6(dir, { recursive: true });
11184
+ const { homedir: homedir10 } = await import("node:os");
11185
+ const dir = joinPath(homedir10(), ".claudemesh");
11186
+ if (!existsSync20(dir))
11187
+ mkdirSync7(dir, { recursive: true });
10544
11188
  writeFileSync10(joinPath(dir, "peer-cache.json"), JSON.stringify(statusCache));
10545
11189
  } catch {}
10546
11190
  return text(sections.join(`
@@ -10783,17 +11427,17 @@ ${lines.join(`
10783
11427
  const { path: filePath, name: fileName, tags, to: fileTo } = args ?? {};
10784
11428
  if (!filePath)
10785
11429
  return text("share_file: `path` required", true);
10786
- const { existsSync: existsSync18 } = await import("node:fs");
10787
- if (!existsSync18(filePath))
11430
+ const { existsSync: existsSync20 } = await import("node:fs");
11431
+ if (!existsSync20(filePath))
10788
11432
  return text(`share_file: file not found: ${filePath}`, true);
10789
11433
  const client = allClients()[0];
10790
11434
  if (!client)
10791
11435
  return text("share_file: not connected", true);
10792
11436
  if (fileTo) {
10793
11437
  const { encryptFile: encryptFile2, sealKeyForPeer: sealKeyForPeer2 } = await Promise.resolve().then(() => (init_file_crypto(), exports_file_crypto));
10794
- const { readFileSync: readFileSync13, writeFileSync: writeFileSync10, mkdtempSync: mkdtempSync2, unlinkSync: unlinkSync2, rmdirSync } = await import("node:fs");
11438
+ const { readFileSync: readFileSync13, writeFileSync: writeFileSync10, mkdtempSync: mkdtempSync2, unlinkSync: unlinkSync3, rmdirSync } = await import("node:fs");
10795
11439
  const { tmpdir: tmpdir2 } = await import("node:os");
10796
- const { join: join10, basename } = await import("node:path");
11440
+ const { join: join11, basename } = await import("node:path");
10797
11441
  const peers = await client.listPeers();
10798
11442
  const targetPeer = peers.find((p) => p.pubkey === fileTo || p.displayName === fileTo);
10799
11443
  if (!targetPeer) {
@@ -10816,8 +11460,8 @@ ${lines.join(`
10816
11460
  combined.set(ciphertext, nonceBytes.length);
10817
11461
  const rawName = fileName ?? basename(filePath);
10818
11462
  const baseName = basename(rawName).replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 255);
10819
- const tmpDir = mkdtempSync2(join10(tmpdir2(), "cm-"));
10820
- const tmpPath = join10(tmpDir, baseName);
11463
+ const tmpDir = mkdtempSync2(join11(tmpdir2(), "cm-"));
11464
+ const tmpPath = join11(tmpDir, baseName);
10821
11465
  writeFileSync10(tmpPath, combined);
10822
11466
  try {
10823
11467
  const fileId = await client.uploadFile(tmpPath, client.meshId, client.meshSlug, {
@@ -10833,7 +11477,7 @@ ${lines.join(`
10833
11477
  return text(`share_file: upload failed — ${e instanceof Error ? e.message : String(e)}`, true);
10834
11478
  } finally {
10835
11479
  try {
10836
- unlinkSync2(tmpPath);
11480
+ unlinkSync3(tmpPath);
10837
11481
  } catch {}
10838
11482
  try {
10839
11483
  rmdirSync(tmpDir);
@@ -10893,9 +11537,9 @@ ${lines.join(`
10893
11537
  const plaintext = await decryptFile2(ciphertext, nonce, kf);
10894
11538
  if (!plaintext)
10895
11539
  return text(genericErr, true);
10896
- const { writeFileSync: writeFileSync11, mkdirSync: mkdirSync7 } = await import("node:fs");
11540
+ const { writeFileSync: writeFileSync11, mkdirSync: mkdirSync8 } = await import("node:fs");
10897
11541
  const { dirname: dirname5 } = await import("node:path");
10898
- mkdirSync7(dirname5(save_to), { recursive: true });
11542
+ mkdirSync8(dirname5(save_to), { recursive: true });
10899
11543
  writeFileSync11(save_to, plaintext);
10900
11544
  return text(`Downloaded and decrypted: ${result.name} → ${save_to}`);
10901
11545
  }
@@ -10906,9 +11550,9 @@ ${lines.join(`
10906
11550
  }
10907
11551
  if (!res.ok)
10908
11552
  return text(`get_file: download failed (${res.status})`, true);
10909
- const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync6 } = await import("node:fs");
11553
+ const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync7 } = await import("node:fs");
10910
11554
  const { dirname: dirname4 } = await import("node:path");
10911
- mkdirSync6(dirname4(save_to), { recursive: true });
11555
+ mkdirSync7(dirname4(save_to), { recursive: true });
10912
11556
  writeFileSync10(save_to, Buffer.from(await res.arrayBuffer()));
10913
11557
  return text(`Downloaded: ${result.name} → ${save_to}`);
10914
11558
  }
@@ -11667,8 +12311,8 @@ ${lines.join(`
11667
12311
  const entryType = vType ?? "env";
11668
12312
  let plaintextBytes;
11669
12313
  if (entryType === "file") {
11670
- const { existsSync: existsSync18, readFileSync: readFileSync13 } = await import("node:fs");
11671
- if (!existsSync18(value))
12314
+ const { existsSync: existsSync20, readFileSync: readFileSync13 } = await import("node:fs");
12315
+ if (!existsSync20(value))
11672
12316
  return text(`vault_set: file not found: ${value}`, true);
11673
12317
  plaintextBytes = new Uint8Array(readFileSync13(value));
11674
12318
  } else {
@@ -11927,8 +12571,14 @@ ${lines.join(`
11927
12571
  });
11928
12572
  const transport = new StdioServerTransport;
11929
12573
  await server.connect(transport);
12574
+ const bridges = [];
11930
12575
  startClients(config).then(() => {
11931
12576
  wirePushHandlers().catch(() => {});
12577
+ for (const client of allClients()) {
12578
+ const bridge = startBridgeServer(client);
12579
+ if (bridge)
12580
+ bridges.push(bridge);
12581
+ }
11932
12582
  }).catch(() => {
11933
12583
  wirePushHandlers().catch(() => {});
11934
12584
  });
@@ -12101,6 +12751,11 @@ ${lines.join(`
12101
12751
  const keepalive = setInterval(() => {}, 1000);
12102
12752
  const shutdown = () => {
12103
12753
  clearInterval(keepalive);
12754
+ for (const b of bridges) {
12755
+ try {
12756
+ b.stop();
12757
+ } catch {}
12758
+ }
12104
12759
  stopAll();
12105
12760
  process.exit(0);
12106
12761
  };
@@ -12221,12 +12876,41 @@ async function startServiceProxy(serviceName) {
12221
12876
  process.on("SIGTERM", shutdown);
12222
12877
  process.on("SIGINT", shutdown);
12223
12878
  }
12224
- var peerNameCache, peerNameCacheAge = 0, CACHE_TTL_MS = 30000;
12225
- var init_server = __esm(() => {
12879
+ var peerNameCache, peerNameCacheAge = 0, CACHE_TTL_MS = 30000, DEPRECATED_TOOL_HINTS, warnedTools;
12880
+ var init_server2 = __esm(() => {
12226
12881
  init_definitions();
12227
12882
  init_facade();
12228
12883
  init_facade8();
12884
+ init_server();
12229
12885
  peerNameCache = new Map;
12886
+ DEPRECATED_TOOL_HINTS = {
12887
+ send_message: "claudemesh send <to> <msg> [--mesh X] [--priority Y]",
12888
+ list_peers: "claudemesh peers --json",
12889
+ check_messages: "claudemesh inbox --json",
12890
+ message_status: "claudemesh msg-status <id>",
12891
+ set_profile: "claudemesh profile --avatar X --bio Y",
12892
+ set_status: "claudemesh status set <state>",
12893
+ set_summary: "claudemesh summary <text>",
12894
+ set_visible: "claudemesh visible <true|false>",
12895
+ join_group: "claudemesh group join @<name> [--role X]",
12896
+ leave_group: "claudemesh group leave @<name>",
12897
+ get_state: "claudemesh state get <key> --json",
12898
+ set_state: "claudemesh state set <key> <value>",
12899
+ list_state: "claudemesh state list --json",
12900
+ remember: "claudemesh remember <text>",
12901
+ recall: "claudemesh recall <query> --json",
12902
+ forget: "claudemesh forget <id>",
12903
+ schedule_reminder: "claudemesh remind <msg> --in/--at/--cron",
12904
+ list_scheduled: "claudemesh remind list --json",
12905
+ cancel_scheduled: "claudemesh remind cancel <id>",
12906
+ mesh_info: "claudemesh info --json",
12907
+ mesh_stats: "claudemesh stats --json",
12908
+ mesh_clock: "claudemesh clock --json",
12909
+ ping_mesh: "claudemesh ping",
12910
+ claim_task: "claudemesh task claim <id>",
12911
+ complete_task: "claudemesh task complete <id>"
12912
+ };
12913
+ warnedTools = new Set;
12230
12914
  });
12231
12915
 
12232
12916
  // src/commands/mcp.ts
@@ -12241,7 +12925,7 @@ async function runMcp() {
12241
12925
  process.exit(0);
12242
12926
  }
12243
12927
  var init_mcp = __esm(() => {
12244
- init_server();
12928
+ init_server2();
12245
12929
  });
12246
12930
 
12247
12931
  // src/commands/hook.ts
@@ -12521,12 +13205,28 @@ Messaging
12521
13205
  claudemesh peers see who's online
12522
13206
  claudemesh send <to> <msg> send a message
12523
13207
  claudemesh inbox drain pending messages
13208
+ claudemesh msg-status <id> check delivery status
12524
13209
  claudemesh state get|set|list shared state
12525
13210
  claudemesh remember <text> store a memory
12526
13211
  claudemesh recall <query> search memories
13212
+ claudemesh forget <id> remove a memory
12527
13213
  claudemesh remind ... schedule a reminder
12528
13214
  claudemesh profile view or edit your profile
12529
13215
  claudemesh info mesh overview
13216
+ claudemesh stats per-peer activity counters
13217
+ claudemesh clock mesh logical clock state
13218
+ claudemesh ping diagnostic round-trip
13219
+
13220
+ Identity / presence
13221
+ claudemesh status set <state> set peer status (idle | working | dnd)
13222
+ claudemesh summary <text> broadcast 1-2 sentence work summary
13223
+ claudemesh visible <true|false> toggle peer visibility
13224
+ claudemesh group join @<name> join a group (--role X optional)
13225
+ claudemesh group leave @<name> leave a group
13226
+
13227
+ Tasks
13228
+ claudemesh task claim <id> claim an unclaimed task
13229
+ claudemesh task complete <id> mark task done [result]
12530
13230
 
12531
13231
  Auth
12532
13232
  claudemesh login sign in (browser or paste token)
@@ -12681,12 +13381,12 @@ async function main() {
12681
13381
  }
12682
13382
  case "peers": {
12683
13383
  const { runPeers: runPeers2 } = await Promise.resolve().then(() => (init_peers(), exports_peers));
12684
- await runPeers2({ mesh: flags.mesh, json: !!flags.json });
13384
+ await runPeers2({ mesh: flags.mesh, json: flags.json });
12685
13385
  break;
12686
13386
  }
12687
13387
  case "send": {
12688
13388
  const { runSend: runSend2 } = await Promise.resolve().then(() => (init_send(), exports_send));
12689
- await runSend2({}, positionals[0] ?? "", positionals.slice(1).join(" "));
13389
+ await runSend2({ mesh: flags.mesh, priority: flags.priority, json: !!flags.json }, positionals[0] ?? "", positionals.slice(1).join(" "));
12690
13390
  break;
12691
13391
  }
12692
13392
  case "inbox": {
@@ -12723,6 +13423,11 @@ async function main() {
12723
13423
  process.exit(await recall2(positionals.join(" "), { json: !!flags.json }));
12724
13424
  break;
12725
13425
  }
13426
+ case "forget": {
13427
+ const { runForget: runForget2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
13428
+ process.exit(await runForget2(positionals[0], { mesh: flags.mesh, json: !!flags.json }));
13429
+ break;
13430
+ }
12726
13431
  case "remind": {
12727
13432
  const { runRemind: runRemind2 } = await Promise.resolve().then(() => (init_remind(), exports_remind));
12728
13433
  await runRemind2({ mesh: flags.mesh }, positionals);
@@ -12733,6 +13438,64 @@ async function main() {
12733
13438
  await runProfile2(flags);
12734
13439
  break;
12735
13440
  }
13441
+ case "summary": {
13442
+ const { runSummary: runSummary2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
13443
+ process.exit(await runSummary2(positionals.join(" "), { mesh: flags.mesh, json: !!flags.json }));
13444
+ break;
13445
+ }
13446
+ case "visible": {
13447
+ const { runVisible: runVisible2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
13448
+ process.exit(await runVisible2(positionals[0], { mesh: flags.mesh, json: !!flags.json }));
13449
+ break;
13450
+ }
13451
+ case "group": {
13452
+ const sub = positionals[0];
13453
+ if (sub === "join") {
13454
+ const { runGroupJoin: runGroupJoin2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
13455
+ process.exit(await runGroupJoin2(positionals[1], { mesh: flags.mesh, role: flags.role, json: !!flags.json }));
13456
+ } else if (sub === "leave") {
13457
+ const { runGroupLeave: runGroupLeave2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
13458
+ process.exit(await runGroupLeave2(positionals[1], { mesh: flags.mesh, json: !!flags.json }));
13459
+ } else {
13460
+ console.error("Usage: claudemesh group <join|leave> @<name> [--role X]");
13461
+ process.exit(EXIT.INVALID_ARGS);
13462
+ }
13463
+ break;
13464
+ }
13465
+ case "msg-status": {
13466
+ const { runMsgStatus: runMsgStatus2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
13467
+ process.exit(await runMsgStatus2(positionals[0], { mesh: flags.mesh, json: !!flags.json }));
13468
+ break;
13469
+ }
13470
+ case "clock": {
13471
+ const { runClock: runClock2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
13472
+ process.exit(await runClock2({ mesh: flags.mesh, json: !!flags.json }));
13473
+ break;
13474
+ }
13475
+ case "stats": {
13476
+ const { runStats: runStats2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
13477
+ process.exit(await runStats2({ mesh: flags.mesh, json: !!flags.json }));
13478
+ break;
13479
+ }
13480
+ case "ping": {
13481
+ const { runPing: runPing2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
13482
+ process.exit(await runPing2({ mesh: flags.mesh, json: !!flags.json }));
13483
+ break;
13484
+ }
13485
+ case "task": {
13486
+ const sub = positionals[0];
13487
+ if (sub === "claim") {
13488
+ const { runTaskClaim: runTaskClaim2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
13489
+ process.exit(await runTaskClaim2(positionals[1], { mesh: flags.mesh, json: !!flags.json }));
13490
+ } else if (sub === "complete") {
13491
+ const { runTaskComplete: runTaskComplete2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
13492
+ process.exit(await runTaskComplete2(positionals[1], positionals.slice(2).join(" ") || undefined, { mesh: flags.mesh, json: !!flags.json }));
13493
+ } else {
13494
+ console.error("Usage: claudemesh task <claim|complete> <id> [result]");
13495
+ process.exit(EXIT.INVALID_ARGS);
13496
+ }
13497
+ break;
13498
+ }
12736
13499
  case "login": {
12737
13500
  const { login: login2 } = await Promise.resolve().then(() => (init_login(), exports_login));
12738
13501
  process.exit(await login2());
@@ -12769,8 +13532,13 @@ async function main() {
12769
13532
  break;
12770
13533
  }
12771
13534
  case "status": {
12772
- const { runStatus: runStatus2 } = await Promise.resolve().then(() => (init_status(), exports_status));
12773
- await runStatus2();
13535
+ if (positionals[0] === "set") {
13536
+ const { runStatusSet: runStatusSet2 } = await Promise.resolve().then(() => (init_broker_actions(), exports_broker_actions));
13537
+ process.exit(await runStatusSet2(positionals[1] ?? "", { mesh: flags.mesh, json: !!flags.json }));
13538
+ } else {
13539
+ const { runStatus: runStatus2 } = await Promise.resolve().then(() => (init_status(), exports_status));
13540
+ await runStatus2();
13541
+ }
12774
13542
  break;
12775
13543
  }
12776
13544
  case "sync": {
@@ -12866,4 +13634,4 @@ main().catch((err) => {
12866
13634
  process.exit(EXIT.INTERNAL_ERROR);
12867
13635
  });
12868
13636
 
12869
- //# debugId=AC9613431467FF4964756E2164756E21
13637
+ //# debugId=25926A42D1A4B83764756E2164756E21