claudemesh-cli 1.27.2 → 1.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entrypoints/cli.js +532 -481
- package/dist/entrypoints/cli.js.map +15 -14
- package/dist/entrypoints/mcp.js +2 -8
- package/dist/entrypoints/mcp.js.map +2 -2
- package/package.json +1 -1
package/dist/entrypoints/cli.js
CHANGED
|
@@ -103,7 +103,7 @@ __export(exports_urls, {
|
|
|
103
103
|
VERSION: () => VERSION,
|
|
104
104
|
URLS: () => URLS
|
|
105
105
|
});
|
|
106
|
-
var URLS, VERSION = "1.
|
|
106
|
+
var URLS, VERSION = "1.28.0", env;
|
|
107
107
|
var init_urls = __esm(() => {
|
|
108
108
|
URLS = {
|
|
109
109
|
BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
|
|
@@ -150,6 +150,32 @@ function normaliseInviteUrl(input, host = "claudemesh.com") {
|
|
|
150
150
|
return trimmed;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
// src/services/daemon/policy.ts
|
|
154
|
+
function readEnvDefault() {
|
|
155
|
+
if (process.env.CLAUDEMESH_NO_DAEMON === "1")
|
|
156
|
+
return { mode: "no-daemon" };
|
|
157
|
+
if (process.env.CLAUDEMESH_STRICT_DAEMON === "1")
|
|
158
|
+
return { mode: "strict" };
|
|
159
|
+
return { mode: "auto" };
|
|
160
|
+
}
|
|
161
|
+
function setDaemonPolicy(mode) {
|
|
162
|
+
policy = { mode };
|
|
163
|
+
}
|
|
164
|
+
function getDaemonPolicy() {
|
|
165
|
+
return policy;
|
|
166
|
+
}
|
|
167
|
+
function policyFromFlags(flags) {
|
|
168
|
+
if (flags["no-daemon"])
|
|
169
|
+
return "no-daemon";
|
|
170
|
+
if (flags.strict)
|
|
171
|
+
return "strict";
|
|
172
|
+
return readEnvDefault().mode;
|
|
173
|
+
}
|
|
174
|
+
var policy;
|
|
175
|
+
var init_policy = __esm(() => {
|
|
176
|
+
policy = readEnvDefault();
|
|
177
|
+
});
|
|
178
|
+
|
|
153
179
|
// src/constants/paths.ts
|
|
154
180
|
import { homedir as homedir2 } from "node:os";
|
|
155
181
|
import { join as join2 } from "node:path";
|
|
@@ -3588,12 +3614,6 @@ var init_spinner = __esm(() => {
|
|
|
3588
3614
|
});
|
|
3589
3615
|
|
|
3590
3616
|
// 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
3617
|
import { join as join3 } from "node:path";
|
|
3598
3618
|
var DAEMON_PATHS, DAEMON_TCP_HOST = "127.0.0.1", DAEMON_TCP_DEFAULT_PORT = 47823;
|
|
3599
3619
|
var init_paths2 = __esm(() => {
|
|
@@ -3623,6 +3643,255 @@ var init_paths2 = __esm(() => {
|
|
|
3623
3643
|
};
|
|
3624
3644
|
});
|
|
3625
3645
|
|
|
3646
|
+
// src/daemon/local-token.ts
|
|
3647
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
3648
|
+
import { dirname as dirname2 } from "node:path";
|
|
3649
|
+
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
3650
|
+
function readLocalToken() {
|
|
3651
|
+
try {
|
|
3652
|
+
return readFileSync4(DAEMON_PATHS.TOKEN_FILE, "utf8").trim();
|
|
3653
|
+
} catch {
|
|
3654
|
+
return null;
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3657
|
+
function ensureLocalToken() {
|
|
3658
|
+
const existing = readLocalToken();
|
|
3659
|
+
if (existing)
|
|
3660
|
+
return existing;
|
|
3661
|
+
mkdirSync3(dirname2(DAEMON_PATHS.TOKEN_FILE), { recursive: true, mode: 448 });
|
|
3662
|
+
const tok = randomBytes4(32).toString("base64url");
|
|
3663
|
+
writeFileSync4(DAEMON_PATHS.TOKEN_FILE, tok + `
|
|
3664
|
+
`, { mode: 384 });
|
|
3665
|
+
return tok;
|
|
3666
|
+
}
|
|
3667
|
+
var init_local_token = __esm(() => {
|
|
3668
|
+
init_paths2();
|
|
3669
|
+
});
|
|
3670
|
+
|
|
3671
|
+
// src/daemon/ipc/client.ts
|
|
3672
|
+
import { request as httpRequest } from "node:http";
|
|
3673
|
+
async function ipc(opts) {
|
|
3674
|
+
const useTcp = !!opts.preferTcp;
|
|
3675
|
+
const headers = {
|
|
3676
|
+
accept: "application/json",
|
|
3677
|
+
host: "localhost"
|
|
3678
|
+
};
|
|
3679
|
+
let bodyBuf;
|
|
3680
|
+
if (opts.body !== undefined) {
|
|
3681
|
+
bodyBuf = Buffer.from(JSON.stringify(opts.body), "utf8");
|
|
3682
|
+
headers["content-type"] = "application/json";
|
|
3683
|
+
headers["content-length"] = String(bodyBuf.length);
|
|
3684
|
+
}
|
|
3685
|
+
if (useTcp) {
|
|
3686
|
+
const tok = readLocalToken();
|
|
3687
|
+
if (!tok)
|
|
3688
|
+
throw new IpcError(0, null, "daemon local token not found; is the daemon running?");
|
|
3689
|
+
headers.authorization = `Bearer ${tok}`;
|
|
3690
|
+
}
|
|
3691
|
+
return new Promise((resolve, reject) => {
|
|
3692
|
+
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) => {
|
|
3693
|
+
const chunks = [];
|
|
3694
|
+
res.on("data", (c) => chunks.push(c));
|
|
3695
|
+
res.on("end", () => {
|
|
3696
|
+
const raw = Buffer.concat(chunks).toString("utf8");
|
|
3697
|
+
let parsed = raw;
|
|
3698
|
+
try {
|
|
3699
|
+
parsed = raw.length > 0 ? JSON.parse(raw) : null;
|
|
3700
|
+
} catch {}
|
|
3701
|
+
resolve({ status: res.statusCode ?? 0, body: parsed });
|
|
3702
|
+
});
|
|
3703
|
+
});
|
|
3704
|
+
req.setTimeout(opts.timeoutMs ?? 5000, () => req.destroy(new Error("ipc_timeout")));
|
|
3705
|
+
req.on("error", (err) => reject(err));
|
|
3706
|
+
if (bodyBuf)
|
|
3707
|
+
req.write(bodyBuf);
|
|
3708
|
+
req.end();
|
|
3709
|
+
});
|
|
3710
|
+
}
|
|
3711
|
+
var IpcError;
|
|
3712
|
+
var init_client3 = __esm(() => {
|
|
3713
|
+
init_paths2();
|
|
3714
|
+
init_local_token();
|
|
3715
|
+
IpcError = class IpcError extends Error {
|
|
3716
|
+
status;
|
|
3717
|
+
payload;
|
|
3718
|
+
constructor(status, payload, msg) {
|
|
3719
|
+
super(msg);
|
|
3720
|
+
this.status = status;
|
|
3721
|
+
this.payload = payload;
|
|
3722
|
+
}
|
|
3723
|
+
};
|
|
3724
|
+
});
|
|
3725
|
+
|
|
3726
|
+
// src/services/daemon/lifecycle.ts
|
|
3727
|
+
var exports_lifecycle = {};
|
|
3728
|
+
__export(exports_lifecycle, {
|
|
3729
|
+
ensureDaemonReady: () => ensureDaemonReady,
|
|
3730
|
+
_resetDaemonReadyCache: () => _resetDaemonReadyCache
|
|
3731
|
+
});
|
|
3732
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, statSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
3733
|
+
import { join as join4 } from "node:path";
|
|
3734
|
+
async function ensureDaemonReady(opts = {}) {
|
|
3735
|
+
if (lastResultThisProcess && (lastResultThisProcess.state === "up" || lastResultThisProcess.state === "started")) {
|
|
3736
|
+
return lastResultThisProcess;
|
|
3737
|
+
}
|
|
3738
|
+
if (process.env.CLAUDEMESH_INTERNAL_NO_AUTOSPAWN === "1") {
|
|
3739
|
+
opts = { ...opts, noAutoSpawn: true };
|
|
3740
|
+
}
|
|
3741
|
+
const result = await runEnsureDaemon(opts);
|
|
3742
|
+
lastResultThisProcess = result;
|
|
3743
|
+
return result;
|
|
3744
|
+
}
|
|
3745
|
+
function _resetDaemonReadyCache() {
|
|
3746
|
+
lastResultThisProcess = null;
|
|
3747
|
+
}
|
|
3748
|
+
async function runEnsureDaemon(opts) {
|
|
3749
|
+
const t0 = Date.now();
|
|
3750
|
+
const probe = await probeDaemon();
|
|
3751
|
+
if (probe === "up")
|
|
3752
|
+
return { state: "up", durationMs: Date.now() - t0 };
|
|
3753
|
+
if (probe === "stale")
|
|
3754
|
+
cleanupStaleFiles();
|
|
3755
|
+
if (opts.noAutoSpawn) {
|
|
3756
|
+
return { state: "down", durationMs: Date.now() - t0, reason: "auto-spawn disabled" };
|
|
3757
|
+
}
|
|
3758
|
+
if (recentSpawnFailureFresh()) {
|
|
3759
|
+
return {
|
|
3760
|
+
state: "spawn-suppressed",
|
|
3761
|
+
durationMs: Date.now() - t0,
|
|
3762
|
+
reason: `daemon failed to start within last ${Math.round(SPAWN_FAIL_TTL_MS / 1000)}s`
|
|
3763
|
+
};
|
|
3764
|
+
}
|
|
3765
|
+
const spawnRes = await spawnDaemon(opts);
|
|
3766
|
+
if (spawnRes.ok) {
|
|
3767
|
+
return { state: "started", durationMs: Date.now() - t0 };
|
|
3768
|
+
}
|
|
3769
|
+
markSpawnFailure();
|
|
3770
|
+
return { state: "spawn-failed", durationMs: Date.now() - t0, reason: spawnRes.reason };
|
|
3771
|
+
}
|
|
3772
|
+
async function probeDaemon() {
|
|
3773
|
+
if (!existsSync5(DAEMON_PATHS.SOCK_FILE))
|
|
3774
|
+
return "absent";
|
|
3775
|
+
try {
|
|
3776
|
+
const res = await ipc({ path: "/v1/version", timeoutMs: PROBE_TIMEOUT_MS });
|
|
3777
|
+
if (res.status === 200)
|
|
3778
|
+
return "up";
|
|
3779
|
+
return "stale";
|
|
3780
|
+
} catch (err) {
|
|
3781
|
+
if (err instanceof IpcError)
|
|
3782
|
+
return "stale";
|
|
3783
|
+
const msg = String(err);
|
|
3784
|
+
if (/ENOENT|ECONNREFUSED|ipc_timeout|EPIPE|ECONNRESET/.test(msg))
|
|
3785
|
+
return "stale";
|
|
3786
|
+
return "stale";
|
|
3787
|
+
}
|
|
3788
|
+
}
|
|
3789
|
+
function cleanupStaleFiles() {
|
|
3790
|
+
for (const p of [DAEMON_PATHS.SOCK_FILE, DAEMON_PATHS.PID_FILE]) {
|
|
3791
|
+
try {
|
|
3792
|
+
unlinkSync2(p);
|
|
3793
|
+
} catch {}
|
|
3794
|
+
}
|
|
3795
|
+
}
|
|
3796
|
+
function recentSpawnFailureFresh() {
|
|
3797
|
+
try {
|
|
3798
|
+
const st = statSync(SPAWN_FAIL_FILE());
|
|
3799
|
+
return Date.now() - st.mtimeMs < SPAWN_FAIL_TTL_MS;
|
|
3800
|
+
} catch {
|
|
3801
|
+
return false;
|
|
3802
|
+
}
|
|
3803
|
+
}
|
|
3804
|
+
function markSpawnFailure() {
|
|
3805
|
+
try {
|
|
3806
|
+
writeFileSync5(SPAWN_FAIL_FILE(), String(Date.now()), { mode: 384 });
|
|
3807
|
+
} catch {}
|
|
3808
|
+
}
|
|
3809
|
+
function clearSpawnFailure() {
|
|
3810
|
+
try {
|
|
3811
|
+
unlinkSync2(SPAWN_FAIL_FILE());
|
|
3812
|
+
} catch {}
|
|
3813
|
+
}
|
|
3814
|
+
async function spawnDaemon(opts) {
|
|
3815
|
+
const lockResult = await acquireOrShareLock(opts);
|
|
3816
|
+
if (lockResult === "wait-existing") {
|
|
3817
|
+
return await pollForSocket(opts.budgetMs ?? 3000);
|
|
3818
|
+
}
|
|
3819
|
+
try {
|
|
3820
|
+
const { spawn } = await import("node:child_process");
|
|
3821
|
+
const binary = await resolveCliBinary();
|
|
3822
|
+
const args = ["daemon", "up"];
|
|
3823
|
+
if (opts.mesh)
|
|
3824
|
+
args.push("--mesh", opts.mesh);
|
|
3825
|
+
const child = spawn(binary, args, {
|
|
3826
|
+
detached: true,
|
|
3827
|
+
stdio: "ignore",
|
|
3828
|
+
env: { ...process.env, CLAUDEMESH_INTERNAL_NO_AUTOSPAWN: "1" }
|
|
3829
|
+
});
|
|
3830
|
+
child.unref();
|
|
3831
|
+
const polled = await pollForSocket(opts.budgetMs ?? 3000);
|
|
3832
|
+
if (polled.ok)
|
|
3833
|
+
clearSpawnFailure();
|
|
3834
|
+
return polled;
|
|
3835
|
+
} catch (err) {
|
|
3836
|
+
return { ok: false, reason: err instanceof Error ? err.message : String(err) };
|
|
3837
|
+
} finally {
|
|
3838
|
+
releaseLock();
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
async function acquireOrShareLock(_opts) {
|
|
3842
|
+
const lockPath = SPAWN_LOCK_FILE();
|
|
3843
|
+
if (existsSync5(lockPath)) {
|
|
3844
|
+
try {
|
|
3845
|
+
const pidStr = readFileSync5(lockPath, "utf8").trim();
|
|
3846
|
+
const pid = Number.parseInt(pidStr, 10);
|
|
3847
|
+
if (Number.isFinite(pid) && pid > 0) {
|
|
3848
|
+
try {
|
|
3849
|
+
process.kill(pid, 0);
|
|
3850
|
+
return "wait-existing";
|
|
3851
|
+
} catch {}
|
|
3852
|
+
}
|
|
3853
|
+
} catch {}
|
|
3854
|
+
}
|
|
3855
|
+
try {
|
|
3856
|
+
writeFileSync5(lockPath, String(process.pid), { mode: 384 });
|
|
3857
|
+
} catch {}
|
|
3858
|
+
return "acquired";
|
|
3859
|
+
}
|
|
3860
|
+
function releaseLock() {
|
|
3861
|
+
try {
|
|
3862
|
+
unlinkSync2(SPAWN_LOCK_FILE());
|
|
3863
|
+
} catch {}
|
|
3864
|
+
}
|
|
3865
|
+
async function pollForSocket(budgetMs) {
|
|
3866
|
+
const start = Date.now();
|
|
3867
|
+
while (Date.now() - start < budgetMs) {
|
|
3868
|
+
if (existsSync5(DAEMON_PATHS.SOCK_FILE)) {
|
|
3869
|
+
const probe = await probeDaemon();
|
|
3870
|
+
if (probe === "up")
|
|
3871
|
+
return { ok: true };
|
|
3872
|
+
}
|
|
3873
|
+
await new Promise((r) => setTimeout(r, 150));
|
|
3874
|
+
}
|
|
3875
|
+
return { ok: false, reason: `socket did not appear within ${budgetMs}ms` };
|
|
3876
|
+
}
|
|
3877
|
+
async function resolveCliBinary() {
|
|
3878
|
+
const argv1 = process.argv[1] ?? "claudemesh";
|
|
3879
|
+
if (/\.ts$/.test(argv1) || /node_modules|src\/entrypoints/.test(argv1)) {
|
|
3880
|
+
try {
|
|
3881
|
+
const { execSync } = await import("node:child_process");
|
|
3882
|
+
return execSync("which claudemesh", { encoding: "utf8" }).trim() || "claudemesh";
|
|
3883
|
+
} catch {
|
|
3884
|
+
return "claudemesh";
|
|
3885
|
+
}
|
|
3886
|
+
}
|
|
3887
|
+
return argv1;
|
|
3888
|
+
}
|
|
3889
|
+
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;
|
|
3890
|
+
var init_lifecycle = __esm(() => {
|
|
3891
|
+
init_client3();
|
|
3892
|
+
init_paths2();
|
|
3893
|
+
});
|
|
3894
|
+
|
|
3626
3895
|
// src/commands/launch.ts
|
|
3627
3896
|
var exports_launch = {};
|
|
3628
3897
|
__export(exports_launch, {
|
|
@@ -3630,42 +3899,26 @@ __export(exports_launch, {
|
|
|
3630
3899
|
});
|
|
3631
3900
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
3632
3901
|
import { randomUUID } from "node:crypto";
|
|
3633
|
-
import { mkdtempSync, writeFileSync as
|
|
3902
|
+
import { mkdtempSync, writeFileSync as writeFileSync6, rmSync, readdirSync, statSync as statSync2, existsSync as existsSync6, readFileSync as readFileSync6 } from "node:fs";
|
|
3634
3903
|
import { tmpdir, hostname as hostname2, homedir as homedir3 } from "node:os";
|
|
3635
|
-
import { join as
|
|
3904
|
+
import { join as join5 } from "node:path";
|
|
3636
3905
|
import { createInterface as createInterface4 } from "node:readline";
|
|
3637
3906
|
async function ensureDaemonRunning(meshSlug, quiet) {
|
|
3638
|
-
const {
|
|
3639
|
-
if (existsSync5(DAEMON_PATHS2.SOCK_FILE))
|
|
3640
|
-
return;
|
|
3907
|
+
const { ensureDaemonReady: ensureDaemonReady2 } = await Promise.resolve().then(() => (init_lifecycle(), exports_lifecycle));
|
|
3641
3908
|
if (!quiet)
|
|
3642
|
-
render.info("
|
|
3643
|
-
const
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
const { execSync } = await import("node:child_process");
|
|
3649
|
-
binary = execSync("which claudemesh", { encoding: "utf8" }).trim();
|
|
3650
|
-
} catch {
|
|
3651
|
-
binary = "claudemesh";
|
|
3652
|
-
}
|
|
3909
|
+
render.info("ensuring claudemesh daemon is running…");
|
|
3910
|
+
const res = await ensureDaemonReady2({ budgetMs: 1e4, mesh: meshSlug });
|
|
3911
|
+
if (res.state === "up") {
|
|
3912
|
+
if (!quiet)
|
|
3913
|
+
render.ok("daemon already running");
|
|
3914
|
+
return;
|
|
3653
3915
|
}
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
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));
|
|
3916
|
+
if (res.state === "started") {
|
|
3917
|
+
if (!quiet)
|
|
3918
|
+
render.ok(`daemon ready (${res.durationMs}ms)`);
|
|
3919
|
+
return;
|
|
3667
3920
|
}
|
|
3668
|
-
render.warn(
|
|
3921
|
+
render.warn(`daemon ${res.state}${res.reason ? `: ${res.reason}` : ""}`, "Run `claudemesh daemon up --mesh " + meshSlug + "` manually, then re-launch.");
|
|
3669
3922
|
}
|
|
3670
3923
|
function parseGroupsString(raw) {
|
|
3671
3924
|
return raw.split(",").map((s) => s.trim()).filter(Boolean).map((token) => {
|
|
@@ -3986,17 +4239,17 @@ async function runLaunch(flags, rawArgs) {
|
|
|
3986
4239
|
for (const entry of readdirSync(tmpBase)) {
|
|
3987
4240
|
if (!entry.startsWith("claudemesh-"))
|
|
3988
4241
|
continue;
|
|
3989
|
-
const full =
|
|
3990
|
-
const age = Date.now() -
|
|
4242
|
+
const full = join5(tmpBase, entry);
|
|
4243
|
+
const age = Date.now() - statSync2(full).mtimeMs;
|
|
3991
4244
|
if (age > 3600000)
|
|
3992
4245
|
rmSync(full, { recursive: true, force: true });
|
|
3993
4246
|
}
|
|
3994
4247
|
} catch {}
|
|
3995
4248
|
await ensureDaemonRunning(mesh.slug, args.quiet);
|
|
3996
4249
|
try {
|
|
3997
|
-
const claudeConfigPath =
|
|
3998
|
-
if (
|
|
3999
|
-
const claudeConfig = JSON.parse(
|
|
4250
|
+
const claudeConfigPath = join5(homedir3(), ".claude.json");
|
|
4251
|
+
if (existsSync6(claudeConfigPath)) {
|
|
4252
|
+
const claudeConfig = JSON.parse(readFileSync6(claudeConfigPath, "utf-8"));
|
|
4000
4253
|
const mcpServers = claudeConfig.mcpServers ?? {};
|
|
4001
4254
|
let cleaned = 0;
|
|
4002
4255
|
for (const key of Object.keys(mcpServers)) {
|
|
@@ -4014,7 +4267,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4014
4267
|
}
|
|
4015
4268
|
if (cleaned > 0) {
|
|
4016
4269
|
claudeConfig.mcpServers = mcpServers;
|
|
4017
|
-
|
|
4270
|
+
writeFileSync6(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
|
|
4018
4271
|
`, "utf-8");
|
|
4019
4272
|
}
|
|
4020
4273
|
}
|
|
@@ -4031,7 +4284,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4031
4284
|
console.log(" (Could not fetch service catalog — mesh services won't be natively available)");
|
|
4032
4285
|
}
|
|
4033
4286
|
}
|
|
4034
|
-
const tmpDir = mkdtempSync(
|
|
4287
|
+
const tmpDir = mkdtempSync(join5(tmpdir(), "claudemesh-"));
|
|
4035
4288
|
const sessionConfig = {
|
|
4036
4289
|
version: 1,
|
|
4037
4290
|
meshes: [mesh],
|
|
@@ -4040,17 +4293,17 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4040
4293
|
...parsedGroups.length > 0 ? { groups: parsedGroups } : {},
|
|
4041
4294
|
messageMode
|
|
4042
4295
|
};
|
|
4043
|
-
|
|
4296
|
+
writeFileSync6(join5(tmpDir, "config.json"), JSON.stringify(sessionConfig, null, 2) + `
|
|
4044
4297
|
`, "utf-8");
|
|
4045
4298
|
if (!args.quiet) {
|
|
4046
4299
|
printBanner(displayName, mesh.slug, role, parsedGroups, messageMode);
|
|
4047
4300
|
}
|
|
4048
4301
|
const meshMcpEntries = [];
|
|
4049
4302
|
if (serviceCatalog.length > 0) {
|
|
4050
|
-
const claudeConfigPath =
|
|
4303
|
+
const claudeConfigPath = join5(homedir3(), ".claude.json");
|
|
4051
4304
|
let claudeConfig = {};
|
|
4052
4305
|
try {
|
|
4053
|
-
claudeConfig = JSON.parse(
|
|
4306
|
+
claudeConfig = JSON.parse(readFileSync6(claudeConfigPath, "utf-8"));
|
|
4054
4307
|
} catch {
|
|
4055
4308
|
claudeConfig = {};
|
|
4056
4309
|
}
|
|
@@ -4077,7 +4330,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4077
4330
|
meshMcpEntries.push({ key: entryKey, entry });
|
|
4078
4331
|
}
|
|
4079
4332
|
claudeConfig.mcpServers = mcpServers;
|
|
4080
|
-
|
|
4333
|
+
writeFileSync6(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
|
|
4081
4334
|
`, "utf-8");
|
|
4082
4335
|
if (!args.quiet && meshMcpEntries.length > 0) {
|
|
4083
4336
|
console.log(` ${meshMcpEntries.length} mesh service(s) registered as native MCPs:`);
|
|
@@ -4114,12 +4367,12 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4114
4367
|
let claudeBin = "claude";
|
|
4115
4368
|
if (!isWindows2) {
|
|
4116
4369
|
const candidates = [
|
|
4117
|
-
|
|
4370
|
+
join5(homedir3(), ".local", "bin", "claude"),
|
|
4118
4371
|
"/usr/local/bin/claude",
|
|
4119
|
-
|
|
4372
|
+
join5(homedir3(), ".claude", "bin", "claude")
|
|
4120
4373
|
];
|
|
4121
4374
|
for (const c of candidates) {
|
|
4122
|
-
if (
|
|
4375
|
+
if (existsSync6(c)) {
|
|
4123
4376
|
claudeBin = c;
|
|
4124
4377
|
break;
|
|
4125
4378
|
}
|
|
@@ -4128,14 +4381,14 @@ async function runLaunch(flags, rawArgs) {
|
|
|
4128
4381
|
const cleanup = () => {
|
|
4129
4382
|
if (meshMcpEntries.length > 0) {
|
|
4130
4383
|
try {
|
|
4131
|
-
const claudeConfigPath =
|
|
4132
|
-
const claudeConfig = JSON.parse(
|
|
4384
|
+
const claudeConfigPath = join5(homedir3(), ".claude.json");
|
|
4385
|
+
const claudeConfig = JSON.parse(readFileSync6(claudeConfigPath, "utf-8"));
|
|
4133
4386
|
const mcpServers = claudeConfig.mcpServers ?? {};
|
|
4134
4387
|
for (const { key } of meshMcpEntries) {
|
|
4135
4388
|
delete mcpServers[key];
|
|
4136
4389
|
}
|
|
4137
4390
|
claudeConfig.mcpServers = mcpServers;
|
|
4138
|
-
|
|
4391
|
+
writeFileSync6(claudeConfigPath, JSON.stringify(claudeConfig, null, 2) + `
|
|
4139
4392
|
`, "utf-8");
|
|
4140
4393
|
} catch {}
|
|
4141
4394
|
}
|
|
@@ -4832,8 +5085,8 @@ __export(exports_join, {
|
|
|
4832
5085
|
runJoin: () => runJoin
|
|
4833
5086
|
});
|
|
4834
5087
|
import sodium3 from "libsodium-wrappers";
|
|
4835
|
-
import { writeFileSync as
|
|
4836
|
-
import { join as
|
|
5088
|
+
import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync4 } from "node:fs";
|
|
5089
|
+
import { join as join6, dirname as dirname3 } from "node:path";
|
|
4837
5090
|
import { homedir as homedir4, hostname as hostname3 } from "node:os";
|
|
4838
5091
|
function deriveAppBaseUrl() {
|
|
4839
5092
|
const override = process.env.CLAUDEMESH_APP_URL;
|
|
@@ -4953,11 +5206,11 @@ async function runJoin(args) {
|
|
|
4953
5206
|
joinedAt: new Date().toISOString()
|
|
4954
5207
|
});
|
|
4955
5208
|
writeConfig(config);
|
|
4956
|
-
const configDir = env.CLAUDEMESH_CONFIG_DIR ??
|
|
4957
|
-
const inviteFile =
|
|
5209
|
+
const configDir = env.CLAUDEMESH_CONFIG_DIR ?? join6(homedir4(), ".claudemesh");
|
|
5210
|
+
const inviteFile = join6(configDir, `invite-${payload.mesh_slug}.txt`);
|
|
4958
5211
|
try {
|
|
4959
|
-
|
|
4960
|
-
|
|
5212
|
+
mkdirSync4(dirname3(inviteFile), { recursive: true });
|
|
5213
|
+
writeFileSync7(inviteFile, link, "utf-8");
|
|
4961
5214
|
} catch {}
|
|
4962
5215
|
console.log("");
|
|
4963
5216
|
console.log(`✓ Joined "${payload.mesh_slug}" as ${displayName}${enroll.alreadyMember ? " (already a member — re-enrolled with same pubkey)" : ""}`);
|
|
@@ -6472,6 +6725,12 @@ async function pickMesh(meshes) {
|
|
|
6472
6725
|
});
|
|
6473
6726
|
}
|
|
6474
6727
|
async function withMesh(opts, fn) {
|
|
6728
|
+
if (getDaemonPolicy().mode === "strict") {
|
|
6729
|
+
console.error(`
|
|
6730
|
+
✘ daemon not reachable — --strict refuses cold-path fallback.
|
|
6731
|
+
` + " run `claudemesh daemon up` (or `claudemesh doctor`) and retry.\n");
|
|
6732
|
+
process.exit(1);
|
|
6733
|
+
}
|
|
6475
6734
|
const config = readConfig();
|
|
6476
6735
|
if (config.meshes.length === 0) {
|
|
6477
6736
|
console.error("No meshes joined. Run `claudemesh join <url>` first.");
|
|
@@ -6522,6 +6781,7 @@ async function withMesh(opts, fn) {
|
|
|
6522
6781
|
var init_connect = __esm(() => {
|
|
6523
6782
|
init_facade8();
|
|
6524
6783
|
init_facade();
|
|
6784
|
+
init_policy();
|
|
6525
6785
|
});
|
|
6526
6786
|
|
|
6527
6787
|
// src/commands/info.ts
|
|
@@ -7158,185 +7418,43 @@ var init_ban = __esm(() => {
|
|
|
7158
7418
|
init_exit_codes();
|
|
7159
7419
|
});
|
|
7160
7420
|
|
|
7161
|
-
// src/
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
let nl = this.buf.indexOf(`
|
|
7421
|
+
// src/ui/warnings.ts
|
|
7422
|
+
function warnDaemonState(res, opts = {}) {
|
|
7423
|
+
if (alreadyWarned)
|
|
7424
|
+
return false;
|
|
7425
|
+
if (opts.quiet || opts.json)
|
|
7426
|
+
return false;
|
|
7427
|
+
if (res.state === "up")
|
|
7428
|
+
return false;
|
|
7429
|
+
if (getDaemonPolicy().mode === "strict" && res.state !== "started")
|
|
7430
|
+
return false;
|
|
7431
|
+
alreadyWarned = true;
|
|
7432
|
+
const tag = (label) => `[claudemesh] ${label}`;
|
|
7433
|
+
const hint = (s) => dim(s);
|
|
7434
|
+
switch (res.state) {
|
|
7435
|
+
case "started":
|
|
7436
|
+
process.stderr.write(`${tag("info")} daemon restarted automatically ${hint(`(took ${res.durationMs}ms)`)}
|
|
7178
7437
|
`);
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
nl = this.buf.indexOf(`
|
|
7438
|
+
return true;
|
|
7439
|
+
case "down":
|
|
7440
|
+
process.stderr.write(`${tag("info")} daemon not running — using cold path ${hint("(slower; run `claudemesh daemon up` for warm path)")}
|
|
7183
7441
|
`);
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
7194
|
-
async function tryBridge(meshSlug, verb, args = {}, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
7195
|
-
const path = socketPath(meshSlug);
|
|
7196
|
-
if (!existsSync6(path))
|
|
7197
|
-
return null;
|
|
7198
|
-
return new Promise((resolve) => {
|
|
7199
|
-
const id = randomUUID2();
|
|
7200
|
-
const req = { id, verb, args };
|
|
7201
|
-
const parser = new LineParser;
|
|
7202
|
-
let settled = false;
|
|
7203
|
-
const finish = (value) => {
|
|
7204
|
-
if (settled)
|
|
7205
|
-
return;
|
|
7206
|
-
settled = true;
|
|
7207
|
-
try {
|
|
7208
|
-
socket.destroy();
|
|
7209
|
-
} catch {}
|
|
7210
|
-
clearTimeout(timer);
|
|
7211
|
-
resolve(value);
|
|
7212
|
-
};
|
|
7213
|
-
const socket = createConnection({ path });
|
|
7214
|
-
const timer = setTimeout(() => {
|
|
7215
|
-
finish(null);
|
|
7216
|
-
}, timeoutMs);
|
|
7217
|
-
socket.on("connect", () => {
|
|
7218
|
-
try {
|
|
7219
|
-
socket.write(frame(req));
|
|
7220
|
-
} catch {
|
|
7221
|
-
finish(null);
|
|
7222
|
-
}
|
|
7223
|
-
});
|
|
7224
|
-
socket.on("data", (chunk) => {
|
|
7225
|
-
const lines = parser.feed(chunk);
|
|
7226
|
-
for (const line of lines) {
|
|
7227
|
-
if (!line.trim())
|
|
7228
|
-
continue;
|
|
7229
|
-
let res;
|
|
7230
|
-
try {
|
|
7231
|
-
res = JSON.parse(line);
|
|
7232
|
-
} catch {
|
|
7233
|
-
continue;
|
|
7234
|
-
}
|
|
7235
|
-
if (res.id !== id)
|
|
7236
|
-
continue;
|
|
7237
|
-
if (res.ok)
|
|
7238
|
-
finish({ ok: true, result: res.result });
|
|
7239
|
-
else
|
|
7240
|
-
finish({ ok: false, error: res.error });
|
|
7241
|
-
return;
|
|
7242
|
-
}
|
|
7243
|
-
});
|
|
7244
|
-
socket.on("error", (err) => {
|
|
7245
|
-
const code = err.code;
|
|
7246
|
-
if (code === "ECONNREFUSED" || code === "ENOENT" || code === "EPERM") {
|
|
7247
|
-
finish(null);
|
|
7248
|
-
} else {
|
|
7249
|
-
finish(null);
|
|
7250
|
-
}
|
|
7251
|
-
});
|
|
7252
|
-
socket.on("close", () => {
|
|
7253
|
-
finish(null);
|
|
7254
|
-
});
|
|
7255
|
-
});
|
|
7256
|
-
}
|
|
7257
|
-
var DEFAULT_TIMEOUT_MS = 5000;
|
|
7258
|
-
var init_client3 = __esm(() => {
|
|
7259
|
-
init_protocol();
|
|
7260
|
-
});
|
|
7261
|
-
|
|
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}`;
|
|
7442
|
+
return true;
|
|
7443
|
+
case "spawn-suppressed":
|
|
7444
|
+
process.stderr.write(`${tag("warn")} ${res.reason ?? "daemon failed to start recently"} — using cold path ${hint("(run `claudemesh doctor`)")}
|
|
7445
|
+
`);
|
|
7446
|
+
return true;
|
|
7447
|
+
case "spawn-failed":
|
|
7448
|
+
process.stderr.write(`${tag("warn")} daemon spawn failed${res.reason ? `: ${res.reason}` : ""} — using cold path ${hint("(check ~/.claudemesh/daemon/daemon.log)")}
|
|
7449
|
+
`);
|
|
7450
|
+
return true;
|
|
7306
7451
|
}
|
|
7307
|
-
return
|
|
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
|
-
});
|
|
7452
|
+
return false;
|
|
7326
7453
|
}
|
|
7327
|
-
var
|
|
7328
|
-
var
|
|
7329
|
-
|
|
7330
|
-
|
|
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
|
-
};
|
|
7454
|
+
var alreadyWarned = false;
|
|
7455
|
+
var init_warnings = __esm(() => {
|
|
7456
|
+
init_policy();
|
|
7457
|
+
init_styles();
|
|
7340
7458
|
});
|
|
7341
7459
|
|
|
7342
7460
|
// src/services/bridge/daemon-route.ts
|
|
@@ -7353,12 +7471,19 @@ __export(exports_daemon_route, {
|
|
|
7353
7471
|
tryGetSkillViaDaemon: () => tryGetSkillViaDaemon,
|
|
7354
7472
|
tryForgetViaDaemon: () => tryForgetViaDaemon
|
|
7355
7473
|
});
|
|
7356
|
-
import { existsSync as existsSync7 } from "node:fs";
|
|
7357
7474
|
function meshQuery(mesh) {
|
|
7358
7475
|
return mesh ? `?mesh=${encodeURIComponent(mesh)}` : "";
|
|
7359
7476
|
}
|
|
7477
|
+
async function daemonReachable() {
|
|
7478
|
+
const policy2 = getDaemonPolicy();
|
|
7479
|
+
if (policy2.mode === "no-daemon")
|
|
7480
|
+
return false;
|
|
7481
|
+
const res = await ensureDaemonReady({ noAutoSpawn: false });
|
|
7482
|
+
warnDaemonState(res, {});
|
|
7483
|
+
return res.state === "up" || res.state === "started";
|
|
7484
|
+
}
|
|
7360
7485
|
async function tryListPeersViaDaemon(mesh) {
|
|
7361
|
-
if (!
|
|
7486
|
+
if (!await daemonReachable())
|
|
7362
7487
|
return null;
|
|
7363
7488
|
try {
|
|
7364
7489
|
const res = await ipc({ path: `/v1/peers${meshQuery(mesh)}`, timeoutMs: 3000 });
|
|
@@ -7373,7 +7498,7 @@ async function tryListPeersViaDaemon(mesh) {
|
|
|
7373
7498
|
}
|
|
7374
7499
|
}
|
|
7375
7500
|
async function tryListSkillsViaDaemon(mesh) {
|
|
7376
|
-
if (!
|
|
7501
|
+
if (!await daemonReachable())
|
|
7377
7502
|
return null;
|
|
7378
7503
|
try {
|
|
7379
7504
|
const res = await ipc({ path: `/v1/skills${meshQuery(mesh)}`, timeoutMs: 3000 });
|
|
@@ -7388,7 +7513,7 @@ async function tryListSkillsViaDaemon(mesh) {
|
|
|
7388
7513
|
}
|
|
7389
7514
|
}
|
|
7390
7515
|
async function tryGetSkillViaDaemon(name, mesh) {
|
|
7391
|
-
if (!
|
|
7516
|
+
if (!await daemonReachable())
|
|
7392
7517
|
return null;
|
|
7393
7518
|
try {
|
|
7394
7519
|
const res = await ipc({
|
|
@@ -7405,7 +7530,7 @@ async function tryGetSkillViaDaemon(name, mesh) {
|
|
|
7405
7530
|
}
|
|
7406
7531
|
}
|
|
7407
7532
|
async function tryGetStateViaDaemon(key, mesh) {
|
|
7408
|
-
if (!
|
|
7533
|
+
if (!await daemonReachable())
|
|
7409
7534
|
return null;
|
|
7410
7535
|
try {
|
|
7411
7536
|
const path = `/v1/state?key=${encodeURIComponent(key)}${mesh ? `&mesh=${encodeURIComponent(mesh)}` : ""}`;
|
|
@@ -7423,7 +7548,7 @@ async function tryGetStateViaDaemon(key, mesh) {
|
|
|
7423
7548
|
}
|
|
7424
7549
|
}
|
|
7425
7550
|
async function tryListStateViaDaemon(mesh) {
|
|
7426
|
-
if (!
|
|
7551
|
+
if (!await daemonReachable())
|
|
7427
7552
|
return null;
|
|
7428
7553
|
try {
|
|
7429
7554
|
const res = await ipc({ path: `/v1/state${meshQuery(mesh)}`, timeoutMs: 3000 });
|
|
@@ -7438,7 +7563,7 @@ async function tryListStateViaDaemon(mesh) {
|
|
|
7438
7563
|
}
|
|
7439
7564
|
}
|
|
7440
7565
|
async function trySetStateViaDaemon(key, value, mesh) {
|
|
7441
|
-
if (!
|
|
7566
|
+
if (!await daemonReachable())
|
|
7442
7567
|
return false;
|
|
7443
7568
|
try {
|
|
7444
7569
|
const res = await ipc({
|
|
@@ -7453,7 +7578,7 @@ async function trySetStateViaDaemon(key, value, mesh) {
|
|
|
7453
7578
|
}
|
|
7454
7579
|
}
|
|
7455
7580
|
async function tryRememberViaDaemon(content, tags, mesh) {
|
|
7456
|
-
if (!
|
|
7581
|
+
if (!await daemonReachable())
|
|
7457
7582
|
return null;
|
|
7458
7583
|
try {
|
|
7459
7584
|
const res = await ipc({
|
|
@@ -7470,7 +7595,7 @@ async function tryRememberViaDaemon(content, tags, mesh) {
|
|
|
7470
7595
|
}
|
|
7471
7596
|
}
|
|
7472
7597
|
async function tryRecallViaDaemon(query, mesh) {
|
|
7473
|
-
if (!
|
|
7598
|
+
if (!await daemonReachable())
|
|
7474
7599
|
return null;
|
|
7475
7600
|
try {
|
|
7476
7601
|
const path = `/v1/memory?q=${encodeURIComponent(query)}${mesh ? `&mesh=${encodeURIComponent(mesh)}` : ""}`;
|
|
@@ -7486,7 +7611,7 @@ async function tryRecallViaDaemon(query, mesh) {
|
|
|
7486
7611
|
}
|
|
7487
7612
|
}
|
|
7488
7613
|
async function tryForgetViaDaemon(id, mesh) {
|
|
7489
|
-
if (!
|
|
7614
|
+
if (!await daemonReachable())
|
|
7490
7615
|
return false;
|
|
7491
7616
|
try {
|
|
7492
7617
|
const path = `/v1/memory/${encodeURIComponent(id)}${meshQuery(mesh)}`;
|
|
@@ -7497,7 +7622,7 @@ async function tryForgetViaDaemon(id, mesh) {
|
|
|
7497
7622
|
}
|
|
7498
7623
|
}
|
|
7499
7624
|
async function trySendViaDaemon(args) {
|
|
7500
|
-
if (!
|
|
7625
|
+
if (!await daemonReachable())
|
|
7501
7626
|
return null;
|
|
7502
7627
|
try {
|
|
7503
7628
|
const res = await ipc({
|
|
@@ -7529,8 +7654,10 @@ async function trySendViaDaemon(args) {
|
|
|
7529
7654
|
}
|
|
7530
7655
|
}
|
|
7531
7656
|
var init_daemon_route = __esm(() => {
|
|
7532
|
-
|
|
7533
|
-
|
|
7657
|
+
init_client3();
|
|
7658
|
+
init_lifecycle();
|
|
7659
|
+
init_policy();
|
|
7660
|
+
init_warnings();
|
|
7534
7661
|
});
|
|
7535
7662
|
|
|
7536
7663
|
// src/commands/peers.ts
|
|
@@ -7557,11 +7684,6 @@ async function listPeersForMesh(slug) {
|
|
|
7557
7684
|
return dr.map((p) => annotateSelf(p, selfMemberPubkey, null));
|
|
7558
7685
|
}
|
|
7559
7686
|
} catch {}
|
|
7560
|
-
const bridged = await tryBridge(slug, "peers");
|
|
7561
|
-
if (bridged && bridged.ok) {
|
|
7562
|
-
const peers = bridged.result;
|
|
7563
|
-
return peers.map((p) => annotateSelf(p, selfMemberPubkey, null));
|
|
7564
|
-
}
|
|
7565
7687
|
let result = [];
|
|
7566
7688
|
await withMesh({ meshSlug: slug }, async (client) => {
|
|
7567
7689
|
const all = await client.listPeers();
|
|
@@ -7631,7 +7753,6 @@ var FIELD_ALIAS;
|
|
|
7631
7753
|
var init_peers = __esm(() => {
|
|
7632
7754
|
init_connect();
|
|
7633
7755
|
init_facade();
|
|
7634
|
-
init_client3();
|
|
7635
7756
|
init_render();
|
|
7636
7757
|
init_styles();
|
|
7637
7758
|
FIELD_ALIAS = {
|
|
@@ -7677,26 +7798,6 @@ async function runSend(flags, to, message) {
|
|
|
7677
7798
|
process.exit(1);
|
|
7678
7799
|
}
|
|
7679
7800
|
}
|
|
7680
|
-
if (meshSlug) {
|
|
7681
|
-
const bridged = await tryBridge(meshSlug, "send", { to, message, priority });
|
|
7682
|
-
if (bridged !== null) {
|
|
7683
|
-
if (bridged.ok) {
|
|
7684
|
-
const r = bridged.result;
|
|
7685
|
-
if (flags.json) {
|
|
7686
|
-
console.log(JSON.stringify({ ok: true, messageId: r.messageId, target: to }));
|
|
7687
|
-
} else {
|
|
7688
|
-
render.ok(`sent to ${to}`, r.messageId ? dim(r.messageId.slice(0, 8)) : undefined);
|
|
7689
|
-
}
|
|
7690
|
-
return;
|
|
7691
|
-
}
|
|
7692
|
-
if (flags.json) {
|
|
7693
|
-
console.log(JSON.stringify({ ok: false, error: bridged.error }));
|
|
7694
|
-
} else {
|
|
7695
|
-
render.err(`send failed: ${bridged.error}`);
|
|
7696
|
-
}
|
|
7697
|
-
process.exit(1);
|
|
7698
|
-
}
|
|
7699
|
-
}
|
|
7700
7801
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
|
|
7701
7802
|
let targetSpec = to;
|
|
7702
7803
|
if (to.startsWith("#") && !/^#[0-9a-z_-]{20,}$/i.test(to)) {
|
|
@@ -7739,7 +7840,6 @@ async function runSend(flags, to, message) {
|
|
|
7739
7840
|
var init_send = __esm(() => {
|
|
7740
7841
|
init_connect();
|
|
7741
7842
|
init_facade();
|
|
7742
|
-
init_client3();
|
|
7743
7843
|
init_daemon_route();
|
|
7744
7844
|
init_render();
|
|
7745
7845
|
init_styles();
|
|
@@ -8067,33 +8167,12 @@ __export(exports_broker_actions, {
|
|
|
8067
8167
|
runForget: () => runForget,
|
|
8068
8168
|
runClock: () => runClock
|
|
8069
8169
|
});
|
|
8070
|
-
function unambiguousMesh(opts) {
|
|
8071
|
-
if (opts.mesh)
|
|
8072
|
-
return opts.mesh;
|
|
8073
|
-
const config = readConfig();
|
|
8074
|
-
return config.meshes.length === 1 ? config.meshes[0].slug : null;
|
|
8075
|
-
}
|
|
8076
8170
|
async function runStatusSet(state, opts) {
|
|
8077
8171
|
const valid = ["idle", "working", "dnd"];
|
|
8078
8172
|
if (!valid.includes(state)) {
|
|
8079
8173
|
render.err(`Invalid status: ${state}`, `must be one of: ${valid.join(", ")}`);
|
|
8080
8174
|
return EXIT.INVALID_ARGS;
|
|
8081
8175
|
}
|
|
8082
|
-
const meshSlug = unambiguousMesh(opts);
|
|
8083
|
-
if (meshSlug) {
|
|
8084
|
-
const bridged = await tryBridge(meshSlug, "status_set", { status: state });
|
|
8085
|
-
if (bridged !== null) {
|
|
8086
|
-
if (bridged.ok) {
|
|
8087
|
-
if (opts.json)
|
|
8088
|
-
console.log(JSON.stringify({ status: state }));
|
|
8089
|
-
else
|
|
8090
|
-
render.ok(`status set to ${bold(state)}`);
|
|
8091
|
-
return EXIT.SUCCESS;
|
|
8092
|
-
}
|
|
8093
|
-
render.err(bridged.error);
|
|
8094
|
-
return EXIT.INTERNAL_ERROR;
|
|
8095
|
-
}
|
|
8096
|
-
}
|
|
8097
8176
|
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
8098
8177
|
await client.setStatus(state);
|
|
8099
8178
|
});
|
|
@@ -8108,21 +8187,6 @@ async function runSummary(text, opts) {
|
|
|
8108
8187
|
render.err("Usage: claudemesh summary <text>");
|
|
8109
8188
|
return EXIT.INVALID_ARGS;
|
|
8110
8189
|
}
|
|
8111
|
-
const meshSlug = unambiguousMesh(opts);
|
|
8112
|
-
if (meshSlug) {
|
|
8113
|
-
const bridged = await tryBridge(meshSlug, "summary", { summary: text });
|
|
8114
|
-
if (bridged !== null) {
|
|
8115
|
-
if (bridged.ok) {
|
|
8116
|
-
if (opts.json)
|
|
8117
|
-
console.log(JSON.stringify({ summary: text }));
|
|
8118
|
-
else
|
|
8119
|
-
render.ok("summary set", dim(text));
|
|
8120
|
-
return EXIT.SUCCESS;
|
|
8121
|
-
}
|
|
8122
|
-
render.err(bridged.error);
|
|
8123
|
-
return EXIT.INTERNAL_ERROR;
|
|
8124
|
-
}
|
|
8125
|
-
}
|
|
8126
8190
|
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
8127
8191
|
await client.setSummary(text);
|
|
8128
8192
|
});
|
|
@@ -8142,21 +8206,6 @@ async function runVisible(value, opts) {
|
|
|
8142
8206
|
render.err("Usage: claudemesh visible <true|false>");
|
|
8143
8207
|
return EXIT.INVALID_ARGS;
|
|
8144
8208
|
}
|
|
8145
|
-
const meshSlug = unambiguousMesh(opts);
|
|
8146
|
-
if (meshSlug) {
|
|
8147
|
-
const bridged = await tryBridge(meshSlug, "visible", { visible });
|
|
8148
|
-
if (bridged !== null) {
|
|
8149
|
-
if (bridged.ok) {
|
|
8150
|
-
if (opts.json)
|
|
8151
|
-
console.log(JSON.stringify({ visible }));
|
|
8152
|
-
else
|
|
8153
|
-
render.ok(visible ? "you are now visible to peers" : "you are now hidden", visible ? undefined : "direct messages still reach you");
|
|
8154
|
-
return EXIT.SUCCESS;
|
|
8155
|
-
}
|
|
8156
|
-
render.err(bridged.error);
|
|
8157
|
-
return EXIT.INTERNAL_ERROR;
|
|
8158
|
-
}
|
|
8159
|
-
}
|
|
8160
8209
|
await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
|
|
8161
8210
|
await client.setVisible(visible);
|
|
8162
8211
|
});
|
|
@@ -8386,8 +8435,6 @@ async function runTaskComplete(id, result, opts) {
|
|
|
8386
8435
|
}
|
|
8387
8436
|
var init_broker_actions = __esm(() => {
|
|
8388
8437
|
init_connect();
|
|
8389
|
-
init_facade();
|
|
8390
|
-
init_client3();
|
|
8391
8438
|
init_daemon_route();
|
|
8392
8439
|
init_render();
|
|
8393
8440
|
init_styles();
|
|
@@ -8622,35 +8669,35 @@ var init_whoami = __esm(() => {
|
|
|
8622
8669
|
});
|
|
8623
8670
|
|
|
8624
8671
|
// src/daemon/lock.ts
|
|
8625
|
-
import { existsSync as
|
|
8672
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeFileSync as writeFileSync8 } from "node:fs";
|
|
8626
8673
|
import { dirname as dirname4 } from "node:path";
|
|
8627
8674
|
function acquireSingletonLock() {
|
|
8628
8675
|
mkdirSync5(dirname4(DAEMON_PATHS.PID_FILE), { recursive: true, mode: 448 });
|
|
8629
|
-
if (
|
|
8630
|
-
const raw =
|
|
8676
|
+
if (existsSync7(DAEMON_PATHS.PID_FILE)) {
|
|
8677
|
+
const raw = readFileSync7(DAEMON_PATHS.PID_FILE, "utf8").trim();
|
|
8631
8678
|
const oldPid = Number.parseInt(raw, 10);
|
|
8632
8679
|
if (Number.isFinite(oldPid) && oldPid > 0 && isProcessAlive(oldPid)) {
|
|
8633
8680
|
return { result: "already-running", pid: oldPid };
|
|
8634
8681
|
}
|
|
8635
8682
|
try {
|
|
8636
|
-
|
|
8683
|
+
unlinkSync3(DAEMON_PATHS.PID_FILE);
|
|
8637
8684
|
} catch {}
|
|
8638
|
-
|
|
8685
|
+
writeFileSync8(DAEMON_PATHS.PID_FILE, String(process.pid), { mode: 384 });
|
|
8639
8686
|
return { result: "stale", pid: process.pid };
|
|
8640
8687
|
}
|
|
8641
|
-
|
|
8688
|
+
writeFileSync8(DAEMON_PATHS.PID_FILE, String(process.pid), { mode: 384 });
|
|
8642
8689
|
return { result: "acquired", pid: process.pid };
|
|
8643
8690
|
}
|
|
8644
8691
|
function releaseSingletonLock() {
|
|
8645
8692
|
try {
|
|
8646
|
-
const raw =
|
|
8693
|
+
const raw = readFileSync7(DAEMON_PATHS.PID_FILE, "utf8").trim();
|
|
8647
8694
|
if (Number.parseInt(raw, 10) === process.pid)
|
|
8648
|
-
|
|
8695
|
+
unlinkSync3(DAEMON_PATHS.PID_FILE);
|
|
8649
8696
|
} catch {}
|
|
8650
8697
|
}
|
|
8651
8698
|
function readRunningPid() {
|
|
8652
8699
|
try {
|
|
8653
|
-
const raw =
|
|
8700
|
+
const raw = readFileSync7(DAEMON_PATHS.PID_FILE, "utf8").trim();
|
|
8654
8701
|
const pid = Number.parseInt(raw, 10);
|
|
8655
8702
|
if (Number.isFinite(pid) && pid > 0 && isProcessAlive(pid))
|
|
8656
8703
|
return pid;
|
|
@@ -8886,10 +8933,10 @@ var init_fingerprint = __esm(() => {
|
|
|
8886
8933
|
});
|
|
8887
8934
|
|
|
8888
8935
|
// src/daemon/ipc/handlers/send.ts
|
|
8889
|
-
import { randomUUID as
|
|
8936
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
8890
8937
|
function acceptSend(req, deps) {
|
|
8891
8938
|
const now = (deps.now ?? Date.now)();
|
|
8892
|
-
const newId = deps.newId ??
|
|
8939
|
+
const newId = deps.newId ?? randomUUID2;
|
|
8893
8940
|
const clientId = req.client_message_id?.trim() || ulidLike(newId);
|
|
8894
8941
|
const body = Buffer.from(req.message, "utf8");
|
|
8895
8942
|
const fingerprint = computeRequestFingerprint({
|
|
@@ -9082,9 +9129,9 @@ function bindSseStream(res, bus) {
|
|
|
9082
9129
|
|
|
9083
9130
|
// src/daemon/ipc/server.ts
|
|
9084
9131
|
import { createServer as createServer2 } from "node:http";
|
|
9085
|
-
import { chmodSync as chmodSync3, existsSync as
|
|
9132
|
+
import { chmodSync as chmodSync3, existsSync as existsSync8, unlinkSync as unlinkSync4 } from "node:fs";
|
|
9086
9133
|
import { timingSafeEqual } from "node:crypto";
|
|
9087
|
-
import { randomUUID as
|
|
9134
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
9088
9135
|
function startIpcServer(opts) {
|
|
9089
9136
|
const log2 = opts.log ?? defaultLogger;
|
|
9090
9137
|
const handler = makeHandler({
|
|
@@ -9098,9 +9145,9 @@ function startIpcServer(opts) {
|
|
|
9098
9145
|
meshConfigs: opts.meshConfigs,
|
|
9099
9146
|
onPendingInserted: opts.onPendingInserted
|
|
9100
9147
|
});
|
|
9101
|
-
if (
|
|
9148
|
+
if (existsSync8(DAEMON_PATHS.SOCK_FILE)) {
|
|
9102
9149
|
try {
|
|
9103
|
-
|
|
9150
|
+
unlinkSync4(DAEMON_PATHS.SOCK_FILE);
|
|
9104
9151
|
} catch {}
|
|
9105
9152
|
}
|
|
9106
9153
|
const uds = createServer2(handler);
|
|
@@ -9136,7 +9183,7 @@ function startIpcServer(opts) {
|
|
|
9136
9183
|
tcp ? new Promise((res) => tcp.close(() => res())) : Promise.resolve()
|
|
9137
9184
|
]);
|
|
9138
9185
|
try {
|
|
9139
|
-
|
|
9186
|
+
unlinkSync4(DAEMON_PATHS.SOCK_FILE);
|
|
9140
9187
|
} catch {}
|
|
9141
9188
|
}
|
|
9142
9189
|
};
|
|
@@ -9555,11 +9602,11 @@ function makeHandler(opts) {
|
|
|
9555
9602
|
respond(res, 400, { error: "missing 'id'" });
|
|
9556
9603
|
return;
|
|
9557
9604
|
}
|
|
9558
|
-
const newId = typeof body.new_client_message_id === "string" && body.new_client_message_id.trim() ? body.new_client_message_id.trim() :
|
|
9605
|
+
const newId = typeof body.new_client_message_id === "string" && body.new_client_message_id.trim() ? body.new_client_message_id.trim() : randomUUID3();
|
|
9559
9606
|
const result = requeueDeadOrPending(opts.outboxDb, {
|
|
9560
9607
|
id: body.id,
|
|
9561
9608
|
newClientMessageId: newId,
|
|
9562
|
-
newRowId:
|
|
9609
|
+
newRowId: randomUUID3(),
|
|
9563
9610
|
now: Date.now(),
|
|
9564
9611
|
abortedBy: typeof body.aborted_by === "string" ? body.aborted_by : "operator"
|
|
9565
9612
|
});
|
|
@@ -10426,7 +10473,7 @@ var POLL_INTERVAL_MS = 500, MAX_ATTEMPTS_PER_ROW = 25, BACKOFF_BASE_MS = 500, BA
|
|
|
10426
10473
|
var init_drain = () => {};
|
|
10427
10474
|
|
|
10428
10475
|
// src/daemon/inbound.ts
|
|
10429
|
-
import { randomUUID as
|
|
10476
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
10430
10477
|
async function handleBrokerPush(msg, ctx) {
|
|
10431
10478
|
if (msg.subtype === "system" && typeof msg.event === "string") {
|
|
10432
10479
|
ctx.bus.publish(mapSystemEventKind(msg.event), {
|
|
@@ -10449,14 +10496,14 @@ async function handleBrokerPush(msg, ctx) {
|
|
|
10449
10496
|
const createdAt = stringOrNull(msg.createdAt);
|
|
10450
10497
|
const priority = stringOrNull(msg.priority) ?? "next";
|
|
10451
10498
|
const subtype = stringOrNull(msg.subtype);
|
|
10452
|
-
const clientMessageId = stringOrNull(msg.client_message_id) ?? brokerMessageId ??
|
|
10499
|
+
const clientMessageId = stringOrNull(msg.client_message_id) ?? brokerMessageId ?? randomUUID4();
|
|
10453
10500
|
const body = await decryptOrFallback({
|
|
10454
10501
|
ciphertext,
|
|
10455
10502
|
nonce,
|
|
10456
10503
|
senderPubkey,
|
|
10457
10504
|
ctx
|
|
10458
10505
|
});
|
|
10459
|
-
const id =
|
|
10506
|
+
const id = randomUUID4();
|
|
10460
10507
|
const inserted = insertIfNew(ctx.db, {
|
|
10461
10508
|
id,
|
|
10462
10509
|
client_message_id: clientMessageId,
|
|
@@ -10533,7 +10580,7 @@ __export(exports_identity, {
|
|
|
10533
10580
|
checkFingerprint: () => checkFingerprint,
|
|
10534
10581
|
acceptCurrentHost: () => acceptCurrentHost
|
|
10535
10582
|
});
|
|
10536
|
-
import { existsSync as
|
|
10583
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync9 } from "node:fs";
|
|
10537
10584
|
import { join as join7 } from "node:path";
|
|
10538
10585
|
import { createHash as createHash2 } from "node:crypto";
|
|
10539
10586
|
import { networkInterfaces } from "node:os";
|
|
@@ -10554,13 +10601,13 @@ function computeCurrentFingerprint() {
|
|
|
10554
10601
|
}
|
|
10555
10602
|
function checkFingerprint() {
|
|
10556
10603
|
const current = computeCurrentFingerprint();
|
|
10557
|
-
if (!
|
|
10558
|
-
|
|
10604
|
+
if (!existsSync9(path())) {
|
|
10605
|
+
writeFileSync9(path(), JSON.stringify(current, null, 2), { mode: 384 });
|
|
10559
10606
|
return { result: "first_run", current };
|
|
10560
10607
|
}
|
|
10561
10608
|
let stored;
|
|
10562
10609
|
try {
|
|
10563
|
-
stored = JSON.parse(
|
|
10610
|
+
stored = JSON.parse(readFileSync8(path(), "utf8"));
|
|
10564
10611
|
} catch {
|
|
10565
10612
|
return { result: "unavailable", current };
|
|
10566
10613
|
}
|
|
@@ -10570,14 +10617,14 @@ function checkFingerprint() {
|
|
|
10570
10617
|
}
|
|
10571
10618
|
function acceptCurrentHost() {
|
|
10572
10619
|
const current = computeCurrentFingerprint();
|
|
10573
|
-
|
|
10620
|
+
writeFileSync9(path(), JSON.stringify(current, null, 2), { mode: 384 });
|
|
10574
10621
|
return current;
|
|
10575
10622
|
}
|
|
10576
10623
|
function readHostId() {
|
|
10577
10624
|
if (process.platform === "linux") {
|
|
10578
10625
|
for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
10579
10626
|
try {
|
|
10580
|
-
const raw =
|
|
10627
|
+
const raw = readFileSync8(p, "utf8").trim();
|
|
10581
10628
|
if (raw)
|
|
10582
10629
|
return `linux:${raw}`;
|
|
10583
10630
|
} catch {}
|
|
@@ -10622,16 +10669,16 @@ var init_identity = __esm(() => {
|
|
|
10622
10669
|
});
|
|
10623
10670
|
|
|
10624
10671
|
// src/daemon/run.ts
|
|
10625
|
-
import { existsSync as
|
|
10672
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync9 } from "node:fs";
|
|
10626
10673
|
function detectContainer() {
|
|
10627
10674
|
if (process.env.KUBERNETES_SERVICE_HOST)
|
|
10628
10675
|
return true;
|
|
10629
10676
|
if (process.env.CONTAINER === "1")
|
|
10630
10677
|
return true;
|
|
10631
10678
|
try {
|
|
10632
|
-
if (
|
|
10679
|
+
if (existsSync10("/.dockerenv"))
|
|
10633
10680
|
return true;
|
|
10634
|
-
const cg =
|
|
10681
|
+
const cg = readFileSync9("/proc/1/cgroup", "utf8");
|
|
10635
10682
|
if (/(docker|kubepods|containerd)/.test(cg))
|
|
10636
10683
|
return true;
|
|
10637
10684
|
} catch {}
|
|
@@ -10650,10 +10697,10 @@ async function runDaemon(opts = {}) {
|
|
|
10650
10697
|
`);
|
|
10651
10698
|
}
|
|
10652
10699
|
const fpCheck = checkFingerprint();
|
|
10653
|
-
const
|
|
10700
|
+
const policy2 = opts.clonePolicy ?? "refuse";
|
|
10654
10701
|
if (fpCheck.result === "mismatch") {
|
|
10655
10702
|
const msg = `host_fingerprint mismatch: this daemon dir was started on a different host.`;
|
|
10656
|
-
if (
|
|
10703
|
+
if (policy2 === "refuse") {
|
|
10657
10704
|
process.stderr.write(`${msg}
|
|
10658
10705
|
`);
|
|
10659
10706
|
process.stderr.write(` stored host_id: ${fpCheck.stored?.host_id}
|
|
@@ -10667,7 +10714,7 @@ async function runDaemon(opts = {}) {
|
|
|
10667
10714
|
releaseSingletonLock();
|
|
10668
10715
|
return 4;
|
|
10669
10716
|
}
|
|
10670
|
-
if (
|
|
10717
|
+
if (policy2 === "warn") {
|
|
10671
10718
|
process.stderr.write(`WARN: ${msg} (continuing per [clone] policy=warn)
|
|
10672
10719
|
`);
|
|
10673
10720
|
}
|
|
@@ -10832,9 +10879,9 @@ __export(exports_service_install, {
|
|
|
10832
10879
|
installService: () => installService,
|
|
10833
10880
|
detectPlatform: () => detectPlatform
|
|
10834
10881
|
});
|
|
10835
|
-
import { existsSync as
|
|
10882
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync7, writeFileSync as writeFileSync10, unlinkSync as unlinkSync5, readFileSync as readFileSync10 } from "node:fs";
|
|
10836
10883
|
import { execSync as execSync2 } from "node:child_process";
|
|
10837
|
-
import { homedir as
|
|
10884
|
+
import { homedir as homedir5 } from "node:os";
|
|
10838
10885
|
import { join as join8, dirname as dirname5 } from "node:path";
|
|
10839
10886
|
function detectPlatform() {
|
|
10840
10887
|
if (process.platform === "darwin")
|
|
@@ -10853,7 +10900,7 @@ function installService(args) {
|
|
|
10853
10900
|
if (isCi() && !args.allowCi) {
|
|
10854
10901
|
throw new Error("Refusing to install persistent service in CI; pass --allow-ci-persistent to override.");
|
|
10855
10902
|
}
|
|
10856
|
-
if (!
|
|
10903
|
+
if (!existsSync11(args.binaryPath)) {
|
|
10857
10904
|
throw new Error(`binary not found at ${args.binaryPath}`);
|
|
10858
10905
|
}
|
|
10859
10906
|
mkdirSync7(DAEMON_PATHS.DAEMON_DIR, { recursive: true, mode: 448 });
|
|
@@ -10869,8 +10916,8 @@ function uninstallService() {
|
|
|
10869
10916
|
try {
|
|
10870
10917
|
execSync2(`launchctl bootout gui/$(id -u)/${SERVICE_LABEL}`, { stdio: "ignore" });
|
|
10871
10918
|
} catch {}
|
|
10872
|
-
if (
|
|
10873
|
-
|
|
10919
|
+
if (existsSync11(p)) {
|
|
10920
|
+
unlinkSync5(p);
|
|
10874
10921
|
removed.push(p);
|
|
10875
10922
|
}
|
|
10876
10923
|
} else if (platform5 === "linux") {
|
|
@@ -10878,15 +10925,15 @@ function uninstallService() {
|
|
|
10878
10925
|
try {
|
|
10879
10926
|
execSync2(`systemctl --user disable --now ${SYSTEMD_UNIT}`, { stdio: "ignore" });
|
|
10880
10927
|
} catch {}
|
|
10881
|
-
if (
|
|
10882
|
-
|
|
10928
|
+
if (existsSync11(p)) {
|
|
10929
|
+
unlinkSync5(p);
|
|
10883
10930
|
removed.push(p);
|
|
10884
10931
|
}
|
|
10885
10932
|
}
|
|
10886
10933
|
return { platform: platform5, removed };
|
|
10887
10934
|
}
|
|
10888
10935
|
function darwinPlistPath() {
|
|
10889
|
-
return join8(
|
|
10936
|
+
return join8(homedir5(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
|
|
10890
10937
|
}
|
|
10891
10938
|
function installDarwin(args) {
|
|
10892
10939
|
const plist = darwinPlistPath();
|
|
@@ -10920,18 +10967,18 @@ function installDarwin(args) {
|
|
|
10920
10967
|
<key>StandardErrorPath</key>
|
|
10921
10968
|
<string>${escapeXml(log2)}</string>
|
|
10922
10969
|
<key>WorkingDirectory</key>
|
|
10923
|
-
<string>${escapeXml(
|
|
10970
|
+
<string>${escapeXml(homedir5())}</string>
|
|
10924
10971
|
<key>EnvironmentVariables</key>
|
|
10925
10972
|
<dict>
|
|
10926
10973
|
<key>HOME</key>
|
|
10927
|
-
<string>${escapeXml(
|
|
10974
|
+
<string>${escapeXml(homedir5())}</string>
|
|
10928
10975
|
<key>PATH</key>
|
|
10929
10976
|
<string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
10930
10977
|
</dict>
|
|
10931
10978
|
</dict>
|
|
10932
10979
|
</plist>
|
|
10933
10980
|
`;
|
|
10934
|
-
|
|
10981
|
+
writeFileSync10(plist, xml, { mode: 420 });
|
|
10935
10982
|
return {
|
|
10936
10983
|
platform: "darwin",
|
|
10937
10984
|
unitPath: plist,
|
|
@@ -10939,7 +10986,7 @@ function installDarwin(args) {
|
|
|
10939
10986
|
};
|
|
10940
10987
|
}
|
|
10941
10988
|
function linuxUnitPath() {
|
|
10942
|
-
return join8(
|
|
10989
|
+
return join8(homedir5(), ".config", "systemd", "user", SYSTEMD_UNIT);
|
|
10943
10990
|
}
|
|
10944
10991
|
function installLinux(args) {
|
|
10945
10992
|
const unit = linuxUnitPath();
|
|
@@ -10968,7 +11015,7 @@ Environment=PATH=/usr/local/bin:/usr/bin:/bin
|
|
|
10968
11015
|
[Install]
|
|
10969
11016
|
WantedBy=default.target
|
|
10970
11017
|
`;
|
|
10971
|
-
|
|
11018
|
+
writeFileSync10(unit, content, { mode: 420 });
|
|
10972
11019
|
return {
|
|
10973
11020
|
platform: "linux",
|
|
10974
11021
|
unitPath: unit,
|
|
@@ -10988,10 +11035,10 @@ function readInstalledUnit() {
|
|
|
10988
11035
|
if (!platform5)
|
|
10989
11036
|
return { platform: null, path: null, content: null };
|
|
10990
11037
|
const path2 = platform5 === "darwin" ? darwinPlistPath() : linuxUnitPath();
|
|
10991
|
-
if (!
|
|
11038
|
+
if (!existsSync11(path2))
|
|
10992
11039
|
return { platform: platform5, path: null, content: null };
|
|
10993
11040
|
try {
|
|
10994
|
-
return { platform: platform5, path: path2, content:
|
|
11041
|
+
return { platform: platform5, path: path2, content: readFileSync10(path2, "utf8") };
|
|
10995
11042
|
} catch {
|
|
10996
11043
|
return { platform: platform5, path: path2, content: null };
|
|
10997
11044
|
}
|
|
@@ -11319,7 +11366,7 @@ async function runStop(opts) {
|
|
|
11319
11366
|
}
|
|
11320
11367
|
var init_daemon = __esm(() => {
|
|
11321
11368
|
init_run();
|
|
11322
|
-
|
|
11369
|
+
init_client3();
|
|
11323
11370
|
init_lock();
|
|
11324
11371
|
init_paths2();
|
|
11325
11372
|
});
|
|
@@ -11333,19 +11380,19 @@ __export(exports_install, {
|
|
|
11333
11380
|
import {
|
|
11334
11381
|
chmodSync as chmodSync4,
|
|
11335
11382
|
copyFileSync,
|
|
11336
|
-
existsSync as
|
|
11383
|
+
existsSync as existsSync12,
|
|
11337
11384
|
mkdirSync as mkdirSync8,
|
|
11338
|
-
readFileSync as
|
|
11339
|
-
writeFileSync as
|
|
11385
|
+
readFileSync as readFileSync11,
|
|
11386
|
+
writeFileSync as writeFileSync11
|
|
11340
11387
|
} from "node:fs";
|
|
11341
|
-
import { homedir as
|
|
11388
|
+
import { homedir as homedir6, platform as platform5 } from "node:os";
|
|
11342
11389
|
import { dirname as dirname6, join as join9, resolve } from "node:path";
|
|
11343
11390
|
import { fileURLToPath } from "node:url";
|
|
11344
11391
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
11345
11392
|
function readClaudeConfig() {
|
|
11346
|
-
if (!
|
|
11393
|
+
if (!existsSync12(CLAUDE_CONFIG))
|
|
11347
11394
|
return {};
|
|
11348
|
-
const text =
|
|
11395
|
+
const text = readFileSync11(CLAUDE_CONFIG, "utf-8").trim();
|
|
11349
11396
|
if (!text)
|
|
11350
11397
|
return {};
|
|
11351
11398
|
try {
|
|
@@ -11355,7 +11402,7 @@ function readClaudeConfig() {
|
|
|
11355
11402
|
}
|
|
11356
11403
|
}
|
|
11357
11404
|
function backupClaudeConfig() {
|
|
11358
|
-
if (!
|
|
11405
|
+
if (!existsSync12(CLAUDE_CONFIG))
|
|
11359
11406
|
return;
|
|
11360
11407
|
const backupDir = join9(dirname6(CLAUDE_CONFIG), ".claude", "backups");
|
|
11361
11408
|
mkdirSync8(backupDir, { recursive: true });
|
|
@@ -11384,7 +11431,7 @@ function patchMcpServer(entry) {
|
|
|
11384
11431
|
return action;
|
|
11385
11432
|
}
|
|
11386
11433
|
function removeMcpServer() {
|
|
11387
|
-
if (!
|
|
11434
|
+
if (!existsSync12(CLAUDE_CONFIG))
|
|
11388
11435
|
return false;
|
|
11389
11436
|
backupClaudeConfig();
|
|
11390
11437
|
const cfg = readClaudeConfig();
|
|
@@ -11398,7 +11445,7 @@ function removeMcpServer() {
|
|
|
11398
11445
|
}
|
|
11399
11446
|
function flushClaudeConfig(obj) {
|
|
11400
11447
|
mkdirSync8(dirname6(CLAUDE_CONFIG), { recursive: true });
|
|
11401
|
-
|
|
11448
|
+
writeFileSync11(CLAUDE_CONFIG, JSON.stringify(obj, null, 2) + `
|
|
11402
11449
|
`, "utf-8");
|
|
11403
11450
|
try {
|
|
11404
11451
|
chmodSync4(CLAUDE_CONFIG, 384);
|
|
@@ -11421,7 +11468,7 @@ function resolveBundledSkillsDir() {
|
|
|
11421
11468
|
const here = fileURLToPath(import.meta.url);
|
|
11422
11469
|
const pkgRoot = resolve(dirname6(here), "..", "..");
|
|
11423
11470
|
const skillsDir = join9(pkgRoot, "skills");
|
|
11424
|
-
if (
|
|
11471
|
+
if (existsSync12(skillsDir))
|
|
11425
11472
|
return skillsDir;
|
|
11426
11473
|
return null;
|
|
11427
11474
|
}
|
|
@@ -11456,7 +11503,7 @@ function uninstallSkills() {
|
|
|
11456
11503
|
if (!entry.isDirectory())
|
|
11457
11504
|
continue;
|
|
11458
11505
|
const dstDir = join9(CLAUDE_SKILLS_ROOT, entry.name);
|
|
11459
|
-
if (
|
|
11506
|
+
if (existsSync12(dstDir)) {
|
|
11460
11507
|
try {
|
|
11461
11508
|
fs.rmSync(dstDir, { recursive: true, force: true });
|
|
11462
11509
|
removed.push(entry.name);
|
|
@@ -11481,9 +11528,9 @@ function entriesEqual(a, b) {
|
|
|
11481
11528
|
return a.command === b.command && JSON.stringify(a.args ?? []) === JSON.stringify(b.args ?? []);
|
|
11482
11529
|
}
|
|
11483
11530
|
function readClaudeSettings() {
|
|
11484
|
-
if (!
|
|
11531
|
+
if (!existsSync12(CLAUDE_SETTINGS))
|
|
11485
11532
|
return {};
|
|
11486
|
-
const text =
|
|
11533
|
+
const text = readFileSync11(CLAUDE_SETTINGS, "utf-8").trim();
|
|
11487
11534
|
if (!text)
|
|
11488
11535
|
return {};
|
|
11489
11536
|
try {
|
|
@@ -11494,7 +11541,7 @@ function readClaudeSettings() {
|
|
|
11494
11541
|
}
|
|
11495
11542
|
function writeClaudeSettings(obj) {
|
|
11496
11543
|
mkdirSync8(dirname6(CLAUDE_SETTINGS), { recursive: true });
|
|
11497
|
-
|
|
11544
|
+
writeFileSync11(CLAUDE_SETTINGS, JSON.stringify(obj, null, 2) + `
|
|
11498
11545
|
`, "utf-8");
|
|
11499
11546
|
}
|
|
11500
11547
|
function installAllowedTools() {
|
|
@@ -11508,7 +11555,7 @@ function installAllowedTools() {
|
|
|
11508
11555
|
return { added: toAdd, unchanged: CLAUDEMESH_TOOLS.length - toAdd.length };
|
|
11509
11556
|
}
|
|
11510
11557
|
function uninstallAllowedTools() {
|
|
11511
|
-
if (!
|
|
11558
|
+
if (!existsSync12(CLAUDE_SETTINGS))
|
|
11512
11559
|
return 0;
|
|
11513
11560
|
const settings = readClaudeSettings();
|
|
11514
11561
|
const existing = settings.allowedTools ?? [];
|
|
@@ -11543,7 +11590,7 @@ function installHooks() {
|
|
|
11543
11590
|
return { added, unchanged };
|
|
11544
11591
|
}
|
|
11545
11592
|
function uninstallHooks() {
|
|
11546
|
-
if (!
|
|
11593
|
+
if (!existsSync12(CLAUDE_SETTINGS))
|
|
11547
11594
|
return 0;
|
|
11548
11595
|
const settings = readClaudeSettings();
|
|
11549
11596
|
const hooks = settings.hooks;
|
|
@@ -11593,7 +11640,7 @@ function runInstall(args = []) {
|
|
|
11593
11640
|
render.err("`bun` is not on PATH.", "Install Bun first: https://bun.com");
|
|
11594
11641
|
process.exit(1);
|
|
11595
11642
|
}
|
|
11596
|
-
if (!
|
|
11643
|
+
if (!existsSync12(entry)) {
|
|
11597
11644
|
render.err(`MCP entry not found at ${entry}`);
|
|
11598
11645
|
process.exit(1);
|
|
11599
11646
|
}
|
|
@@ -11781,9 +11828,9 @@ var init_install = __esm(() => {
|
|
|
11781
11828
|
init_facade();
|
|
11782
11829
|
init_render();
|
|
11783
11830
|
init_styles();
|
|
11784
|
-
CLAUDE_CONFIG = join9(
|
|
11785
|
-
CLAUDE_SETTINGS = join9(
|
|
11786
|
-
CLAUDE_SKILLS_ROOT = join9(
|
|
11831
|
+
CLAUDE_CONFIG = join9(homedir6(), ".claude.json");
|
|
11832
|
+
CLAUDE_SETTINGS = join9(homedir6(), ".claude", "settings.json");
|
|
11833
|
+
CLAUDE_SKILLS_ROOT = join9(homedir6(), ".claude", "skills");
|
|
11787
11834
|
CLAUDEMESH_TOOLS = [
|
|
11788
11835
|
"mcp__claudemesh__cancel_scheduled",
|
|
11789
11836
|
"mcp__claudemesh__check_messages",
|
|
@@ -11838,35 +11885,35 @@ var exports_uninstall = {};
|
|
|
11838
11885
|
__export(exports_uninstall, {
|
|
11839
11886
|
uninstall: () => uninstall
|
|
11840
11887
|
});
|
|
11841
|
-
import { readFileSync as
|
|
11888
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync12, existsSync as existsSync13, rmSync as rmSync2, readdirSync as readdirSync2 } from "node:fs";
|
|
11842
11889
|
import { join as join10, dirname as dirname7 } from "node:path";
|
|
11843
|
-
import { homedir as
|
|
11890
|
+
import { homedir as homedir7 } from "node:os";
|
|
11844
11891
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
11845
11892
|
function bundledSkillsDir() {
|
|
11846
11893
|
const here = fileURLToPath2(import.meta.url);
|
|
11847
11894
|
const pkgRoot = join10(dirname7(here), "..", "..");
|
|
11848
11895
|
const skillsDir = join10(pkgRoot, "skills");
|
|
11849
|
-
return
|
|
11896
|
+
return existsSync13(skillsDir) ? skillsDir : null;
|
|
11850
11897
|
}
|
|
11851
11898
|
async function uninstall() {
|
|
11852
11899
|
let removed = 0;
|
|
11853
|
-
if (
|
|
11900
|
+
if (existsSync13(PATHS.CLAUDE_JSON)) {
|
|
11854
11901
|
try {
|
|
11855
|
-
const raw =
|
|
11902
|
+
const raw = readFileSync12(PATHS.CLAUDE_JSON, "utf-8");
|
|
11856
11903
|
const config = JSON.parse(raw);
|
|
11857
11904
|
const servers = config.mcpServers;
|
|
11858
11905
|
if (servers && "claudemesh" in servers) {
|
|
11859
11906
|
delete servers.claudemesh;
|
|
11860
|
-
|
|
11907
|
+
writeFileSync12(PATHS.CLAUDE_JSON, JSON.stringify(config, null, 2) + `
|
|
11861
11908
|
`, "utf-8");
|
|
11862
11909
|
render.ok("removed MCP server", dim("~/.claude.json"));
|
|
11863
11910
|
removed++;
|
|
11864
11911
|
}
|
|
11865
11912
|
} catch {}
|
|
11866
11913
|
}
|
|
11867
|
-
if (
|
|
11914
|
+
if (existsSync13(PATHS.CLAUDE_SETTINGS)) {
|
|
11868
11915
|
try {
|
|
11869
|
-
const raw =
|
|
11916
|
+
const raw = readFileSync12(PATHS.CLAUDE_SETTINGS, "utf-8");
|
|
11870
11917
|
const config = JSON.parse(raw);
|
|
11871
11918
|
const hooks = config.hooks;
|
|
11872
11919
|
if (hooks) {
|
|
@@ -11887,7 +11934,7 @@ async function uninstall() {
|
|
|
11887
11934
|
}
|
|
11888
11935
|
}
|
|
11889
11936
|
if (removedHooks > 0) {
|
|
11890
|
-
|
|
11937
|
+
writeFileSync12(PATHS.CLAUDE_SETTINGS, JSON.stringify(config, null, 2) + `
|
|
11891
11938
|
`, "utf-8");
|
|
11892
11939
|
render.ok(`removed ${removedHooks} claudemesh hook${removedHooks === 1 ? "" : "s"}`, dim("settings.json"));
|
|
11893
11940
|
removed++;
|
|
@@ -11903,7 +11950,7 @@ async function uninstall() {
|
|
|
11903
11950
|
if (!entry.isDirectory())
|
|
11904
11951
|
continue;
|
|
11905
11952
|
const dst = join10(CLAUDE_SKILLS_ROOT2, entry.name);
|
|
11906
|
-
if (
|
|
11953
|
+
if (existsSync13(dst)) {
|
|
11907
11954
|
try {
|
|
11908
11955
|
rmSync2(dst, { recursive: true, force: true });
|
|
11909
11956
|
removedSkills.push(entry.name);
|
|
@@ -11927,7 +11974,7 @@ var init_uninstall = __esm(() => {
|
|
|
11927
11974
|
init_render();
|
|
11928
11975
|
init_styles();
|
|
11929
11976
|
init_exit_codes();
|
|
11930
|
-
CLAUDE_SKILLS_ROOT2 = join10(
|
|
11977
|
+
CLAUDE_SKILLS_ROOT2 = join10(homedir7(), ".claude", "skills");
|
|
11931
11978
|
});
|
|
11932
11979
|
|
|
11933
11980
|
// src/commands/doctor.ts
|
|
@@ -11935,8 +11982,8 @@ var exports_doctor = {};
|
|
|
11935
11982
|
__export(exports_doctor, {
|
|
11936
11983
|
runDoctor: () => runDoctor
|
|
11937
11984
|
});
|
|
11938
|
-
import { existsSync as
|
|
11939
|
-
import { homedir as
|
|
11985
|
+
import { existsSync as existsSync14, readFileSync as readFileSync13, statSync as statSync3 } from "node:fs";
|
|
11986
|
+
import { homedir as homedir8, platform as platform6 } from "node:os";
|
|
11940
11987
|
import { join as join11 } from "node:path";
|
|
11941
11988
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
11942
11989
|
function checkNode() {
|
|
@@ -11961,8 +12008,8 @@ function checkClaudeOnPath() {
|
|
|
11961
12008
|
};
|
|
11962
12009
|
}
|
|
11963
12010
|
function checkMcpRegistered() {
|
|
11964
|
-
const claudeConfig = join11(
|
|
11965
|
-
if (!
|
|
12011
|
+
const claudeConfig = join11(homedir8(), ".claude.json");
|
|
12012
|
+
if (!existsSync14(claudeConfig)) {
|
|
11966
12013
|
return {
|
|
11967
12014
|
name: "claudemesh MCP registered in ~/.claude.json",
|
|
11968
12015
|
pass: false,
|
|
@@ -11970,7 +12017,7 @@ function checkMcpRegistered() {
|
|
|
11970
12017
|
};
|
|
11971
12018
|
}
|
|
11972
12019
|
try {
|
|
11973
|
-
const cfg = JSON.parse(
|
|
12020
|
+
const cfg = JSON.parse(readFileSync13(claudeConfig, "utf-8"));
|
|
11974
12021
|
const registered = Boolean(cfg.mcpServers?.["claudemesh"]);
|
|
11975
12022
|
return {
|
|
11976
12023
|
name: "claudemesh MCP registered in ~/.claude.json",
|
|
@@ -11987,8 +12034,8 @@ function checkMcpRegistered() {
|
|
|
11987
12034
|
}
|
|
11988
12035
|
}
|
|
11989
12036
|
function checkHooksRegistered() {
|
|
11990
|
-
const settings = join11(
|
|
11991
|
-
if (!
|
|
12037
|
+
const settings = join11(homedir8(), ".claude", "settings.json");
|
|
12038
|
+
if (!existsSync14(settings)) {
|
|
11992
12039
|
return {
|
|
11993
12040
|
name: "Status hooks registered in ~/.claude/settings.json",
|
|
11994
12041
|
pass: false,
|
|
@@ -11996,7 +12043,7 @@ function checkHooksRegistered() {
|
|
|
11996
12043
|
};
|
|
11997
12044
|
}
|
|
11998
12045
|
try {
|
|
11999
|
-
const raw =
|
|
12046
|
+
const raw = readFileSync13(settings, "utf-8");
|
|
12000
12047
|
const has = raw.includes("claudemesh hook ");
|
|
12001
12048
|
return {
|
|
12002
12049
|
name: "Status hooks registered in ~/.claude/settings.json",
|
|
@@ -12013,7 +12060,7 @@ function checkHooksRegistered() {
|
|
|
12013
12060
|
}
|
|
12014
12061
|
function checkConfigFile() {
|
|
12015
12062
|
const path2 = getConfigPath();
|
|
12016
|
-
if (!
|
|
12063
|
+
if (!existsSync14(path2)) {
|
|
12017
12064
|
return {
|
|
12018
12065
|
name: "~/.claudemesh/config.json exists and parses",
|
|
12019
12066
|
pass: true,
|
|
@@ -12022,7 +12069,7 @@ function checkConfigFile() {
|
|
|
12022
12069
|
}
|
|
12023
12070
|
try {
|
|
12024
12071
|
readConfig();
|
|
12025
|
-
const st =
|
|
12072
|
+
const st = statSync3(path2);
|
|
12026
12073
|
const mode = (st.mode & 511).toString(8);
|
|
12027
12074
|
const secure = platform6() === "win32" || mode === "600";
|
|
12028
12075
|
return {
|
|
@@ -12196,7 +12243,7 @@ var exports_status = {};
|
|
|
12196
12243
|
__export(exports_status, {
|
|
12197
12244
|
runStatus: () => runStatus2
|
|
12198
12245
|
});
|
|
12199
|
-
import { statSync as
|
|
12246
|
+
import { statSync as statSync4, existsSync as existsSync15 } from "node:fs";
|
|
12200
12247
|
import WebSocket3 from "ws";
|
|
12201
12248
|
async function probeBroker(url, timeoutMs = 4000) {
|
|
12202
12249
|
return new Promise((resolve2) => {
|
|
@@ -12226,8 +12273,8 @@ async function runStatus2() {
|
|
|
12226
12273
|
render.section(`status (v${VERSION})`);
|
|
12227
12274
|
const configPath = getConfigPath();
|
|
12228
12275
|
let configPermsNote = "missing";
|
|
12229
|
-
if (
|
|
12230
|
-
const mode = (
|
|
12276
|
+
if (existsSync15(configPath)) {
|
|
12277
|
+
const mode = (statSync4(configPath).mode & 511).toString(8).padStart(4, "0");
|
|
12231
12278
|
configPermsNote = mode === "0600" ? `${mode}` : `${mode} — expected 0600`;
|
|
12232
12279
|
}
|
|
12233
12280
|
render.kv([["config", configPath], ["perms", configPermsNote]]);
|
|
@@ -12372,13 +12419,13 @@ var init_check_claude_binary = __esm(() => {
|
|
|
12372
12419
|
});
|
|
12373
12420
|
|
|
12374
12421
|
// src/services/health/check-mcp-registered.ts
|
|
12375
|
-
import { existsSync as
|
|
12422
|
+
import { existsSync as existsSync16, readFileSync as readFileSync14 } from "node:fs";
|
|
12376
12423
|
function checkMcpRegistered2() {
|
|
12377
12424
|
try {
|
|
12378
|
-
if (!
|
|
12425
|
+
if (!existsSync16(PATHS.CLAUDE_JSON)) {
|
|
12379
12426
|
return { name: "mcp-registered", ok: false, message: "~/.claude.json not found" };
|
|
12380
12427
|
}
|
|
12381
|
-
const raw =
|
|
12428
|
+
const raw = readFileSync14(PATHS.CLAUDE_JSON, "utf-8");
|
|
12382
12429
|
const config = JSON.parse(raw);
|
|
12383
12430
|
if (config.mcpServers && "claudemesh" in config.mcpServers) {
|
|
12384
12431
|
return { name: "mcp-registered", ok: true, message: "MCP server registered" };
|
|
@@ -12393,13 +12440,13 @@ var init_check_mcp_registered = __esm(() => {
|
|
|
12393
12440
|
});
|
|
12394
12441
|
|
|
12395
12442
|
// src/services/health/check-hooks-registered.ts
|
|
12396
|
-
import { existsSync as
|
|
12443
|
+
import { existsSync as existsSync17, readFileSync as readFileSync15 } from "node:fs";
|
|
12397
12444
|
function checkHooksRegistered2() {
|
|
12398
12445
|
try {
|
|
12399
|
-
if (!
|
|
12446
|
+
if (!existsSync17(PATHS.CLAUDE_SETTINGS)) {
|
|
12400
12447
|
return { name: "hooks-registered", ok: false, message: "~/.claude/settings.json not found" };
|
|
12401
12448
|
}
|
|
12402
|
-
const raw =
|
|
12449
|
+
const raw = readFileSync15(PATHS.CLAUDE_SETTINGS, "utf-8");
|
|
12403
12450
|
const config = JSON.parse(raw);
|
|
12404
12451
|
if (config.hooks) {
|
|
12405
12452
|
return { name: "hooks-registered", ok: true, message: "Hooks configured" };
|
|
@@ -12414,14 +12461,14 @@ var init_check_hooks_registered = __esm(() => {
|
|
|
12414
12461
|
});
|
|
12415
12462
|
|
|
12416
12463
|
// src/services/health/check-config-perms.ts
|
|
12417
|
-
import { existsSync as
|
|
12464
|
+
import { existsSync as existsSync18, statSync as statSync5 } from "node:fs";
|
|
12418
12465
|
function checkConfigPerms() {
|
|
12419
12466
|
const configFile = PATHS.CONFIG_FILE;
|
|
12420
|
-
if (!
|
|
12467
|
+
if (!existsSync18(configFile)) {
|
|
12421
12468
|
return { name: "config-perms", ok: true, message: "No config file yet (first run)" };
|
|
12422
12469
|
}
|
|
12423
12470
|
try {
|
|
12424
|
-
const mode =
|
|
12471
|
+
const mode = statSync5(configFile).mode & 511;
|
|
12425
12472
|
if (mode <= 384) {
|
|
12426
12473
|
return { name: "config-perms", ok: true, message: `config.json mode ${mode.toString(8)}` };
|
|
12427
12474
|
}
|
|
@@ -12435,13 +12482,13 @@ var init_check_config_perms = __esm(() => {
|
|
|
12435
12482
|
});
|
|
12436
12483
|
|
|
12437
12484
|
// src/services/health/check-keypairs-valid.ts
|
|
12438
|
-
import { existsSync as
|
|
12485
|
+
import { existsSync as existsSync19, readFileSync as readFileSync16 } from "node:fs";
|
|
12439
12486
|
function checkKeypairsValid() {
|
|
12440
|
-
if (!
|
|
12487
|
+
if (!existsSync19(PATHS.CONFIG_FILE)) {
|
|
12441
12488
|
return { name: "keypairs-valid", ok: true, message: "No config (first run)" };
|
|
12442
12489
|
}
|
|
12443
12490
|
try {
|
|
12444
|
-
const raw =
|
|
12491
|
+
const raw = readFileSync16(PATHS.CONFIG_FILE, "utf-8");
|
|
12445
12492
|
const config = JSON.parse(raw);
|
|
12446
12493
|
const meshes = config.meshes ?? [];
|
|
12447
12494
|
if (meshes.length === 0) {
|
|
@@ -12921,8 +12968,8 @@ var exports_url_handler = {};
|
|
|
12921
12968
|
__export(exports_url_handler, {
|
|
12922
12969
|
runUrlHandler: () => runUrlHandler
|
|
12923
12970
|
});
|
|
12924
|
-
import { platform as platform7, homedir as
|
|
12925
|
-
import { existsSync as
|
|
12971
|
+
import { platform as platform7, homedir as homedir9 } from "node:os";
|
|
12972
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync9, writeFileSync as writeFileSync13, rmSync as rmSync3, chmodSync as chmodSync5 } from "node:fs";
|
|
12926
12973
|
import { join as join12 } from "node:path";
|
|
12927
12974
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
12928
12975
|
function resolveClaudemeshBin() {
|
|
@@ -12930,7 +12977,7 @@ function resolveClaudemeshBin() {
|
|
|
12930
12977
|
}
|
|
12931
12978
|
function installDarwin2() {
|
|
12932
12979
|
const binPath = resolveClaudemeshBin();
|
|
12933
|
-
const appDir = join12(
|
|
12980
|
+
const appDir = join12(homedir9(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
|
|
12934
12981
|
const contents = join12(appDir, "Contents");
|
|
12935
12982
|
const macOS = join12(contents, "MacOS");
|
|
12936
12983
|
mkdirSync9(macOS, { recursive: true });
|
|
@@ -12956,7 +13003,7 @@ function installDarwin2() {
|
|
|
12956
13003
|
</array>
|
|
12957
13004
|
</dict>
|
|
12958
13005
|
</plist>`;
|
|
12959
|
-
|
|
13006
|
+
writeFileSync13(join12(contents, "Info.plist"), plist);
|
|
12960
13007
|
const shim = `#!/bin/sh
|
|
12961
13008
|
URL="$1"
|
|
12962
13009
|
CODE=\${URL#claudemesh://}
|
|
@@ -12971,7 +13018,7 @@ end tell
|
|
|
12971
13018
|
EOF
|
|
12972
13019
|
`;
|
|
12973
13020
|
const shimPath = join12(macOS, "open-url");
|
|
12974
|
-
|
|
13021
|
+
writeFileSync13(shimPath, shim);
|
|
12975
13022
|
chmodSync5(shimPath, 493);
|
|
12976
13023
|
const lsreg = spawnSync5("/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister", ["-f", appDir], { encoding: "utf-8" });
|
|
12977
13024
|
if (lsreg.status !== 0) {
|
|
@@ -12982,7 +13029,7 @@ EOF
|
|
|
12982
13029
|
}
|
|
12983
13030
|
function installLinux2() {
|
|
12984
13031
|
const binPath = resolveClaudemeshBin();
|
|
12985
|
-
const appsDir = join12(
|
|
13032
|
+
const appsDir = join12(homedir9(), ".local", "share", "applications");
|
|
12986
13033
|
mkdirSync9(appsDir, { recursive: true });
|
|
12987
13034
|
const desktop = `[Desktop Entry]
|
|
12988
13035
|
Type=Application
|
|
@@ -12995,7 +13042,7 @@ MimeType=x-scheme-handler/claudemesh;
|
|
|
12995
13042
|
NoDisplay=true
|
|
12996
13043
|
`;
|
|
12997
13044
|
const desktopPath = join12(appsDir, "claudemesh.desktop");
|
|
12998
|
-
|
|
13045
|
+
writeFileSync13(desktopPath, desktop);
|
|
12999
13046
|
const xdg1 = spawnSync5("xdg-mime", ["default", "claudemesh.desktop", "x-scheme-handler/claudemesh"], { encoding: "utf-8" });
|
|
13000
13047
|
if (xdg1.status !== 0) {
|
|
13001
13048
|
render.warn("xdg-mime not available — skipped mime default registration");
|
|
@@ -13017,8 +13064,8 @@ function installWindows() {
|
|
|
13017
13064
|
`[HKEY_CURRENT_USER\\Software\\Classes\\claudemesh\\shell\\open\\command]`,
|
|
13018
13065
|
`@="\\"${binPath.replace(/\\/g, "\\\\")}\\" \\"%1\\""`
|
|
13019
13066
|
];
|
|
13020
|
-
const regPath = join12(
|
|
13021
|
-
|
|
13067
|
+
const regPath = join12(homedir9(), "claudemesh-handler.reg");
|
|
13068
|
+
writeFileSync13(regPath, lines.join(`\r
|
|
13022
13069
|
`));
|
|
13023
13070
|
const res = spawnSync5("reg.exe", ["import", regPath], { encoding: "utf-8" });
|
|
13024
13071
|
if (res.status !== 0) {
|
|
@@ -13029,15 +13076,15 @@ function installWindows() {
|
|
|
13029
13076
|
return EXIT.SUCCESS;
|
|
13030
13077
|
}
|
|
13031
13078
|
function uninstallDarwin() {
|
|
13032
|
-
const appDir = join12(
|
|
13033
|
-
if (
|
|
13079
|
+
const appDir = join12(homedir9(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
|
|
13080
|
+
if (existsSync20(appDir))
|
|
13034
13081
|
rmSync3(appDir, { recursive: true, force: true });
|
|
13035
13082
|
render.ok("removed claudemesh:// handler on macOS");
|
|
13036
13083
|
return EXIT.SUCCESS;
|
|
13037
13084
|
}
|
|
13038
13085
|
function uninstallLinux() {
|
|
13039
|
-
const desktopPath = join12(
|
|
13040
|
-
if (
|
|
13086
|
+
const desktopPath = join12(homedir9(), ".local", "share", "applications", "claudemesh.desktop");
|
|
13087
|
+
if (existsSync20(desktopPath))
|
|
13041
13088
|
rmSync3(desktopPath, { force: true });
|
|
13042
13089
|
render.ok("removed claudemesh:// handler on Linux");
|
|
13043
13090
|
return EXIT.SUCCESS;
|
|
@@ -13082,9 +13129,9 @@ var exports_status_line = {};
|
|
|
13082
13129
|
__export(exports_status_line, {
|
|
13083
13130
|
runStatusLine: () => runStatusLine
|
|
13084
13131
|
});
|
|
13085
|
-
import { existsSync as
|
|
13132
|
+
import { existsSync as existsSync21, readFileSync as readFileSync17 } from "node:fs";
|
|
13086
13133
|
import { join as join13 } from "node:path";
|
|
13087
|
-
import { homedir as
|
|
13134
|
+
import { homedir as homedir10 } from "node:os";
|
|
13088
13135
|
async function runStatusLine() {
|
|
13089
13136
|
try {
|
|
13090
13137
|
const config = readConfig();
|
|
@@ -13092,11 +13139,11 @@ async function runStatusLine() {
|
|
|
13092
13139
|
process.stdout.write("◇ claudemesh (not joined)");
|
|
13093
13140
|
return EXIT.SUCCESS;
|
|
13094
13141
|
}
|
|
13095
|
-
const cachePath = join13(
|
|
13142
|
+
const cachePath = join13(homedir10(), ".claudemesh", "peer-cache.json");
|
|
13096
13143
|
let cache = {};
|
|
13097
|
-
if (
|
|
13144
|
+
if (existsSync21(cachePath)) {
|
|
13098
13145
|
try {
|
|
13099
|
-
cache = JSON.parse(
|
|
13146
|
+
cache = JSON.parse(readFileSync17(cachePath, "utf-8"));
|
|
13100
13147
|
} catch {}
|
|
13101
13148
|
}
|
|
13102
13149
|
const pick = config.meshes[0];
|
|
@@ -13127,7 +13174,7 @@ __export(exports_backup, {
|
|
|
13127
13174
|
runRestore: () => runRestore,
|
|
13128
13175
|
runBackup: () => runBackup
|
|
13129
13176
|
});
|
|
13130
|
-
import { readFileSync as
|
|
13177
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync14, existsSync as existsSync22 } from "node:fs";
|
|
13131
13178
|
import { createInterface as createInterface11 } from "node:readline";
|
|
13132
13179
|
function readHidden(prompt5) {
|
|
13133
13180
|
return new Promise((resolve2) => {
|
|
@@ -13169,11 +13216,11 @@ async function deriveKey(pass, salt, s) {
|
|
|
13169
13216
|
}
|
|
13170
13217
|
async function runBackup(outPath) {
|
|
13171
13218
|
const configPath = getConfigPath();
|
|
13172
|
-
if (!
|
|
13219
|
+
if (!existsSync22(configPath)) {
|
|
13173
13220
|
console.error(" No config found — nothing to back up. Join a mesh first.");
|
|
13174
13221
|
return EXIT.NOT_FOUND;
|
|
13175
13222
|
}
|
|
13176
|
-
const plaintext =
|
|
13223
|
+
const plaintext = readFileSync18(configPath);
|
|
13177
13224
|
const pass = await readHidden(" Passphrase (min 12 chars): ");
|
|
13178
13225
|
if (pass.length < 12) {
|
|
13179
13226
|
console.error(" ✗ Passphrase too short.");
|
|
@@ -13191,7 +13238,7 @@ async function runBackup(outPath) {
|
|
|
13191
13238
|
const ciphertext = Buffer.from(s.crypto_aead_xchacha20poly1305_ietf_encrypt(plaintext, null, null, nonce, key));
|
|
13192
13239
|
const blob = Buffer.concat([MAGIC, salt, nonce, ciphertext]);
|
|
13193
13240
|
const file = outPath ?? `claudemesh-backup-${new Date().toISOString().replace(/[:.]/g, "-")}.cmb`;
|
|
13194
|
-
|
|
13241
|
+
writeFileSync14(file, blob, { mode: 384 });
|
|
13195
13242
|
console.log(`
|
|
13196
13243
|
✓ Backup saved: ${file}`);
|
|
13197
13244
|
console.log(` Size: ${blob.length} bytes. Guard the passphrase — there is no recovery.
|
|
@@ -13203,11 +13250,11 @@ async function runRestore(inPath) {
|
|
|
13203
13250
|
console.error(" Usage: claudemesh restore <backup-file>");
|
|
13204
13251
|
return EXIT.INVALID_ARGS;
|
|
13205
13252
|
}
|
|
13206
|
-
if (!
|
|
13253
|
+
if (!existsSync22(inPath)) {
|
|
13207
13254
|
console.error(` ✗ File not found: ${inPath}`);
|
|
13208
13255
|
return EXIT.NOT_FOUND;
|
|
13209
13256
|
}
|
|
13210
|
-
const blob =
|
|
13257
|
+
const blob = readFileSync18(inPath);
|
|
13211
13258
|
if (blob.length < 4 + 16 + 24 + 17 || !blob.subarray(0, 4).equals(MAGIC)) {
|
|
13212
13259
|
console.error(" ✗ Not a claudemesh backup file (bad magic).");
|
|
13213
13260
|
return EXIT.INVALID_ARGS;
|
|
@@ -13226,12 +13273,12 @@ async function runRestore(inPath) {
|
|
|
13226
13273
|
return EXIT.INTERNAL_ERROR;
|
|
13227
13274
|
}
|
|
13228
13275
|
const configPath = getConfigPath();
|
|
13229
|
-
if (
|
|
13276
|
+
if (existsSync22(configPath)) {
|
|
13230
13277
|
const backupOld = `${configPath}.before-restore.${Date.now()}`;
|
|
13231
|
-
|
|
13278
|
+
writeFileSync14(backupOld, readFileSync18(configPath), { mode: 384 });
|
|
13232
13279
|
console.log(` ↻ Existing config saved to ${backupOld}`);
|
|
13233
13280
|
}
|
|
13234
|
-
|
|
13281
|
+
writeFileSync14(configPath, Buffer.from(plaintext), { mode: 384 });
|
|
13235
13282
|
console.log(`
|
|
13236
13283
|
✓ Config restored to ${configPath}`);
|
|
13237
13284
|
console.log(" Run `claudemesh list` to verify your meshes.\n");
|
|
@@ -13251,7 +13298,7 @@ __export(exports_upgrade, {
|
|
|
13251
13298
|
runUpgrade: () => runUpgrade
|
|
13252
13299
|
});
|
|
13253
13300
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
13254
|
-
import { existsSync as
|
|
13301
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
13255
13302
|
import { dirname as dirname8, join as join14, resolve as resolve2 } from "node:path";
|
|
13256
13303
|
async function latestVersion() {
|
|
13257
13304
|
try {
|
|
@@ -13266,14 +13313,14 @@ async function latestVersion() {
|
|
|
13266
13313
|
}
|
|
13267
13314
|
function findNpm() {
|
|
13268
13315
|
const portable = join14(process.env.HOME ?? "", ".claudemesh", "node", "bin", "npm");
|
|
13269
|
-
if (
|
|
13316
|
+
if (existsSync23(portable)) {
|
|
13270
13317
|
return { npm: portable, prefix: join14(process.env.HOME ?? "", ".claudemesh") };
|
|
13271
13318
|
}
|
|
13272
13319
|
let cur = resolve2(process.argv[1] ?? ".");
|
|
13273
13320
|
for (let i = 0;i < 6; i++) {
|
|
13274
13321
|
cur = dirname8(cur);
|
|
13275
13322
|
const candidate = join14(cur, "bin", "npm");
|
|
13276
|
-
if (
|
|
13323
|
+
if (existsSync23(candidate))
|
|
13277
13324
|
return { npm: candidate };
|
|
13278
13325
|
}
|
|
13279
13326
|
return { npm: "npm" };
|
|
@@ -13335,8 +13382,8 @@ __export(exports_grants, {
|
|
|
13335
13382
|
runBlock: () => runBlock,
|
|
13336
13383
|
isAllowed: () => isAllowed
|
|
13337
13384
|
});
|
|
13338
|
-
import { existsSync as
|
|
13339
|
-
import { homedir as
|
|
13385
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync10, readFileSync as readFileSync19, writeFileSync as writeFileSync15 } from "node:fs";
|
|
13386
|
+
import { homedir as homedir11 } from "node:os";
|
|
13340
13387
|
import { join as join15 } from "node:path";
|
|
13341
13388
|
async function syncToBroker(meshSlug, grants) {
|
|
13342
13389
|
const auth = getStoredToken();
|
|
@@ -13355,19 +13402,19 @@ async function syncToBroker(meshSlug, grants) {
|
|
|
13355
13402
|
}
|
|
13356
13403
|
}
|
|
13357
13404
|
function readGrants() {
|
|
13358
|
-
if (!
|
|
13405
|
+
if (!existsSync24(GRANT_FILE))
|
|
13359
13406
|
return {};
|
|
13360
13407
|
try {
|
|
13361
|
-
return JSON.parse(
|
|
13408
|
+
return JSON.parse(readFileSync19(GRANT_FILE, "utf-8"));
|
|
13362
13409
|
} catch {
|
|
13363
13410
|
return {};
|
|
13364
13411
|
}
|
|
13365
13412
|
}
|
|
13366
13413
|
function writeGrants(g) {
|
|
13367
|
-
const dir = join15(
|
|
13368
|
-
if (!
|
|
13414
|
+
const dir = join15(homedir11(), ".claudemesh");
|
|
13415
|
+
if (!existsSync24(dir))
|
|
13369
13416
|
mkdirSync10(dir, { recursive: true });
|
|
13370
|
-
|
|
13417
|
+
writeFileSync15(GRANT_FILE, JSON.stringify(g, null, 2), { mode: 384 });
|
|
13371
13418
|
}
|
|
13372
13419
|
function resolveCaps(input) {
|
|
13373
13420
|
if (input.includes("all"))
|
|
@@ -13523,7 +13570,7 @@ var init_grants = __esm(() => {
|
|
|
13523
13570
|
BROKER_HTTP7 = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
|
|
13524
13571
|
ALL_CAPS = ["read", "dm", "broadcast", "state-read", "state-write", "file-read"];
|
|
13525
13572
|
DEFAULT_CAPS = ["read", "dm", "broadcast", "state-read"];
|
|
13526
|
-
GRANT_FILE = join15(
|
|
13573
|
+
GRANT_FILE = join15(homedir11(), ".claudemesh", "grants.json");
|
|
13527
13574
|
});
|
|
13528
13575
|
|
|
13529
13576
|
// src/commands/profile.ts
|
|
@@ -15205,7 +15252,7 @@ __export(exports_file, {
|
|
|
15205
15252
|
});
|
|
15206
15253
|
import { hostname as osHostname } from "node:os";
|
|
15207
15254
|
import { resolve as resolvePath, basename, dirname as dirname9 } from "node:path";
|
|
15208
|
-
import { statSync as
|
|
15255
|
+
import { statSync as statSync7, existsSync as existsSync25, writeFileSync as writeFileSync16, mkdirSync as mkdirSync11 } from "node:fs";
|
|
15209
15256
|
function emitJson2(data) {
|
|
15210
15257
|
console.log(JSON.stringify(data, null, 2));
|
|
15211
15258
|
}
|
|
@@ -15222,11 +15269,11 @@ async function runFileShare(filePath, opts) {
|
|
|
15222
15269
|
return EXIT.INVALID_ARGS;
|
|
15223
15270
|
}
|
|
15224
15271
|
const absPath = resolvePath(filePath);
|
|
15225
|
-
if (!
|
|
15272
|
+
if (!existsSync25(absPath)) {
|
|
15226
15273
|
render.err(`File not found: ${absPath}`);
|
|
15227
15274
|
return EXIT.INVALID_ARGS;
|
|
15228
15275
|
}
|
|
15229
|
-
const stat =
|
|
15276
|
+
const stat = statSync7(absPath);
|
|
15230
15277
|
if (!stat.isFile()) {
|
|
15231
15278
|
render.err(`Not a regular file: ${absPath}`);
|
|
15232
15279
|
return EXIT.INVALID_ARGS;
|
|
@@ -15302,7 +15349,7 @@ async function runFileGet(fileId, opts) {
|
|
|
15302
15349
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
15303
15350
|
const outPath = opts.out ? resolvePath(opts.out) : resolvePath(process.cwd(), meta.name);
|
|
15304
15351
|
mkdirSync11(dirname9(outPath), { recursive: true });
|
|
15305
|
-
|
|
15352
|
+
writeFileSync16(outPath, buf);
|
|
15306
15353
|
if (opts.json) {
|
|
15307
15354
|
emitJson2({ fileId, name: meta.name, savedTo: outPath, sizeBytes: buf.length });
|
|
15308
15355
|
} else {
|
|
@@ -15912,7 +15959,7 @@ __export(exports_bridge, {
|
|
|
15912
15959
|
runBridge: () => runBridge,
|
|
15913
15960
|
bridgeConfigTemplate: () => bridgeConfigTemplate
|
|
15914
15961
|
});
|
|
15915
|
-
import { readFileSync as
|
|
15962
|
+
import { readFileSync as readFileSync20, existsSync as existsSync26 } from "node:fs";
|
|
15916
15963
|
function parseConfig(text) {
|
|
15917
15964
|
const trimmed = text.trim();
|
|
15918
15965
|
if (trimmed.startsWith("{"))
|
|
@@ -15956,13 +16003,13 @@ async function runBridge(configPath) {
|
|
|
15956
16003
|
render.err("Usage: claudemesh bridge run <config.yaml>");
|
|
15957
16004
|
return EXIT.INVALID_ARGS;
|
|
15958
16005
|
}
|
|
15959
|
-
if (!
|
|
16006
|
+
if (!existsSync26(configPath)) {
|
|
15960
16007
|
render.err(`config file not found: ${configPath}`);
|
|
15961
16008
|
return EXIT.NOT_FOUND;
|
|
15962
16009
|
}
|
|
15963
16010
|
let cfg;
|
|
15964
16011
|
try {
|
|
15965
|
-
cfg = parseConfig(
|
|
16012
|
+
cfg = parseConfig(readFileSync20(configPath, "utf-8"));
|
|
15966
16013
|
} catch (e) {
|
|
15967
16014
|
render.err(`failed to parse ${configPath}: ${e instanceof Error ? e.message : String(e)}`);
|
|
15968
16015
|
return EXIT.INVALID_ARGS;
|
|
@@ -16936,11 +16983,11 @@ import {
|
|
|
16936
16983
|
ListResourcesRequestSchema,
|
|
16937
16984
|
ReadResourceRequestSchema
|
|
16938
16985
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
16939
|
-
import { existsSync as
|
|
16986
|
+
import { existsSync as existsSync27 } from "node:fs";
|
|
16940
16987
|
import { request as httpRequest2 } from "node:http";
|
|
16941
16988
|
async function daemonReady() {
|
|
16942
16989
|
for (let i = 0;i < DAEMON_BOOT_RETRIES; i++) {
|
|
16943
|
-
if (
|
|
16990
|
+
if (existsSync27(DAEMON_PATHS.SOCK_FILE))
|
|
16944
16991
|
return true;
|
|
16945
16992
|
await new Promise((r) => setTimeout(r, DAEMON_BOOT_RETRY_MS));
|
|
16946
16993
|
}
|
|
@@ -18017,10 +18064,12 @@ async function gate(ctx, opts) {
|
|
|
18017
18064
|
}
|
|
18018
18065
|
|
|
18019
18066
|
// src/entrypoints/cli.ts
|
|
18067
|
+
init_policy();
|
|
18020
18068
|
init_styles();
|
|
18021
18069
|
installSignalHandlers();
|
|
18022
18070
|
installErrorHandlers();
|
|
18023
18071
|
var { command, positionals, flags } = parseArgv(process.argv);
|
|
18072
|
+
setDaemonPolicy(policyFromFlags(flags));
|
|
18024
18073
|
function resolveApprovalMode() {
|
|
18025
18074
|
const raw = flags["approval-mode"] ?? process.env.CLAUDEMESH_APPROVAL_MODE ?? null;
|
|
18026
18075
|
if (raw === "plan" || raw === "read-only" || raw === "write" || raw === "yolo")
|
|
@@ -18197,6 +18246,8 @@ Flags
|
|
|
18197
18246
|
--policy <path> override policy file
|
|
18198
18247
|
-y, --yes skip confirmations (= --approval-mode yolo)
|
|
18199
18248
|
-q, --quiet suppress non-essential output
|
|
18249
|
+
--strict require daemon for broker-touching verbs (no cold-path fallback)
|
|
18250
|
+
--no-daemon skip daemon entirely; open broker WS directly (CI / sandboxed scripts)
|
|
18200
18251
|
`;
|
|
18201
18252
|
function colorizeHelp(raw) {
|
|
18202
18253
|
const lines = raw.split(`
|
|
@@ -19238,4 +19289,4 @@ main().catch((err) => {
|
|
|
19238
19289
|
process.exit(EXIT.INTERNAL_ERROR);
|
|
19239
19290
|
});
|
|
19240
19291
|
|
|
19241
|
-
//# debugId=
|
|
19292
|
+
//# debugId=04E4A5313AE4F0EA64756E2164756E21
|