claudemesh-cli 1.1.0 → 1.2.0

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