claudemesh-cli 1.27.2 → 1.27.3

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.
@@ -103,7 +103,7 @@ __export(exports_urls, {
103
103
  VERSION: () => VERSION,
104
104
  URLS: () => URLS
105
105
  });
106
- var URLS, VERSION = "1.27.2", env;
106
+ var URLS, VERSION = "1.27.3", env;
107
107
  var init_urls = __esm(() => {
108
108
  URLS = {
109
109
  BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
@@ -3588,12 +3588,6 @@ var init_spinner = __esm(() => {
3588
3588
  });
3589
3589
 
3590
3590
  // src/daemon/paths.ts
3591
- var exports_paths = {};
3592
- __export(exports_paths, {
3593
- DAEMON_TCP_HOST: () => DAEMON_TCP_HOST,
3594
- DAEMON_TCP_DEFAULT_PORT: () => DAEMON_TCP_DEFAULT_PORT,
3595
- DAEMON_PATHS: () => DAEMON_PATHS
3596
- });
3597
3591
  import { join as join3 } from "node:path";
3598
3592
  var DAEMON_PATHS, DAEMON_TCP_HOST = "127.0.0.1", DAEMON_TCP_DEFAULT_PORT = 47823;
3599
3593
  var init_paths2 = __esm(() => {
@@ -3623,6 +3617,255 @@ var init_paths2 = __esm(() => {
3623
3617
  };
3624
3618
  });
3625
3619
 
3620
+ // src/daemon/local-token.ts
3621
+ import { mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
3622
+ import { dirname as dirname2 } from "node:path";
3623
+ import { randomBytes as randomBytes4 } from "node:crypto";
3624
+ function readLocalToken() {
3625
+ try {
3626
+ return readFileSync4(DAEMON_PATHS.TOKEN_FILE, "utf8").trim();
3627
+ } catch {
3628
+ return null;
3629
+ }
3630
+ }
3631
+ function ensureLocalToken() {
3632
+ const existing = readLocalToken();
3633
+ if (existing)
3634
+ return existing;
3635
+ mkdirSync3(dirname2(DAEMON_PATHS.TOKEN_FILE), { recursive: true, mode: 448 });
3636
+ const tok = randomBytes4(32).toString("base64url");
3637
+ writeFileSync4(DAEMON_PATHS.TOKEN_FILE, tok + `
3638
+ `, { mode: 384 });
3639
+ return tok;
3640
+ }
3641
+ var init_local_token = __esm(() => {
3642
+ init_paths2();
3643
+ });
3644
+
3645
+ // src/daemon/ipc/client.ts
3646
+ import { request as httpRequest } from "node:http";
3647
+ async function ipc(opts) {
3648
+ const useTcp = !!opts.preferTcp;
3649
+ const headers = {
3650
+ accept: "application/json",
3651
+ host: "localhost"
3652
+ };
3653
+ let bodyBuf;
3654
+ if (opts.body !== undefined) {
3655
+ bodyBuf = Buffer.from(JSON.stringify(opts.body), "utf8");
3656
+ headers["content-type"] = "application/json";
3657
+ headers["content-length"] = String(bodyBuf.length);
3658
+ }
3659
+ if (useTcp) {
3660
+ const tok = readLocalToken();
3661
+ if (!tok)
3662
+ throw new IpcError(0, null, "daemon local token not found; is the daemon running?");
3663
+ headers.authorization = `Bearer ${tok}`;
3664
+ }
3665
+ return new Promise((resolve, reject) => {
3666
+ const req = httpRequest(useTcp ? { host: DAEMON_TCP_HOST, port: DAEMON_TCP_DEFAULT_PORT, path: opts.path, method: opts.method ?? "GET", headers } : { socketPath: DAEMON_PATHS.SOCK_FILE, path: opts.path, method: opts.method ?? "GET", headers }, (res) => {
3667
+ const chunks = [];
3668
+ res.on("data", (c) => chunks.push(c));
3669
+ res.on("end", () => {
3670
+ const raw = Buffer.concat(chunks).toString("utf8");
3671
+ let parsed = raw;
3672
+ try {
3673
+ parsed = raw.length > 0 ? JSON.parse(raw) : null;
3674
+ } catch {}
3675
+ resolve({ status: res.statusCode ?? 0, body: parsed });
3676
+ });
3677
+ });
3678
+ req.setTimeout(opts.timeoutMs ?? 5000, () => req.destroy(new Error("ipc_timeout")));
3679
+ req.on("error", (err) => reject(err));
3680
+ if (bodyBuf)
3681
+ req.write(bodyBuf);
3682
+ req.end();
3683
+ });
3684
+ }
3685
+ var IpcError;
3686
+ var init_client3 = __esm(() => {
3687
+ init_paths2();
3688
+ init_local_token();
3689
+ IpcError = class IpcError extends Error {
3690
+ status;
3691
+ payload;
3692
+ constructor(status, payload, msg) {
3693
+ super(msg);
3694
+ this.status = status;
3695
+ this.payload = payload;
3696
+ }
3697
+ };
3698
+ });
3699
+
3700
+ // src/services/daemon/lifecycle.ts
3701
+ var exports_lifecycle = {};
3702
+ __export(exports_lifecycle, {
3703
+ ensureDaemonReady: () => ensureDaemonReady,
3704
+ _resetDaemonReadyCache: () => _resetDaemonReadyCache
3705
+ });
3706
+ import { existsSync as existsSync5, readFileSync as readFileSync5, statSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
3707
+ import { join as join4 } from "node:path";
3708
+ async function ensureDaemonReady(opts = {}) {
3709
+ if (lastResultThisProcess && (lastResultThisProcess.state === "up" || lastResultThisProcess.state === "started")) {
3710
+ return lastResultThisProcess;
3711
+ }
3712
+ if (process.env.CLAUDEMESH_INTERNAL_NO_AUTOSPAWN === "1") {
3713
+ opts = { ...opts, noAutoSpawn: true };
3714
+ }
3715
+ const result = await runEnsureDaemon(opts);
3716
+ lastResultThisProcess = result;
3717
+ return result;
3718
+ }
3719
+ function _resetDaemonReadyCache() {
3720
+ lastResultThisProcess = null;
3721
+ }
3722
+ async function runEnsureDaemon(opts) {
3723
+ const t0 = Date.now();
3724
+ const probe = await probeDaemon();
3725
+ if (probe === "up")
3726
+ return { state: "up", durationMs: Date.now() - t0 };
3727
+ if (probe === "stale")
3728
+ cleanupStaleFiles();
3729
+ if (opts.noAutoSpawn) {
3730
+ return { state: "down", durationMs: Date.now() - t0, reason: "auto-spawn disabled" };
3731
+ }
3732
+ if (recentSpawnFailureFresh()) {
3733
+ return {
3734
+ state: "spawn-suppressed",
3735
+ durationMs: Date.now() - t0,
3736
+ reason: `daemon failed to start within last ${Math.round(SPAWN_FAIL_TTL_MS / 1000)}s`
3737
+ };
3738
+ }
3739
+ const spawnRes = await spawnDaemon(opts);
3740
+ if (spawnRes.ok) {
3741
+ return { state: "started", durationMs: Date.now() - t0 };
3742
+ }
3743
+ markSpawnFailure();
3744
+ return { state: "spawn-failed", durationMs: Date.now() - t0, reason: spawnRes.reason };
3745
+ }
3746
+ async function probeDaemon() {
3747
+ if (!existsSync5(DAEMON_PATHS.SOCK_FILE))
3748
+ return "absent";
3749
+ try {
3750
+ const res = await ipc({ path: "/v1/version", timeoutMs: PROBE_TIMEOUT_MS });
3751
+ if (res.status === 200)
3752
+ return "up";
3753
+ return "stale";
3754
+ } catch (err) {
3755
+ if (err instanceof IpcError)
3756
+ return "stale";
3757
+ const msg = String(err);
3758
+ if (/ENOENT|ECONNREFUSED|ipc_timeout|EPIPE|ECONNRESET/.test(msg))
3759
+ return "stale";
3760
+ return "stale";
3761
+ }
3762
+ }
3763
+ function cleanupStaleFiles() {
3764
+ for (const p of [DAEMON_PATHS.SOCK_FILE, DAEMON_PATHS.PID_FILE]) {
3765
+ try {
3766
+ unlinkSync2(p);
3767
+ } catch {}
3768
+ }
3769
+ }
3770
+ function recentSpawnFailureFresh() {
3771
+ try {
3772
+ const st = statSync(SPAWN_FAIL_FILE());
3773
+ return Date.now() - st.mtimeMs < SPAWN_FAIL_TTL_MS;
3774
+ } catch {
3775
+ return false;
3776
+ }
3777
+ }
3778
+ function markSpawnFailure() {
3779
+ try {
3780
+ writeFileSync5(SPAWN_FAIL_FILE(), String(Date.now()), { mode: 384 });
3781
+ } catch {}
3782
+ }
3783
+ function clearSpawnFailure() {
3784
+ try {
3785
+ unlinkSync2(SPAWN_FAIL_FILE());
3786
+ } catch {}
3787
+ }
3788
+ async function spawnDaemon(opts) {
3789
+ const lockResult = await acquireOrShareLock(opts);
3790
+ if (lockResult === "wait-existing") {
3791
+ return await pollForSocket(opts.budgetMs ?? 3000);
3792
+ }
3793
+ try {
3794
+ const { spawn } = await import("node:child_process");
3795
+ const binary = await resolveCliBinary();
3796
+ const args = ["daemon", "up"];
3797
+ if (opts.mesh)
3798
+ args.push("--mesh", opts.mesh);
3799
+ const child = spawn(binary, args, {
3800
+ detached: true,
3801
+ stdio: "ignore",
3802
+ env: { ...process.env, CLAUDEMESH_INTERNAL_NO_AUTOSPAWN: "1" }
3803
+ });
3804
+ child.unref();
3805
+ const polled = await pollForSocket(opts.budgetMs ?? 3000);
3806
+ if (polled.ok)
3807
+ clearSpawnFailure();
3808
+ return polled;
3809
+ } catch (err) {
3810
+ return { ok: false, reason: err instanceof Error ? err.message : String(err) };
3811
+ } finally {
3812
+ releaseLock();
3813
+ }
3814
+ }
3815
+ async function acquireOrShareLock(_opts) {
3816
+ const lockPath = SPAWN_LOCK_FILE();
3817
+ if (existsSync5(lockPath)) {
3818
+ try {
3819
+ const pidStr = readFileSync5(lockPath, "utf8").trim();
3820
+ const pid = Number.parseInt(pidStr, 10);
3821
+ if (Number.isFinite(pid) && pid > 0) {
3822
+ try {
3823
+ process.kill(pid, 0);
3824
+ return "wait-existing";
3825
+ } catch {}
3826
+ }
3827
+ } catch {}
3828
+ }
3829
+ try {
3830
+ writeFileSync5(lockPath, String(process.pid), { mode: 384 });
3831
+ } catch {}
3832
+ return "acquired";
3833
+ }
3834
+ function releaseLock() {
3835
+ try {
3836
+ unlinkSync2(SPAWN_LOCK_FILE());
3837
+ } catch {}
3838
+ }
3839
+ async function pollForSocket(budgetMs) {
3840
+ const start = Date.now();
3841
+ while (Date.now() - start < budgetMs) {
3842
+ if (existsSync5(DAEMON_PATHS.SOCK_FILE)) {
3843
+ const probe = await probeDaemon();
3844
+ if (probe === "up")
3845
+ return { ok: true };
3846
+ }
3847
+ await new Promise((r) => setTimeout(r, 150));
3848
+ }
3849
+ return { ok: false, reason: `socket did not appear within ${budgetMs}ms` };
3850
+ }
3851
+ async function resolveCliBinary() {
3852
+ const argv1 = process.argv[1] ?? "claudemesh";
3853
+ if (/\.ts$/.test(argv1) || /node_modules|src\/entrypoints/.test(argv1)) {
3854
+ try {
3855
+ const { execSync } = await import("node:child_process");
3856
+ return execSync("which claudemesh", { encoding: "utf8" }).trim() || "claudemesh";
3857
+ } catch {
3858
+ return "claudemesh";
3859
+ }
3860
+ }
3861
+ return argv1;
3862
+ }
3863
+ var SPAWN_LOCK_FILE = () => join4(DAEMON_PATHS.DAEMON_DIR, ".spawn.lock"), SPAWN_FAIL_FILE = () => join4(DAEMON_PATHS.DAEMON_DIR, ".spawn-failure"), SPAWN_FAIL_TTL_MS = 30000, PROBE_TIMEOUT_MS = 800, lastResultThisProcess = null;
3864
+ var init_lifecycle = __esm(() => {
3865
+ init_client3();
3866
+ init_paths2();
3867
+ });
3868
+
3626
3869
  // src/commands/launch.ts
3627
3870
  var exports_launch = {};
3628
3871
  __export(exports_launch, {
@@ -3630,42 +3873,26 @@ __export(exports_launch, {
3630
3873
  });
3631
3874
  import { spawnSync as spawnSync2 } from "node:child_process";
3632
3875
  import { randomUUID } from "node:crypto";
3633
- import { mkdtempSync, writeFileSync as writeFileSync4, rmSync, readdirSync, statSync, existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
3876
+ import { mkdtempSync, writeFileSync as writeFileSync6, rmSync, readdirSync, statSync as statSync2, existsSync as existsSync6, readFileSync as readFileSync6 } from "node:fs";
3634
3877
  import { tmpdir, hostname as hostname2, homedir as homedir3 } from "node:os";
3635
- import { join as join4 } from "node:path";
3878
+ import { join as join5 } from "node:path";
3636
3879
  import { createInterface as createInterface4 } from "node:readline";
3637
3880
  async function ensureDaemonRunning(meshSlug, quiet) {
3638
- const { DAEMON_PATHS: DAEMON_PATHS2 } = await Promise.resolve().then(() => (init_paths2(), exports_paths));
3639
- if (existsSync5(DAEMON_PATHS2.SOCK_FILE))
3640
- return;
3881
+ const { ensureDaemonReady: ensureDaemonReady2 } = await Promise.resolve().then(() => (init_lifecycle(), exports_lifecycle));
3641
3882
  if (!quiet)
3642
- render.info("starting claudemesh daemon…");
3643
- const { spawn } = await import("node:child_process");
3644
- const argv0 = process.argv[1] ?? "claudemesh";
3645
- let binary = argv0;
3646
- if (/\.ts$/.test(binary) || /node_modules|src\/entrypoints/.test(binary)) {
3647
- try {
3648
- const { execSync } = await import("node:child_process");
3649
- binary = execSync("which claudemesh", { encoding: "utf8" }).trim();
3650
- } catch {
3651
- binary = "claudemesh";
3652
- }
3883
+ render.info("ensuring claudemesh daemon is running…");
3884
+ const res = await ensureDaemonReady2({ budgetMs: 1e4, mesh: meshSlug });
3885
+ if (res.state === "up") {
3886
+ if (!quiet)
3887
+ render.ok("daemon already running");
3888
+ return;
3653
3889
  }
3654
- const child = spawn(binary, ["daemon", "up", "--mesh", meshSlug], {
3655
- detached: true,
3656
- stdio: "ignore"
3657
- });
3658
- child.unref();
3659
- const start = Date.now();
3660
- while (Date.now() - start < 1e4) {
3661
- if (existsSync5(DAEMON_PATHS2.SOCK_FILE)) {
3662
- if (!quiet)
3663
- render.ok("daemon ready");
3664
- return;
3665
- }
3666
- await new Promise((r) => setTimeout(r, 200));
3890
+ if (res.state === "started") {
3891
+ if (!quiet)
3892
+ render.ok(`daemon ready (${res.durationMs}ms)`);
3893
+ return;
3667
3894
  }
3668
- render.warn("daemon failed to start within 10s", "Run `claudemesh daemon up --mesh " + meshSlug + "` manually, then re-launch.");
3895
+ render.warn(`daemon ${res.state}${res.reason ? `: ${res.reason}` : ""}`, "Run `claudemesh daemon up --mesh " + meshSlug + "` manually, then re-launch.");
3669
3896
  }
3670
3897
  function parseGroupsString(raw) {
3671
3898
  return raw.split(",").map((s) => s.trim()).filter(Boolean).map((token) => {
@@ -3986,17 +4213,17 @@ async function runLaunch(flags, rawArgs) {
3986
4213
  for (const entry of readdirSync(tmpBase)) {
3987
4214
  if (!entry.startsWith("claudemesh-"))
3988
4215
  continue;
3989
- const full = join4(tmpBase, entry);
3990
- const age = Date.now() - statSync(full).mtimeMs;
4216
+ const full = join5(tmpBase, entry);
4217
+ const age = Date.now() - statSync2(full).mtimeMs;
3991
4218
  if (age > 3600000)
3992
4219
  rmSync(full, { recursive: true, force: true });
3993
4220
  }
3994
4221
  } catch {}
3995
4222
  await ensureDaemonRunning(mesh.slug, args.quiet);
3996
4223
  try {
3997
- const claudeConfigPath = join4(homedir3(), ".claude.json");
3998
- if (existsSync5(claudeConfigPath)) {
3999
- const claudeConfig = JSON.parse(readFileSync4(claudeConfigPath, "utf-8"));
4224
+ const claudeConfigPath = join5(homedir3(), ".claude.json");
4225
+ if (existsSync6(claudeConfigPath)) {
4226
+ const claudeConfig = JSON.parse(readFileSync6(claudeConfigPath, "utf-8"));
4000
4227
  const mcpServers = claudeConfig.mcpServers ?? {};
4001
4228
  let cleaned = 0;
4002
4229
  for (const key of Object.keys(mcpServers)) {
@@ -4014,7 +4241,7 @@ async function runLaunch(flags, rawArgs) {
4014
4241
  }
4015
4242
  if (cleaned > 0) {
4016
4243
  claudeConfig.mcpServers = mcpServers;
4017
- writeFileSync4(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
4244
+ writeFileSync6(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
4018
4245
  `, "utf-8");
4019
4246
  }
4020
4247
  }
@@ -4031,7 +4258,7 @@ async function runLaunch(flags, rawArgs) {
4031
4258
  console.log(" (Could not fetch service catalog — mesh services won't be natively available)");
4032
4259
  }
4033
4260
  }
4034
- const tmpDir = mkdtempSync(join4(tmpdir(), "claudemesh-"));
4261
+ const tmpDir = mkdtempSync(join5(tmpdir(), "claudemesh-"));
4035
4262
  const sessionConfig = {
4036
4263
  version: 1,
4037
4264
  meshes: [mesh],
@@ -4040,17 +4267,17 @@ async function runLaunch(flags, rawArgs) {
4040
4267
  ...parsedGroups.length > 0 ? { groups: parsedGroups } : {},
4041
4268
  messageMode
4042
4269
  };
4043
- writeFileSync4(join4(tmpDir, "config.json"), JSON.stringify(sessionConfig, null, 2) + `
4270
+ writeFileSync6(join5(tmpDir, "config.json"), JSON.stringify(sessionConfig, null, 2) + `
4044
4271
  `, "utf-8");
4045
4272
  if (!args.quiet) {
4046
4273
  printBanner(displayName, mesh.slug, role, parsedGroups, messageMode);
4047
4274
  }
4048
4275
  const meshMcpEntries = [];
4049
4276
  if (serviceCatalog.length > 0) {
4050
- const claudeConfigPath = join4(homedir3(), ".claude.json");
4277
+ const claudeConfigPath = join5(homedir3(), ".claude.json");
4051
4278
  let claudeConfig = {};
4052
4279
  try {
4053
- claudeConfig = JSON.parse(readFileSync4(claudeConfigPath, "utf-8"));
4280
+ claudeConfig = JSON.parse(readFileSync6(claudeConfigPath, "utf-8"));
4054
4281
  } catch {
4055
4282
  claudeConfig = {};
4056
4283
  }
@@ -4077,7 +4304,7 @@ async function runLaunch(flags, rawArgs) {
4077
4304
  meshMcpEntries.push({ key: entryKey, entry });
4078
4305
  }
4079
4306
  claudeConfig.mcpServers = mcpServers;
4080
- writeFileSync4(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
4307
+ writeFileSync6(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
4081
4308
  `, "utf-8");
4082
4309
  if (!args.quiet && meshMcpEntries.length > 0) {
4083
4310
  console.log(` ${meshMcpEntries.length} mesh service(s) registered as native MCPs:`);
@@ -4114,12 +4341,12 @@ async function runLaunch(flags, rawArgs) {
4114
4341
  let claudeBin = "claude";
4115
4342
  if (!isWindows2) {
4116
4343
  const candidates = [
4117
- join4(homedir3(), ".local", "bin", "claude"),
4344
+ join5(homedir3(), ".local", "bin", "claude"),
4118
4345
  "/usr/local/bin/claude",
4119
- join4(homedir3(), ".claude", "bin", "claude")
4346
+ join5(homedir3(), ".claude", "bin", "claude")
4120
4347
  ];
4121
4348
  for (const c of candidates) {
4122
- if (existsSync5(c)) {
4349
+ if (existsSync6(c)) {
4123
4350
  claudeBin = c;
4124
4351
  break;
4125
4352
  }
@@ -4128,14 +4355,14 @@ async function runLaunch(flags, rawArgs) {
4128
4355
  const cleanup = () => {
4129
4356
  if (meshMcpEntries.length > 0) {
4130
4357
  try {
4131
- const claudeConfigPath = join4(homedir3(), ".claude.json");
4132
- const claudeConfig = JSON.parse(readFileSync4(claudeConfigPath, "utf-8"));
4358
+ const claudeConfigPath = join5(homedir3(), ".claude.json");
4359
+ const claudeConfig = JSON.parse(readFileSync6(claudeConfigPath, "utf-8"));
4133
4360
  const mcpServers = claudeConfig.mcpServers ?? {};
4134
4361
  for (const { key } of meshMcpEntries) {
4135
4362
  delete mcpServers[key];
4136
4363
  }
4137
4364
  claudeConfig.mcpServers = mcpServers;
4138
- writeFileSync4(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
4365
+ writeFileSync6(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
4139
4366
  `, "utf-8");
4140
4367
  } catch {}
4141
4368
  }
@@ -4832,8 +5059,8 @@ __export(exports_join, {
4832
5059
  runJoin: () => runJoin
4833
5060
  });
4834
5061
  import sodium3 from "libsodium-wrappers";
4835
- import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync3 } from "node:fs";
4836
- import { join as join5, dirname as dirname2 } from "node:path";
5062
+ import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync4 } from "node:fs";
5063
+ import { join as join6, dirname as dirname3 } from "node:path";
4837
5064
  import { homedir as homedir4, hostname as hostname3 } from "node:os";
4838
5065
  function deriveAppBaseUrl() {
4839
5066
  const override = process.env.CLAUDEMESH_APP_URL;
@@ -4953,11 +5180,11 @@ async function runJoin(args) {
4953
5180
  joinedAt: new Date().toISOString()
4954
5181
  });
4955
5182
  writeConfig(config);
4956
- const configDir = env.CLAUDEMESH_CONFIG_DIR ?? join5(homedir4(), ".claudemesh");
4957
- const inviteFile = join5(configDir, `invite-${payload.mesh_slug}.txt`);
5183
+ const configDir = env.CLAUDEMESH_CONFIG_DIR ?? join6(homedir4(), ".claudemesh");
5184
+ const inviteFile = join6(configDir, `invite-${payload.mesh_slug}.txt`);
4958
5185
  try {
4959
- mkdirSync3(dirname2(inviteFile), { recursive: true });
4960
- writeFileSync5(inviteFile, link, "utf-8");
5186
+ mkdirSync4(dirname3(inviteFile), { recursive: true });
5187
+ writeFileSync7(inviteFile, link, "utf-8");
4961
5188
  } catch {}
4962
5189
  console.log("");
4963
5190
  console.log(`✓ Joined "${payload.mesh_slug}" as ${displayName}${enroll.alreadyMember ? " (already a member — re-enrolled with same pubkey)" : ""}`);
@@ -7160,9 +7387,9 @@ var init_ban = __esm(() => {
7160
7387
 
7161
7388
  // src/services/bridge/protocol.ts
7162
7389
  import { homedir as homedir5 } from "node:os";
7163
- import { join as join6 } from "node:path";
7390
+ import { join as join7 } from "node:path";
7164
7391
  function socketPath(meshSlug) {
7165
- return join6(homedir5(), ".claudemesh", "sockets", `${meshSlug}.sock`);
7392
+ return join7(homedir5(), ".claudemesh", "sockets", `${meshSlug}.sock`);
7166
7393
  }
7167
7394
  function frame(obj) {
7168
7395
  return JSON.stringify(obj) + `
@@ -7189,11 +7416,11 @@ var init_protocol = () => {};
7189
7416
 
7190
7417
  // src/services/bridge/client.ts
7191
7418
  import { createConnection } from "node:net";
7192
- import { existsSync as existsSync6 } from "node:fs";
7419
+ import { existsSync as existsSync7 } from "node:fs";
7193
7420
  import { randomUUID as randomUUID2 } from "node:crypto";
7194
7421
  async function tryBridge(meshSlug, verb, args = {}, timeoutMs = DEFAULT_TIMEOUT_MS) {
7195
7422
  const path = socketPath(meshSlug);
7196
- if (!existsSync6(path))
7423
+ if (!existsSync7(path))
7197
7424
  return null;
7198
7425
  return new Promise((resolve) => {
7199
7426
  const id = randomUUID2();
@@ -7255,88 +7482,44 @@ async function tryBridge(meshSlug, verb, args = {}, timeoutMs = DEFAULT_TIMEOUT_
7255
7482
  });
7256
7483
  }
7257
7484
  var DEFAULT_TIMEOUT_MS = 5000;
7258
- var init_client3 = __esm(() => {
7485
+ var init_client4 = __esm(() => {
7259
7486
  init_protocol();
7260
7487
  });
7261
7488
 
7262
- // src/daemon/local-token.ts
7263
- import { mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "node:fs";
7264
- import { dirname as dirname3 } from "node:path";
7265
- import { randomBytes as randomBytes4 } from "node:crypto";
7266
- function readLocalToken() {
7267
- try {
7268
- return readFileSync5(DAEMON_PATHS.TOKEN_FILE, "utf8").trim();
7269
- } catch {
7270
- return null;
7271
- }
7272
- }
7273
- function ensureLocalToken() {
7274
- const existing = readLocalToken();
7275
- if (existing)
7276
- return existing;
7277
- mkdirSync4(dirname3(DAEMON_PATHS.TOKEN_FILE), { recursive: true, mode: 448 });
7278
- const tok = randomBytes4(32).toString("base64url");
7279
- writeFileSync6(DAEMON_PATHS.TOKEN_FILE, tok + `
7280
- `, { mode: 384 });
7281
- return tok;
7282
- }
7283
- var init_local_token = __esm(() => {
7284
- init_paths2();
7285
- });
7286
-
7287
- // src/daemon/ipc/client.ts
7288
- import { request as httpRequest } from "node:http";
7289
- async function ipc(opts) {
7290
- const useTcp = !!opts.preferTcp;
7291
- const headers = {
7292
- accept: "application/json",
7293
- host: "localhost"
7294
- };
7295
- let bodyBuf;
7296
- if (opts.body !== undefined) {
7297
- bodyBuf = Buffer.from(JSON.stringify(opts.body), "utf8");
7298
- headers["content-type"] = "application/json";
7299
- headers["content-length"] = String(bodyBuf.length);
7300
- }
7301
- if (useTcp) {
7302
- const tok = readLocalToken();
7303
- if (!tok)
7304
- throw new IpcError(0, null, "daemon local token not found; is the daemon running?");
7305
- headers.authorization = `Bearer ${tok}`;
7489
+ // src/ui/warnings.ts
7490
+ function warnDaemonState(res, opts = {}) {
7491
+ if (alreadyWarned)
7492
+ return false;
7493
+ if (opts.quiet || opts.json)
7494
+ return false;
7495
+ if (res.state === "up")
7496
+ return false;
7497
+ alreadyWarned = true;
7498
+ const tag = (label) => `[claudemesh] ${label}`;
7499
+ const hint = (s) => dim(s);
7500
+ switch (res.state) {
7501
+ case "started":
7502
+ process.stderr.write(`${tag("info")} daemon restarted automatically ${hint(`(took ${res.durationMs}ms)`)}
7503
+ `);
7504
+ return true;
7505
+ case "down":
7506
+ process.stderr.write(`${tag("info")} daemon not running — using cold path ${hint("(slower; run `claudemesh daemon up` for warm path)")}
7507
+ `);
7508
+ return true;
7509
+ case "spawn-suppressed":
7510
+ process.stderr.write(`${tag("warn")} ${res.reason ?? "daemon failed to start recently"} — using cold path ${hint("(run `claudemesh doctor`)")}
7511
+ `);
7512
+ return true;
7513
+ case "spawn-failed":
7514
+ process.stderr.write(`${tag("warn")} daemon spawn failed${res.reason ? `: ${res.reason}` : ""} — using cold path ${hint("(check ~/.claudemesh/daemon/daemon.log)")}
7515
+ `);
7516
+ return true;
7306
7517
  }
7307
- return new Promise((resolve, reject) => {
7308
- const req = httpRequest(useTcp ? { host: DAEMON_TCP_HOST, port: DAEMON_TCP_DEFAULT_PORT, path: opts.path, method: opts.method ?? "GET", headers } : { socketPath: DAEMON_PATHS.SOCK_FILE, path: opts.path, method: opts.method ?? "GET", headers }, (res) => {
7309
- const chunks = [];
7310
- res.on("data", (c) => chunks.push(c));
7311
- res.on("end", () => {
7312
- const raw = Buffer.concat(chunks).toString("utf8");
7313
- let parsed = raw;
7314
- try {
7315
- parsed = raw.length > 0 ? JSON.parse(raw) : null;
7316
- } catch {}
7317
- resolve({ status: res.statusCode ?? 0, body: parsed });
7318
- });
7319
- });
7320
- req.setTimeout(opts.timeoutMs ?? 5000, () => req.destroy(new Error("ipc_timeout")));
7321
- req.on("error", (err) => reject(err));
7322
- if (bodyBuf)
7323
- req.write(bodyBuf);
7324
- req.end();
7325
- });
7518
+ return false;
7326
7519
  }
7327
- var IpcError;
7328
- var init_client4 = __esm(() => {
7329
- init_paths2();
7330
- init_local_token();
7331
- IpcError = class IpcError extends Error {
7332
- status;
7333
- payload;
7334
- constructor(status, payload, msg) {
7335
- super(msg);
7336
- this.status = status;
7337
- this.payload = payload;
7338
- }
7339
- };
7520
+ var alreadyWarned = false;
7521
+ var init_warnings = __esm(() => {
7522
+ init_styles();
7340
7523
  });
7341
7524
 
7342
7525
  // src/services/bridge/daemon-route.ts
@@ -7353,12 +7536,16 @@ __export(exports_daemon_route, {
7353
7536
  tryGetSkillViaDaemon: () => tryGetSkillViaDaemon,
7354
7537
  tryForgetViaDaemon: () => tryForgetViaDaemon
7355
7538
  });
7356
- import { existsSync as existsSync7 } from "node:fs";
7357
7539
  function meshQuery(mesh) {
7358
7540
  return mesh ? `?mesh=${encodeURIComponent(mesh)}` : "";
7359
7541
  }
7542
+ async function daemonReachable() {
7543
+ const res = await ensureDaemonReady();
7544
+ warnDaemonState(res, {});
7545
+ return res.state === "up" || res.state === "started";
7546
+ }
7360
7547
  async function tryListPeersViaDaemon(mesh) {
7361
- if (!existsSync7(DAEMON_PATHS.SOCK_FILE))
7548
+ if (!await daemonReachable())
7362
7549
  return null;
7363
7550
  try {
7364
7551
  const res = await ipc({ path: `/v1/peers${meshQuery(mesh)}`, timeoutMs: 3000 });
@@ -7373,7 +7560,7 @@ async function tryListPeersViaDaemon(mesh) {
7373
7560
  }
7374
7561
  }
7375
7562
  async function tryListSkillsViaDaemon(mesh) {
7376
- if (!existsSync7(DAEMON_PATHS.SOCK_FILE))
7563
+ if (!await daemonReachable())
7377
7564
  return null;
7378
7565
  try {
7379
7566
  const res = await ipc({ path: `/v1/skills${meshQuery(mesh)}`, timeoutMs: 3000 });
@@ -7388,7 +7575,7 @@ async function tryListSkillsViaDaemon(mesh) {
7388
7575
  }
7389
7576
  }
7390
7577
  async function tryGetSkillViaDaemon(name, mesh) {
7391
- if (!existsSync7(DAEMON_PATHS.SOCK_FILE))
7578
+ if (!await daemonReachable())
7392
7579
  return null;
7393
7580
  try {
7394
7581
  const res = await ipc({
@@ -7405,7 +7592,7 @@ async function tryGetSkillViaDaemon(name, mesh) {
7405
7592
  }
7406
7593
  }
7407
7594
  async function tryGetStateViaDaemon(key, mesh) {
7408
- if (!existsSync7(DAEMON_PATHS.SOCK_FILE))
7595
+ if (!await daemonReachable())
7409
7596
  return null;
7410
7597
  try {
7411
7598
  const path = `/v1/state?key=${encodeURIComponent(key)}${mesh ? `&mesh=${encodeURIComponent(mesh)}` : ""}`;
@@ -7423,7 +7610,7 @@ async function tryGetStateViaDaemon(key, mesh) {
7423
7610
  }
7424
7611
  }
7425
7612
  async function tryListStateViaDaemon(mesh) {
7426
- if (!existsSync7(DAEMON_PATHS.SOCK_FILE))
7613
+ if (!await daemonReachable())
7427
7614
  return null;
7428
7615
  try {
7429
7616
  const res = await ipc({ path: `/v1/state${meshQuery(mesh)}`, timeoutMs: 3000 });
@@ -7438,7 +7625,7 @@ async function tryListStateViaDaemon(mesh) {
7438
7625
  }
7439
7626
  }
7440
7627
  async function trySetStateViaDaemon(key, value, mesh) {
7441
- if (!existsSync7(DAEMON_PATHS.SOCK_FILE))
7628
+ if (!await daemonReachable())
7442
7629
  return false;
7443
7630
  try {
7444
7631
  const res = await ipc({
@@ -7453,7 +7640,7 @@ async function trySetStateViaDaemon(key, value, mesh) {
7453
7640
  }
7454
7641
  }
7455
7642
  async function tryRememberViaDaemon(content, tags, mesh) {
7456
- if (!existsSync7(DAEMON_PATHS.SOCK_FILE))
7643
+ if (!await daemonReachable())
7457
7644
  return null;
7458
7645
  try {
7459
7646
  const res = await ipc({
@@ -7470,7 +7657,7 @@ async function tryRememberViaDaemon(content, tags, mesh) {
7470
7657
  }
7471
7658
  }
7472
7659
  async function tryRecallViaDaemon(query, mesh) {
7473
- if (!existsSync7(DAEMON_PATHS.SOCK_FILE))
7660
+ if (!await daemonReachable())
7474
7661
  return null;
7475
7662
  try {
7476
7663
  const path = `/v1/memory?q=${encodeURIComponent(query)}${mesh ? `&mesh=${encodeURIComponent(mesh)}` : ""}`;
@@ -7486,7 +7673,7 @@ async function tryRecallViaDaemon(query, mesh) {
7486
7673
  }
7487
7674
  }
7488
7675
  async function tryForgetViaDaemon(id, mesh) {
7489
- if (!existsSync7(DAEMON_PATHS.SOCK_FILE))
7676
+ if (!await daemonReachable())
7490
7677
  return false;
7491
7678
  try {
7492
7679
  const path = `/v1/memory/${encodeURIComponent(id)}${meshQuery(mesh)}`;
@@ -7497,7 +7684,7 @@ async function tryForgetViaDaemon(id, mesh) {
7497
7684
  }
7498
7685
  }
7499
7686
  async function trySendViaDaemon(args) {
7500
- if (!existsSync7(DAEMON_PATHS.SOCK_FILE))
7687
+ if (!await daemonReachable())
7501
7688
  return null;
7502
7689
  try {
7503
7690
  const res = await ipc({
@@ -7529,8 +7716,9 @@ async function trySendViaDaemon(args) {
7529
7716
  }
7530
7717
  }
7531
7718
  var init_daemon_route = __esm(() => {
7532
- init_client4();
7533
- init_paths2();
7719
+ init_client3();
7720
+ init_lifecycle();
7721
+ init_warnings();
7534
7722
  });
7535
7723
 
7536
7724
  // src/commands/peers.ts
@@ -7631,7 +7819,7 @@ var FIELD_ALIAS;
7631
7819
  var init_peers = __esm(() => {
7632
7820
  init_connect();
7633
7821
  init_facade();
7634
- init_client3();
7822
+ init_client4();
7635
7823
  init_render();
7636
7824
  init_styles();
7637
7825
  FIELD_ALIAS = {
@@ -7739,7 +7927,7 @@ async function runSend(flags, to, message) {
7739
7927
  var init_send = __esm(() => {
7740
7928
  init_connect();
7741
7929
  init_facade();
7742
- init_client3();
7930
+ init_client4();
7743
7931
  init_daemon_route();
7744
7932
  init_render();
7745
7933
  init_styles();
@@ -8387,7 +8575,7 @@ async function runTaskComplete(id, result, opts) {
8387
8575
  var init_broker_actions = __esm(() => {
8388
8576
  init_connect();
8389
8577
  init_facade();
8390
- init_client3();
8578
+ init_client4();
8391
8579
  init_daemon_route();
8392
8580
  init_render();
8393
8581
  init_styles();
@@ -8622,35 +8810,35 @@ var init_whoami = __esm(() => {
8622
8810
  });
8623
8811
 
8624
8812
  // src/daemon/lock.ts
8625
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync7 } from "node:fs";
8813
+ import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeFileSync as writeFileSync8 } from "node:fs";
8626
8814
  import { dirname as dirname4 } from "node:path";
8627
8815
  function acquireSingletonLock() {
8628
8816
  mkdirSync5(dirname4(DAEMON_PATHS.PID_FILE), { recursive: true, mode: 448 });
8629
8817
  if (existsSync8(DAEMON_PATHS.PID_FILE)) {
8630
- const raw = readFileSync6(DAEMON_PATHS.PID_FILE, "utf8").trim();
8818
+ const raw = readFileSync7(DAEMON_PATHS.PID_FILE, "utf8").trim();
8631
8819
  const oldPid = Number.parseInt(raw, 10);
8632
8820
  if (Number.isFinite(oldPid) && oldPid > 0 && isProcessAlive(oldPid)) {
8633
8821
  return { result: "already-running", pid: oldPid };
8634
8822
  }
8635
8823
  try {
8636
- unlinkSync2(DAEMON_PATHS.PID_FILE);
8824
+ unlinkSync3(DAEMON_PATHS.PID_FILE);
8637
8825
  } catch {}
8638
- writeFileSync7(DAEMON_PATHS.PID_FILE, String(process.pid), { mode: 384 });
8826
+ writeFileSync8(DAEMON_PATHS.PID_FILE, String(process.pid), { mode: 384 });
8639
8827
  return { result: "stale", pid: process.pid };
8640
8828
  }
8641
- writeFileSync7(DAEMON_PATHS.PID_FILE, String(process.pid), { mode: 384 });
8829
+ writeFileSync8(DAEMON_PATHS.PID_FILE, String(process.pid), { mode: 384 });
8642
8830
  return { result: "acquired", pid: process.pid };
8643
8831
  }
8644
8832
  function releaseSingletonLock() {
8645
8833
  try {
8646
- const raw = readFileSync6(DAEMON_PATHS.PID_FILE, "utf8").trim();
8834
+ const raw = readFileSync7(DAEMON_PATHS.PID_FILE, "utf8").trim();
8647
8835
  if (Number.parseInt(raw, 10) === process.pid)
8648
- unlinkSync2(DAEMON_PATHS.PID_FILE);
8836
+ unlinkSync3(DAEMON_PATHS.PID_FILE);
8649
8837
  } catch {}
8650
8838
  }
8651
8839
  function readRunningPid() {
8652
8840
  try {
8653
- const raw = readFileSync6(DAEMON_PATHS.PID_FILE, "utf8").trim();
8841
+ const raw = readFileSync7(DAEMON_PATHS.PID_FILE, "utf8").trim();
8654
8842
  const pid = Number.parseInt(raw, 10);
8655
8843
  if (Number.isFinite(pid) && pid > 0 && isProcessAlive(pid))
8656
8844
  return pid;
@@ -9082,7 +9270,7 @@ function bindSseStream(res, bus) {
9082
9270
 
9083
9271
  // src/daemon/ipc/server.ts
9084
9272
  import { createServer as createServer2 } from "node:http";
9085
- import { chmodSync as chmodSync3, existsSync as existsSync9, unlinkSync as unlinkSync3 } from "node:fs";
9273
+ import { chmodSync as chmodSync3, existsSync as existsSync9, unlinkSync as unlinkSync4 } from "node:fs";
9086
9274
  import { timingSafeEqual } from "node:crypto";
9087
9275
  import { randomUUID as randomUUID4 } from "node:crypto";
9088
9276
  function startIpcServer(opts) {
@@ -9100,7 +9288,7 @@ function startIpcServer(opts) {
9100
9288
  });
9101
9289
  if (existsSync9(DAEMON_PATHS.SOCK_FILE)) {
9102
9290
  try {
9103
- unlinkSync3(DAEMON_PATHS.SOCK_FILE);
9291
+ unlinkSync4(DAEMON_PATHS.SOCK_FILE);
9104
9292
  } catch {}
9105
9293
  }
9106
9294
  const uds = createServer2(handler);
@@ -9136,7 +9324,7 @@ function startIpcServer(opts) {
9136
9324
  tcp ? new Promise((res) => tcp.close(() => res())) : Promise.resolve()
9137
9325
  ]);
9138
9326
  try {
9139
- unlinkSync3(DAEMON_PATHS.SOCK_FILE);
9327
+ unlinkSync4(DAEMON_PATHS.SOCK_FILE);
9140
9328
  } catch {}
9141
9329
  }
9142
9330
  };
@@ -10533,12 +10721,12 @@ __export(exports_identity, {
10533
10721
  checkFingerprint: () => checkFingerprint,
10534
10722
  acceptCurrentHost: () => acceptCurrentHost
10535
10723
  });
10536
- import { existsSync as existsSync10, readFileSync as readFileSync7, writeFileSync as writeFileSync8 } from "node:fs";
10537
- import { join as join7 } from "node:path";
10724
+ import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync9 } from "node:fs";
10725
+ import { join as join8 } from "node:path";
10538
10726
  import { createHash as createHash2 } from "node:crypto";
10539
10727
  import { networkInterfaces } from "node:os";
10540
10728
  function path() {
10541
- return join7(DAEMON_PATHS.DAEMON_DIR, FILE_NAME);
10729
+ return join8(DAEMON_PATHS.DAEMON_DIR, FILE_NAME);
10542
10730
  }
10543
10731
  function computeCurrentFingerprint() {
10544
10732
  const host_id = readHostId() ?? "";
@@ -10555,12 +10743,12 @@ function computeCurrentFingerprint() {
10555
10743
  function checkFingerprint() {
10556
10744
  const current = computeCurrentFingerprint();
10557
10745
  if (!existsSync10(path())) {
10558
- writeFileSync8(path(), JSON.stringify(current, null, 2), { mode: 384 });
10746
+ writeFileSync9(path(), JSON.stringify(current, null, 2), { mode: 384 });
10559
10747
  return { result: "first_run", current };
10560
10748
  }
10561
10749
  let stored;
10562
10750
  try {
10563
- stored = JSON.parse(readFileSync7(path(), "utf8"));
10751
+ stored = JSON.parse(readFileSync8(path(), "utf8"));
10564
10752
  } catch {
10565
10753
  return { result: "unavailable", current };
10566
10754
  }
@@ -10570,14 +10758,14 @@ function checkFingerprint() {
10570
10758
  }
10571
10759
  function acceptCurrentHost() {
10572
10760
  const current = computeCurrentFingerprint();
10573
- writeFileSync8(path(), JSON.stringify(current, null, 2), { mode: 384 });
10761
+ writeFileSync9(path(), JSON.stringify(current, null, 2), { mode: 384 });
10574
10762
  return current;
10575
10763
  }
10576
10764
  function readHostId() {
10577
10765
  if (process.platform === "linux") {
10578
10766
  for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
10579
10767
  try {
10580
- const raw = readFileSync7(p, "utf8").trim();
10768
+ const raw = readFileSync8(p, "utf8").trim();
10581
10769
  if (raw)
10582
10770
  return `linux:${raw}`;
10583
10771
  } catch {}
@@ -10622,7 +10810,7 @@ var init_identity = __esm(() => {
10622
10810
  });
10623
10811
 
10624
10812
  // src/daemon/run.ts
10625
- import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync8 } from "node:fs";
10813
+ import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync9 } from "node:fs";
10626
10814
  function detectContainer() {
10627
10815
  if (process.env.KUBERNETES_SERVICE_HOST)
10628
10816
  return true;
@@ -10631,7 +10819,7 @@ function detectContainer() {
10631
10819
  try {
10632
10820
  if (existsSync11("/.dockerenv"))
10633
10821
  return true;
10634
- const cg = readFileSync8("/proc/1/cgroup", "utf8");
10822
+ const cg = readFileSync9("/proc/1/cgroup", "utf8");
10635
10823
  if (/(docker|kubepods|containerd)/.test(cg))
10636
10824
  return true;
10637
10825
  } catch {}
@@ -10832,10 +11020,10 @@ __export(exports_service_install, {
10832
11020
  installService: () => installService,
10833
11021
  detectPlatform: () => detectPlatform
10834
11022
  });
10835
- import { existsSync as existsSync12, mkdirSync as mkdirSync7, writeFileSync as writeFileSync9, unlinkSync as unlinkSync4, readFileSync as readFileSync9 } from "node:fs";
11023
+ import { existsSync as existsSync12, mkdirSync as mkdirSync7, writeFileSync as writeFileSync10, unlinkSync as unlinkSync5, readFileSync as readFileSync10 } from "node:fs";
10836
11024
  import { execSync as execSync2 } from "node:child_process";
10837
11025
  import { homedir as homedir6 } from "node:os";
10838
- import { join as join8, dirname as dirname5 } from "node:path";
11026
+ import { join as join9, dirname as dirname5 } from "node:path";
10839
11027
  function detectPlatform() {
10840
11028
  if (process.platform === "darwin")
10841
11029
  return "darwin";
@@ -10870,7 +11058,7 @@ function uninstallService() {
10870
11058
  execSync2(`launchctl bootout gui/$(id -u)/${SERVICE_LABEL}`, { stdio: "ignore" });
10871
11059
  } catch {}
10872
11060
  if (existsSync12(p)) {
10873
- unlinkSync4(p);
11061
+ unlinkSync5(p);
10874
11062
  removed.push(p);
10875
11063
  }
10876
11064
  } else if (platform5 === "linux") {
@@ -10879,14 +11067,14 @@ function uninstallService() {
10879
11067
  execSync2(`systemctl --user disable --now ${SYSTEMD_UNIT}`, { stdio: "ignore" });
10880
11068
  } catch {}
10881
11069
  if (existsSync12(p)) {
10882
- unlinkSync4(p);
11070
+ unlinkSync5(p);
10883
11071
  removed.push(p);
10884
11072
  }
10885
11073
  }
10886
11074
  return { platform: platform5, removed };
10887
11075
  }
10888
11076
  function darwinPlistPath() {
10889
- return join8(homedir6(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
11077
+ return join9(homedir6(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
10890
11078
  }
10891
11079
  function installDarwin(args) {
10892
11080
  const plist = darwinPlistPath();
@@ -10931,7 +11119,7 @@ function installDarwin(args) {
10931
11119
  </dict>
10932
11120
  </plist>
10933
11121
  `;
10934
- writeFileSync9(plist, xml, { mode: 420 });
11122
+ writeFileSync10(plist, xml, { mode: 420 });
10935
11123
  return {
10936
11124
  platform: "darwin",
10937
11125
  unitPath: plist,
@@ -10939,7 +11127,7 @@ function installDarwin(args) {
10939
11127
  };
10940
11128
  }
10941
11129
  function linuxUnitPath() {
10942
- return join8(homedir6(), ".config", "systemd", "user", SYSTEMD_UNIT);
11130
+ return join9(homedir6(), ".config", "systemd", "user", SYSTEMD_UNIT);
10943
11131
  }
10944
11132
  function installLinux(args) {
10945
11133
  const unit = linuxUnitPath();
@@ -10968,7 +11156,7 @@ Environment=PATH=/usr/local/bin:/usr/bin:/bin
10968
11156
  [Install]
10969
11157
  WantedBy=default.target
10970
11158
  `;
10971
- writeFileSync9(unit, content, { mode: 420 });
11159
+ writeFileSync10(unit, content, { mode: 420 });
10972
11160
  return {
10973
11161
  platform: "linux",
10974
11162
  unitPath: unit,
@@ -10991,7 +11179,7 @@ function readInstalledUnit() {
10991
11179
  if (!existsSync12(path2))
10992
11180
  return { platform: platform5, path: null, content: null };
10993
11181
  try {
10994
- return { platform: platform5, path: path2, content: readFileSync9(path2, "utf8") };
11182
+ return { platform: platform5, path: path2, content: readFileSync10(path2, "utf8") };
10995
11183
  } catch {
10996
11184
  return { platform: platform5, path: path2, content: null };
10997
11185
  }
@@ -11319,7 +11507,7 @@ async function runStop(opts) {
11319
11507
  }
11320
11508
  var init_daemon = __esm(() => {
11321
11509
  init_run();
11322
- init_client4();
11510
+ init_client3();
11323
11511
  init_lock();
11324
11512
  init_paths2();
11325
11513
  });
@@ -11335,17 +11523,17 @@ import {
11335
11523
  copyFileSync,
11336
11524
  existsSync as existsSync13,
11337
11525
  mkdirSync as mkdirSync8,
11338
- readFileSync as readFileSync10,
11339
- writeFileSync as writeFileSync10
11526
+ readFileSync as readFileSync11,
11527
+ writeFileSync as writeFileSync11
11340
11528
  } from "node:fs";
11341
11529
  import { homedir as homedir7, platform as platform5 } from "node:os";
11342
- import { dirname as dirname6, join as join9, resolve } from "node:path";
11530
+ import { dirname as dirname6, join as join10, resolve } from "node:path";
11343
11531
  import { fileURLToPath } from "node:url";
11344
11532
  import { spawnSync as spawnSync3 } from "node:child_process";
11345
11533
  function readClaudeConfig() {
11346
11534
  if (!existsSync13(CLAUDE_CONFIG))
11347
11535
  return {};
11348
- const text = readFileSync10(CLAUDE_CONFIG, "utf-8").trim();
11536
+ const text = readFileSync11(CLAUDE_CONFIG, "utf-8").trim();
11349
11537
  if (!text)
11350
11538
  return {};
11351
11539
  try {
@@ -11357,10 +11545,10 @@ function readClaudeConfig() {
11357
11545
  function backupClaudeConfig() {
11358
11546
  if (!existsSync13(CLAUDE_CONFIG))
11359
11547
  return;
11360
- const backupDir = join9(dirname6(CLAUDE_CONFIG), ".claude", "backups");
11548
+ const backupDir = join10(dirname6(CLAUDE_CONFIG), ".claude", "backups");
11361
11549
  mkdirSync8(backupDir, { recursive: true });
11362
11550
  const ts = Date.now();
11363
- const dest = join9(backupDir, `.claude.json.pre-claudemesh.${ts}`);
11551
+ const dest = join10(backupDir, `.claude.json.pre-claudemesh.${ts}`);
11364
11552
  copyFileSync(CLAUDE_CONFIG, dest);
11365
11553
  }
11366
11554
  function patchMcpServer(entry) {
@@ -11398,7 +11586,7 @@ function removeMcpServer() {
11398
11586
  }
11399
11587
  function flushClaudeConfig(obj) {
11400
11588
  mkdirSync8(dirname6(CLAUDE_CONFIG), { recursive: true });
11401
- writeFileSync10(CLAUDE_CONFIG, JSON.stringify(obj, null, 2) + `
11589
+ writeFileSync11(CLAUDE_CONFIG, JSON.stringify(obj, null, 2) + `
11402
11590
  `, "utf-8");
11403
11591
  try {
11404
11592
  chmodSync4(CLAUDE_CONFIG, 384);
@@ -11420,7 +11608,7 @@ function resolveEntry() {
11420
11608
  function resolveBundledSkillsDir() {
11421
11609
  const here = fileURLToPath(import.meta.url);
11422
11610
  const pkgRoot = resolve(dirname6(here), "..", "..");
11423
- const skillsDir = join9(pkgRoot, "skills");
11611
+ const skillsDir = join10(pkgRoot, "skills");
11424
11612
  if (existsSync13(skillsDir))
11425
11613
  return skillsDir;
11426
11614
  return null;
@@ -11434,13 +11622,13 @@ function installSkills() {
11434
11622
  for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
11435
11623
  if (!entry.isDirectory())
11436
11624
  continue;
11437
- const srcDir = join9(src, entry.name);
11438
- const dstDir = join9(CLAUDE_SKILLS_ROOT, entry.name);
11625
+ const srcDir = join10(src, entry.name);
11626
+ const dstDir = join10(CLAUDE_SKILLS_ROOT, entry.name);
11439
11627
  mkdirSync8(dstDir, { recursive: true });
11440
11628
  for (const file of fs.readdirSync(srcDir, { withFileTypes: true })) {
11441
11629
  if (!file.isFile())
11442
11630
  continue;
11443
- copyFileSync(join9(srcDir, file.name), join9(dstDir, file.name));
11631
+ copyFileSync(join10(srcDir, file.name), join10(dstDir, file.name));
11444
11632
  }
11445
11633
  installed.push(entry.name);
11446
11634
  }
@@ -11455,7 +11643,7 @@ function uninstallSkills() {
11455
11643
  for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
11456
11644
  if (!entry.isDirectory())
11457
11645
  continue;
11458
- const dstDir = join9(CLAUDE_SKILLS_ROOT, entry.name);
11646
+ const dstDir = join10(CLAUDE_SKILLS_ROOT, entry.name);
11459
11647
  if (existsSync13(dstDir)) {
11460
11648
  try {
11461
11649
  fs.rmSync(dstDir, { recursive: true, force: true });
@@ -11483,7 +11671,7 @@ function entriesEqual(a, b) {
11483
11671
  function readClaudeSettings() {
11484
11672
  if (!existsSync13(CLAUDE_SETTINGS))
11485
11673
  return {};
11486
- const text = readFileSync10(CLAUDE_SETTINGS, "utf-8").trim();
11674
+ const text = readFileSync11(CLAUDE_SETTINGS, "utf-8").trim();
11487
11675
  if (!text)
11488
11676
  return {};
11489
11677
  try {
@@ -11494,7 +11682,7 @@ function readClaudeSettings() {
11494
11682
  }
11495
11683
  function writeClaudeSettings(obj) {
11496
11684
  mkdirSync8(dirname6(CLAUDE_SETTINGS), { recursive: true });
11497
- writeFileSync10(CLAUDE_SETTINGS, JSON.stringify(obj, null, 2) + `
11685
+ writeFileSync11(CLAUDE_SETTINGS, JSON.stringify(obj, null, 2) + `
11498
11686
  `, "utf-8");
11499
11687
  }
11500
11688
  function installAllowedTools() {
@@ -11644,7 +11832,7 @@ function runInstall(args = []) {
11644
11832
  const installed = installSkills();
11645
11833
  if (installed.length > 0) {
11646
11834
  render.ok(`Claude skill${installed.length === 1 ? "" : "s"} installed`, installed.join(", "));
11647
- render.info(dim(` ${join9(CLAUDE_SKILLS_ROOT, installed[0])}/SKILL.md`));
11835
+ render.info(dim(` ${join10(CLAUDE_SKILLS_ROOT, installed[0])}/SKILL.md`));
11648
11836
  }
11649
11837
  } catch (e) {
11650
11838
  render.warn(`skill install failed: ${e instanceof Error ? e.message : String(e)}`);
@@ -11781,9 +11969,9 @@ var init_install = __esm(() => {
11781
11969
  init_facade();
11782
11970
  init_render();
11783
11971
  init_styles();
11784
- CLAUDE_CONFIG = join9(homedir7(), ".claude.json");
11785
- CLAUDE_SETTINGS = join9(homedir7(), ".claude", "settings.json");
11786
- CLAUDE_SKILLS_ROOT = join9(homedir7(), ".claude", "skills");
11972
+ CLAUDE_CONFIG = join10(homedir7(), ".claude.json");
11973
+ CLAUDE_SETTINGS = join10(homedir7(), ".claude", "settings.json");
11974
+ CLAUDE_SKILLS_ROOT = join10(homedir7(), ".claude", "skills");
11787
11975
  CLAUDEMESH_TOOLS = [
11788
11976
  "mcp__claudemesh__cancel_scheduled",
11789
11977
  "mcp__claudemesh__check_messages",
@@ -11838,26 +12026,26 @@ var exports_uninstall = {};
11838
12026
  __export(exports_uninstall, {
11839
12027
  uninstall: () => uninstall
11840
12028
  });
11841
- import { readFileSync as readFileSync11, writeFileSync as writeFileSync11, existsSync as existsSync14, rmSync as rmSync2, readdirSync as readdirSync2 } from "node:fs";
11842
- import { join as join10, dirname as dirname7 } from "node:path";
12029
+ import { readFileSync as readFileSync12, writeFileSync as writeFileSync12, existsSync as existsSync14, rmSync as rmSync2, readdirSync as readdirSync2 } from "node:fs";
12030
+ import { join as join11, dirname as dirname7 } from "node:path";
11843
12031
  import { homedir as homedir8 } from "node:os";
11844
12032
  import { fileURLToPath as fileURLToPath2 } from "node:url";
11845
12033
  function bundledSkillsDir() {
11846
12034
  const here = fileURLToPath2(import.meta.url);
11847
- const pkgRoot = join10(dirname7(here), "..", "..");
11848
- const skillsDir = join10(pkgRoot, "skills");
12035
+ const pkgRoot = join11(dirname7(here), "..", "..");
12036
+ const skillsDir = join11(pkgRoot, "skills");
11849
12037
  return existsSync14(skillsDir) ? skillsDir : null;
11850
12038
  }
11851
12039
  async function uninstall() {
11852
12040
  let removed = 0;
11853
12041
  if (existsSync14(PATHS.CLAUDE_JSON)) {
11854
12042
  try {
11855
- const raw = readFileSync11(PATHS.CLAUDE_JSON, "utf-8");
12043
+ const raw = readFileSync12(PATHS.CLAUDE_JSON, "utf-8");
11856
12044
  const config = JSON.parse(raw);
11857
12045
  const servers = config.mcpServers;
11858
12046
  if (servers && "claudemesh" in servers) {
11859
12047
  delete servers.claudemesh;
11860
- writeFileSync11(PATHS.CLAUDE_JSON, JSON.stringify(config, null, 2) + `
12048
+ writeFileSync12(PATHS.CLAUDE_JSON, JSON.stringify(config, null, 2) + `
11861
12049
  `, "utf-8");
11862
12050
  render.ok("removed MCP server", dim("~/.claude.json"));
11863
12051
  removed++;
@@ -11866,7 +12054,7 @@ async function uninstall() {
11866
12054
  }
11867
12055
  if (existsSync14(PATHS.CLAUDE_SETTINGS)) {
11868
12056
  try {
11869
- const raw = readFileSync11(PATHS.CLAUDE_SETTINGS, "utf-8");
12057
+ const raw = readFileSync12(PATHS.CLAUDE_SETTINGS, "utf-8");
11870
12058
  const config = JSON.parse(raw);
11871
12059
  const hooks = config.hooks;
11872
12060
  if (hooks) {
@@ -11887,7 +12075,7 @@ async function uninstall() {
11887
12075
  }
11888
12076
  }
11889
12077
  if (removedHooks > 0) {
11890
- writeFileSync11(PATHS.CLAUDE_SETTINGS, JSON.stringify(config, null, 2) + `
12078
+ writeFileSync12(PATHS.CLAUDE_SETTINGS, JSON.stringify(config, null, 2) + `
11891
12079
  `, "utf-8");
11892
12080
  render.ok(`removed ${removedHooks} claudemesh hook${removedHooks === 1 ? "" : "s"}`, dim("settings.json"));
11893
12081
  removed++;
@@ -11902,7 +12090,7 @@ async function uninstall() {
11902
12090
  for (const entry of readdirSync2(src, { withFileTypes: true })) {
11903
12091
  if (!entry.isDirectory())
11904
12092
  continue;
11905
- const dst = join10(CLAUDE_SKILLS_ROOT2, entry.name);
12093
+ const dst = join11(CLAUDE_SKILLS_ROOT2, entry.name);
11906
12094
  if (existsSync14(dst)) {
11907
12095
  try {
11908
12096
  rmSync2(dst, { recursive: true, force: true });
@@ -11927,7 +12115,7 @@ var init_uninstall = __esm(() => {
11927
12115
  init_render();
11928
12116
  init_styles();
11929
12117
  init_exit_codes();
11930
- CLAUDE_SKILLS_ROOT2 = join10(homedir8(), ".claude", "skills");
12118
+ CLAUDE_SKILLS_ROOT2 = join11(homedir8(), ".claude", "skills");
11931
12119
  });
11932
12120
 
11933
12121
  // src/commands/doctor.ts
@@ -11935,9 +12123,9 @@ var exports_doctor = {};
11935
12123
  __export(exports_doctor, {
11936
12124
  runDoctor: () => runDoctor
11937
12125
  });
11938
- import { existsSync as existsSync15, readFileSync as readFileSync12, statSync as statSync2 } from "node:fs";
12126
+ import { existsSync as existsSync15, readFileSync as readFileSync13, statSync as statSync3 } from "node:fs";
11939
12127
  import { homedir as homedir9, platform as platform6 } from "node:os";
11940
- import { join as join11 } from "node:path";
12128
+ import { join as join12 } from "node:path";
11941
12129
  import { spawnSync as spawnSync4 } from "node:child_process";
11942
12130
  function checkNode() {
11943
12131
  const major = Number(process.versions.node.split(".")[0]);
@@ -11961,7 +12149,7 @@ function checkClaudeOnPath() {
11961
12149
  };
11962
12150
  }
11963
12151
  function checkMcpRegistered() {
11964
- const claudeConfig = join11(homedir9(), ".claude.json");
12152
+ const claudeConfig = join12(homedir9(), ".claude.json");
11965
12153
  if (!existsSync15(claudeConfig)) {
11966
12154
  return {
11967
12155
  name: "claudemesh MCP registered in ~/.claude.json",
@@ -11970,7 +12158,7 @@ function checkMcpRegistered() {
11970
12158
  };
11971
12159
  }
11972
12160
  try {
11973
- const cfg = JSON.parse(readFileSync12(claudeConfig, "utf-8"));
12161
+ const cfg = JSON.parse(readFileSync13(claudeConfig, "utf-8"));
11974
12162
  const registered = Boolean(cfg.mcpServers?.["claudemesh"]);
11975
12163
  return {
11976
12164
  name: "claudemesh MCP registered in ~/.claude.json",
@@ -11987,7 +12175,7 @@ function checkMcpRegistered() {
11987
12175
  }
11988
12176
  }
11989
12177
  function checkHooksRegistered() {
11990
- const settings = join11(homedir9(), ".claude", "settings.json");
12178
+ const settings = join12(homedir9(), ".claude", "settings.json");
11991
12179
  if (!existsSync15(settings)) {
11992
12180
  return {
11993
12181
  name: "Status hooks registered in ~/.claude/settings.json",
@@ -11996,7 +12184,7 @@ function checkHooksRegistered() {
11996
12184
  };
11997
12185
  }
11998
12186
  try {
11999
- const raw = readFileSync12(settings, "utf-8");
12187
+ const raw = readFileSync13(settings, "utf-8");
12000
12188
  const has = raw.includes("claudemesh hook ");
12001
12189
  return {
12002
12190
  name: "Status hooks registered in ~/.claude/settings.json",
@@ -12022,7 +12210,7 @@ function checkConfigFile() {
12022
12210
  }
12023
12211
  try {
12024
12212
  readConfig();
12025
- const st = statSync2(path2);
12213
+ const st = statSync3(path2);
12026
12214
  const mode = (st.mode & 511).toString(8);
12027
12215
  const secure = platform6() === "win32" || mode === "600";
12028
12216
  return {
@@ -12196,7 +12384,7 @@ var exports_status = {};
12196
12384
  __export(exports_status, {
12197
12385
  runStatus: () => runStatus2
12198
12386
  });
12199
- import { statSync as statSync3, existsSync as existsSync16 } from "node:fs";
12387
+ import { statSync as statSync4, existsSync as existsSync16 } from "node:fs";
12200
12388
  import WebSocket3 from "ws";
12201
12389
  async function probeBroker(url, timeoutMs = 4000) {
12202
12390
  return new Promise((resolve2) => {
@@ -12227,7 +12415,7 @@ async function runStatus2() {
12227
12415
  const configPath = getConfigPath();
12228
12416
  let configPermsNote = "missing";
12229
12417
  if (existsSync16(configPath)) {
12230
- const mode = (statSync3(configPath).mode & 511).toString(8).padStart(4, "0");
12418
+ const mode = (statSync4(configPath).mode & 511).toString(8).padStart(4, "0");
12231
12419
  configPermsNote = mode === "0600" ? `${mode}` : `${mode} — expected 0600`;
12232
12420
  }
12233
12421
  render.kv([["config", configPath], ["perms", configPermsNote]]);
@@ -12372,13 +12560,13 @@ var init_check_claude_binary = __esm(() => {
12372
12560
  });
12373
12561
 
12374
12562
  // src/services/health/check-mcp-registered.ts
12375
- import { existsSync as existsSync17, readFileSync as readFileSync13 } from "node:fs";
12563
+ import { existsSync as existsSync17, readFileSync as readFileSync14 } from "node:fs";
12376
12564
  function checkMcpRegistered2() {
12377
12565
  try {
12378
12566
  if (!existsSync17(PATHS.CLAUDE_JSON)) {
12379
12567
  return { name: "mcp-registered", ok: false, message: "~/.claude.json not found" };
12380
12568
  }
12381
- const raw = readFileSync13(PATHS.CLAUDE_JSON, "utf-8");
12569
+ const raw = readFileSync14(PATHS.CLAUDE_JSON, "utf-8");
12382
12570
  const config = JSON.parse(raw);
12383
12571
  if (config.mcpServers && "claudemesh" in config.mcpServers) {
12384
12572
  return { name: "mcp-registered", ok: true, message: "MCP server registered" };
@@ -12393,13 +12581,13 @@ var init_check_mcp_registered = __esm(() => {
12393
12581
  });
12394
12582
 
12395
12583
  // src/services/health/check-hooks-registered.ts
12396
- import { existsSync as existsSync18, readFileSync as readFileSync14 } from "node:fs";
12584
+ import { existsSync as existsSync18, readFileSync as readFileSync15 } from "node:fs";
12397
12585
  function checkHooksRegistered2() {
12398
12586
  try {
12399
12587
  if (!existsSync18(PATHS.CLAUDE_SETTINGS)) {
12400
12588
  return { name: "hooks-registered", ok: false, message: "~/.claude/settings.json not found" };
12401
12589
  }
12402
- const raw = readFileSync14(PATHS.CLAUDE_SETTINGS, "utf-8");
12590
+ const raw = readFileSync15(PATHS.CLAUDE_SETTINGS, "utf-8");
12403
12591
  const config = JSON.parse(raw);
12404
12592
  if (config.hooks) {
12405
12593
  return { name: "hooks-registered", ok: true, message: "Hooks configured" };
@@ -12414,14 +12602,14 @@ var init_check_hooks_registered = __esm(() => {
12414
12602
  });
12415
12603
 
12416
12604
  // src/services/health/check-config-perms.ts
12417
- import { existsSync as existsSync19, statSync as statSync4 } from "node:fs";
12605
+ import { existsSync as existsSync19, statSync as statSync5 } from "node:fs";
12418
12606
  function checkConfigPerms() {
12419
12607
  const configFile = PATHS.CONFIG_FILE;
12420
12608
  if (!existsSync19(configFile)) {
12421
12609
  return { name: "config-perms", ok: true, message: "No config file yet (first run)" };
12422
12610
  }
12423
12611
  try {
12424
- const mode = statSync4(configFile).mode & 511;
12612
+ const mode = statSync5(configFile).mode & 511;
12425
12613
  if (mode <= 384) {
12426
12614
  return { name: "config-perms", ok: true, message: `config.json mode ${mode.toString(8)}` };
12427
12615
  }
@@ -12435,13 +12623,13 @@ var init_check_config_perms = __esm(() => {
12435
12623
  });
12436
12624
 
12437
12625
  // src/services/health/check-keypairs-valid.ts
12438
- import { existsSync as existsSync20, readFileSync as readFileSync15 } from "node:fs";
12626
+ import { existsSync as existsSync20, readFileSync as readFileSync16 } from "node:fs";
12439
12627
  function checkKeypairsValid() {
12440
12628
  if (!existsSync20(PATHS.CONFIG_FILE)) {
12441
12629
  return { name: "keypairs-valid", ok: true, message: "No config (first run)" };
12442
12630
  }
12443
12631
  try {
12444
- const raw = readFileSync15(PATHS.CONFIG_FILE, "utf-8");
12632
+ const raw = readFileSync16(PATHS.CONFIG_FILE, "utf-8");
12445
12633
  const config = JSON.parse(raw);
12446
12634
  const meshes = config.meshes ?? [];
12447
12635
  if (meshes.length === 0) {
@@ -12922,17 +13110,17 @@ __export(exports_url_handler, {
12922
13110
  runUrlHandler: () => runUrlHandler
12923
13111
  });
12924
13112
  import { platform as platform7, homedir as homedir10 } from "node:os";
12925
- import { existsSync as existsSync21, mkdirSync as mkdirSync9, writeFileSync as writeFileSync12, rmSync as rmSync3, chmodSync as chmodSync5 } from "node:fs";
12926
- import { join as join12 } from "node:path";
13113
+ import { existsSync as existsSync21, mkdirSync as mkdirSync9, writeFileSync as writeFileSync13, rmSync as rmSync3, chmodSync as chmodSync5 } from "node:fs";
13114
+ import { join as join13 } from "node:path";
12927
13115
  import { spawnSync as spawnSync5 } from "node:child_process";
12928
13116
  function resolveClaudemeshBin() {
12929
13117
  return process.argv[1] ?? "claudemesh";
12930
13118
  }
12931
13119
  function installDarwin2() {
12932
13120
  const binPath = resolveClaudemeshBin();
12933
- const appDir = join12(homedir10(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
12934
- const contents = join12(appDir, "Contents");
12935
- const macOS = join12(contents, "MacOS");
13121
+ const appDir = join13(homedir10(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
13122
+ const contents = join13(appDir, "Contents");
13123
+ const macOS = join13(contents, "MacOS");
12936
13124
  mkdirSync9(macOS, { recursive: true });
12937
13125
  const plist = `<?xml version="1.0" encoding="UTF-8"?>
12938
13126
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@@ -12956,7 +13144,7 @@ function installDarwin2() {
12956
13144
  </array>
12957
13145
  </dict>
12958
13146
  </plist>`;
12959
- writeFileSync12(join12(contents, "Info.plist"), plist);
13147
+ writeFileSync13(join13(contents, "Info.plist"), plist);
12960
13148
  const shim = `#!/bin/sh
12961
13149
  URL="$1"
12962
13150
  CODE=\${URL#claudemesh://}
@@ -12970,8 +13158,8 @@ tell application "Terminal"
12970
13158
  end tell
12971
13159
  EOF
12972
13160
  `;
12973
- const shimPath = join12(macOS, "open-url");
12974
- writeFileSync12(shimPath, shim);
13161
+ const shimPath = join13(macOS, "open-url");
13162
+ writeFileSync13(shimPath, shim);
12975
13163
  chmodSync5(shimPath, 493);
12976
13164
  const lsreg = spawnSync5("/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister", ["-f", appDir], { encoding: "utf-8" });
12977
13165
  if (lsreg.status !== 0) {
@@ -12982,7 +13170,7 @@ EOF
12982
13170
  }
12983
13171
  function installLinux2() {
12984
13172
  const binPath = resolveClaudemeshBin();
12985
- const appsDir = join12(homedir10(), ".local", "share", "applications");
13173
+ const appsDir = join13(homedir10(), ".local", "share", "applications");
12986
13174
  mkdirSync9(appsDir, { recursive: true });
12987
13175
  const desktop = `[Desktop Entry]
12988
13176
  Type=Application
@@ -12994,8 +13182,8 @@ Terminal=true
12994
13182
  MimeType=x-scheme-handler/claudemesh;
12995
13183
  NoDisplay=true
12996
13184
  `;
12997
- const desktopPath = join12(appsDir, "claudemesh.desktop");
12998
- writeFileSync12(desktopPath, desktop);
13185
+ const desktopPath = join13(appsDir, "claudemesh.desktop");
13186
+ writeFileSync13(desktopPath, desktop);
12999
13187
  const xdg1 = spawnSync5("xdg-mime", ["default", "claudemesh.desktop", "x-scheme-handler/claudemesh"], { encoding: "utf-8" });
13000
13188
  if (xdg1.status !== 0) {
13001
13189
  render.warn("xdg-mime not available — skipped mime default registration");
@@ -13017,8 +13205,8 @@ function installWindows() {
13017
13205
  `[HKEY_CURRENT_USER\\Software\\Classes\\claudemesh\\shell\\open\\command]`,
13018
13206
  `@="\\"${binPath.replace(/\\/g, "\\\\")}\\" \\"%1\\""`
13019
13207
  ];
13020
- const regPath = join12(homedir10(), "claudemesh-handler.reg");
13021
- writeFileSync12(regPath, lines.join(`\r
13208
+ const regPath = join13(homedir10(), "claudemesh-handler.reg");
13209
+ writeFileSync13(regPath, lines.join(`\r
13022
13210
  `));
13023
13211
  const res = spawnSync5("reg.exe", ["import", regPath], { encoding: "utf-8" });
13024
13212
  if (res.status !== 0) {
@@ -13029,14 +13217,14 @@ function installWindows() {
13029
13217
  return EXIT.SUCCESS;
13030
13218
  }
13031
13219
  function uninstallDarwin() {
13032
- const appDir = join12(homedir10(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
13220
+ const appDir = join13(homedir10(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
13033
13221
  if (existsSync21(appDir))
13034
13222
  rmSync3(appDir, { recursive: true, force: true });
13035
13223
  render.ok("removed claudemesh:// handler on macOS");
13036
13224
  return EXIT.SUCCESS;
13037
13225
  }
13038
13226
  function uninstallLinux() {
13039
- const desktopPath = join12(homedir10(), ".local", "share", "applications", "claudemesh.desktop");
13227
+ const desktopPath = join13(homedir10(), ".local", "share", "applications", "claudemesh.desktop");
13040
13228
  if (existsSync21(desktopPath))
13041
13229
  rmSync3(desktopPath, { force: true });
13042
13230
  render.ok("removed claudemesh:// handler on Linux");
@@ -13082,8 +13270,8 @@ var exports_status_line = {};
13082
13270
  __export(exports_status_line, {
13083
13271
  runStatusLine: () => runStatusLine
13084
13272
  });
13085
- import { existsSync as existsSync22, readFileSync as readFileSync16 } from "node:fs";
13086
- import { join as join13 } from "node:path";
13273
+ import { existsSync as existsSync22, readFileSync as readFileSync17 } from "node:fs";
13274
+ import { join as join14 } from "node:path";
13087
13275
  import { homedir as homedir11 } from "node:os";
13088
13276
  async function runStatusLine() {
13089
13277
  try {
@@ -13092,11 +13280,11 @@ async function runStatusLine() {
13092
13280
  process.stdout.write("◇ claudemesh (not joined)");
13093
13281
  return EXIT.SUCCESS;
13094
13282
  }
13095
- const cachePath = join13(homedir11(), ".claudemesh", "peer-cache.json");
13283
+ const cachePath = join14(homedir11(), ".claudemesh", "peer-cache.json");
13096
13284
  let cache = {};
13097
13285
  if (existsSync22(cachePath)) {
13098
13286
  try {
13099
- cache = JSON.parse(readFileSync16(cachePath, "utf-8"));
13287
+ cache = JSON.parse(readFileSync17(cachePath, "utf-8"));
13100
13288
  } catch {}
13101
13289
  }
13102
13290
  const pick = config.meshes[0];
@@ -13127,7 +13315,7 @@ __export(exports_backup, {
13127
13315
  runRestore: () => runRestore,
13128
13316
  runBackup: () => runBackup
13129
13317
  });
13130
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync13, existsSync as existsSync23 } from "node:fs";
13318
+ import { readFileSync as readFileSync18, writeFileSync as writeFileSync14, existsSync as existsSync23 } from "node:fs";
13131
13319
  import { createInterface as createInterface11 } from "node:readline";
13132
13320
  function readHidden(prompt5) {
13133
13321
  return new Promise((resolve2) => {
@@ -13173,7 +13361,7 @@ async function runBackup(outPath) {
13173
13361
  console.error(" No config found — nothing to back up. Join a mesh first.");
13174
13362
  return EXIT.NOT_FOUND;
13175
13363
  }
13176
- const plaintext = readFileSync17(configPath);
13364
+ const plaintext = readFileSync18(configPath);
13177
13365
  const pass = await readHidden(" Passphrase (min 12 chars): ");
13178
13366
  if (pass.length < 12) {
13179
13367
  console.error(" ✗ Passphrase too short.");
@@ -13191,7 +13379,7 @@ async function runBackup(outPath) {
13191
13379
  const ciphertext = Buffer.from(s.crypto_aead_xchacha20poly1305_ietf_encrypt(plaintext, null, null, nonce, key));
13192
13380
  const blob = Buffer.concat([MAGIC, salt, nonce, ciphertext]);
13193
13381
  const file = outPath ?? `claudemesh-backup-${new Date().toISOString().replace(/[:.]/g, "-")}.cmb`;
13194
- writeFileSync13(file, blob, { mode: 384 });
13382
+ writeFileSync14(file, blob, { mode: 384 });
13195
13383
  console.log(`
13196
13384
  ✓ Backup saved: ${file}`);
13197
13385
  console.log(` Size: ${blob.length} bytes. Guard the passphrase — there is no recovery.
@@ -13207,7 +13395,7 @@ async function runRestore(inPath) {
13207
13395
  console.error(` ✗ File not found: ${inPath}`);
13208
13396
  return EXIT.NOT_FOUND;
13209
13397
  }
13210
- const blob = readFileSync17(inPath);
13398
+ const blob = readFileSync18(inPath);
13211
13399
  if (blob.length < 4 + 16 + 24 + 17 || !blob.subarray(0, 4).equals(MAGIC)) {
13212
13400
  console.error(" ✗ Not a claudemesh backup file (bad magic).");
13213
13401
  return EXIT.INVALID_ARGS;
@@ -13228,10 +13416,10 @@ async function runRestore(inPath) {
13228
13416
  const configPath = getConfigPath();
13229
13417
  if (existsSync23(configPath)) {
13230
13418
  const backupOld = `${configPath}.before-restore.${Date.now()}`;
13231
- writeFileSync13(backupOld, readFileSync17(configPath), { mode: 384 });
13419
+ writeFileSync14(backupOld, readFileSync18(configPath), { mode: 384 });
13232
13420
  console.log(` ↻ Existing config saved to ${backupOld}`);
13233
13421
  }
13234
- writeFileSync13(configPath, Buffer.from(plaintext), { mode: 384 });
13422
+ writeFileSync14(configPath, Buffer.from(plaintext), { mode: 384 });
13235
13423
  console.log(`
13236
13424
  ✓ Config restored to ${configPath}`);
13237
13425
  console.log(" Run `claudemesh list` to verify your meshes.\n");
@@ -13252,7 +13440,7 @@ __export(exports_upgrade, {
13252
13440
  });
13253
13441
  import { spawnSync as spawnSync6 } from "node:child_process";
13254
13442
  import { existsSync as existsSync24 } from "node:fs";
13255
- import { dirname as dirname8, join as join14, resolve as resolve2 } from "node:path";
13443
+ import { dirname as dirname8, join as join15, resolve as resolve2 } from "node:path";
13256
13444
  async function latestVersion() {
13257
13445
  try {
13258
13446
  const res = await fetch(URLS.NPM_REGISTRY, { signal: AbortSignal.timeout(8000) });
@@ -13265,14 +13453,14 @@ async function latestVersion() {
13265
13453
  }
13266
13454
  }
13267
13455
  function findNpm() {
13268
- const portable = join14(process.env.HOME ?? "", ".claudemesh", "node", "bin", "npm");
13456
+ const portable = join15(process.env.HOME ?? "", ".claudemesh", "node", "bin", "npm");
13269
13457
  if (existsSync24(portable)) {
13270
- return { npm: portable, prefix: join14(process.env.HOME ?? "", ".claudemesh") };
13458
+ return { npm: portable, prefix: join15(process.env.HOME ?? "", ".claudemesh") };
13271
13459
  }
13272
13460
  let cur = resolve2(process.argv[1] ?? ".");
13273
13461
  for (let i = 0;i < 6; i++) {
13274
13462
  cur = dirname8(cur);
13275
- const candidate = join14(cur, "bin", "npm");
13463
+ const candidate = join15(cur, "bin", "npm");
13276
13464
  if (existsSync24(candidate))
13277
13465
  return { npm: candidate };
13278
13466
  }
@@ -13335,9 +13523,9 @@ __export(exports_grants, {
13335
13523
  runBlock: () => runBlock,
13336
13524
  isAllowed: () => isAllowed
13337
13525
  });
13338
- import { existsSync as existsSync25, mkdirSync as mkdirSync10, readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "node:fs";
13526
+ import { existsSync as existsSync25, mkdirSync as mkdirSync10, readFileSync as readFileSync19, writeFileSync as writeFileSync15 } from "node:fs";
13339
13527
  import { homedir as homedir12 } from "node:os";
13340
- import { join as join15 } from "node:path";
13528
+ import { join as join16 } from "node:path";
13341
13529
  async function syncToBroker(meshSlug, grants) {
13342
13530
  const auth = getStoredToken();
13343
13531
  if (!auth)
@@ -13358,16 +13546,16 @@ function readGrants() {
13358
13546
  if (!existsSync25(GRANT_FILE))
13359
13547
  return {};
13360
13548
  try {
13361
- return JSON.parse(readFileSync18(GRANT_FILE, "utf-8"));
13549
+ return JSON.parse(readFileSync19(GRANT_FILE, "utf-8"));
13362
13550
  } catch {
13363
13551
  return {};
13364
13552
  }
13365
13553
  }
13366
13554
  function writeGrants(g) {
13367
- const dir = join15(homedir12(), ".claudemesh");
13555
+ const dir = join16(homedir12(), ".claudemesh");
13368
13556
  if (!existsSync25(dir))
13369
13557
  mkdirSync10(dir, { recursive: true });
13370
- writeFileSync14(GRANT_FILE, JSON.stringify(g, null, 2), { mode: 384 });
13558
+ writeFileSync15(GRANT_FILE, JSON.stringify(g, null, 2), { mode: 384 });
13371
13559
  }
13372
13560
  function resolveCaps(input) {
13373
13561
  if (input.includes("all"))
@@ -13523,7 +13711,7 @@ var init_grants = __esm(() => {
13523
13711
  BROKER_HTTP7 = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
13524
13712
  ALL_CAPS = ["read", "dm", "broadcast", "state-read", "state-write", "file-read"];
13525
13713
  DEFAULT_CAPS = ["read", "dm", "broadcast", "state-read"];
13526
- GRANT_FILE = join15(homedir12(), ".claudemesh", "grants.json");
13714
+ GRANT_FILE = join16(homedir12(), ".claudemesh", "grants.json");
13527
13715
  });
13528
13716
 
13529
13717
  // src/commands/profile.ts
@@ -15205,7 +15393,7 @@ __export(exports_file, {
15205
15393
  });
15206
15394
  import { hostname as osHostname } from "node:os";
15207
15395
  import { resolve as resolvePath, basename, dirname as dirname9 } from "node:path";
15208
- import { statSync as statSync6, existsSync as existsSync26, writeFileSync as writeFileSync15, mkdirSync as mkdirSync11 } from "node:fs";
15396
+ import { statSync as statSync7, existsSync as existsSync26, writeFileSync as writeFileSync16, mkdirSync as mkdirSync11 } from "node:fs";
15209
15397
  function emitJson2(data) {
15210
15398
  console.log(JSON.stringify(data, null, 2));
15211
15399
  }
@@ -15226,7 +15414,7 @@ async function runFileShare(filePath, opts) {
15226
15414
  render.err(`File not found: ${absPath}`);
15227
15415
  return EXIT.INVALID_ARGS;
15228
15416
  }
15229
- const stat = statSync6(absPath);
15417
+ const stat = statSync7(absPath);
15230
15418
  if (!stat.isFile()) {
15231
15419
  render.err(`Not a regular file: ${absPath}`);
15232
15420
  return EXIT.INVALID_ARGS;
@@ -15302,7 +15490,7 @@ async function runFileGet(fileId, opts) {
15302
15490
  const buf = Buffer.from(await res.arrayBuffer());
15303
15491
  const outPath = opts.out ? resolvePath(opts.out) : resolvePath(process.cwd(), meta.name);
15304
15492
  mkdirSync11(dirname9(outPath), { recursive: true });
15305
- writeFileSync15(outPath, buf);
15493
+ writeFileSync16(outPath, buf);
15306
15494
  if (opts.json) {
15307
15495
  emitJson2({ fileId, name: meta.name, savedTo: outPath, sizeBytes: buf.length });
15308
15496
  } else {
@@ -15912,7 +16100,7 @@ __export(exports_bridge, {
15912
16100
  runBridge: () => runBridge,
15913
16101
  bridgeConfigTemplate: () => bridgeConfigTemplate
15914
16102
  });
15915
- import { readFileSync as readFileSync19, existsSync as existsSync27 } from "node:fs";
16103
+ import { readFileSync as readFileSync20, existsSync as existsSync27 } from "node:fs";
15916
16104
  function parseConfig(text) {
15917
16105
  const trimmed = text.trim();
15918
16106
  if (trimmed.startsWith("{"))
@@ -15962,7 +16150,7 @@ async function runBridge(configPath) {
15962
16150
  }
15963
16151
  let cfg;
15964
16152
  try {
15965
- cfg = parseConfig(readFileSync19(configPath, "utf-8"));
16153
+ cfg = parseConfig(readFileSync20(configPath, "utf-8"));
15966
16154
  } catch (e) {
15967
16155
  render.err(`failed to parse ${configPath}: ${e instanceof Error ? e.message : String(e)}`);
15968
16156
  return EXIT.INVALID_ARGS;
@@ -19238,4 +19426,4 @@ main().catch((err) => {
19238
19426
  process.exit(EXIT.INTERNAL_ERROR);
19239
19427
  });
19240
19428
 
19241
- //# debugId=856EC7628E8E9AE364756E2164756E21
19429
+ //# debugId=1F2A51E3A3AE432A64756E2164756E21