claudemesh-cli 1.0.1 → 1.0.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.
- package/dist/entrypoints/cli.js +361 -325
- package/dist/entrypoints/cli.js.map +21 -21
- package/dist/entrypoints/mcp.js +14 -2
- package/dist/entrypoints/mcp.js.map +3 -3
- package/package.json +1 -1
package/dist/entrypoints/cli.js
CHANGED
|
@@ -88,7 +88,7 @@ __export(exports_urls, {
|
|
|
88
88
|
VERSION: () => VERSION,
|
|
89
89
|
URLS: () => URLS
|
|
90
90
|
});
|
|
91
|
-
var URLS, VERSION = "1.0.
|
|
91
|
+
var URLS, VERSION = "1.0.3", env;
|
|
92
92
|
var init_urls = __esm(() => {
|
|
93
93
|
URLS = {
|
|
94
94
|
BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
|
|
@@ -3170,6 +3170,75 @@ var init_facade8 = __esm(() => {
|
|
|
3170
3170
|
init_errors3();
|
|
3171
3171
|
});
|
|
3172
3172
|
|
|
3173
|
+
// src/ui/render.ts
|
|
3174
|
+
var OUT, ERR, INDENT = " ", render;
|
|
3175
|
+
var init_render = __esm(() => {
|
|
3176
|
+
init_styles();
|
|
3177
|
+
OUT = process.stdout;
|
|
3178
|
+
ERR = process.stderr;
|
|
3179
|
+
render = {
|
|
3180
|
+
blank() {
|
|
3181
|
+
OUT.write(`
|
|
3182
|
+
`);
|
|
3183
|
+
},
|
|
3184
|
+
ok(msg, detail) {
|
|
3185
|
+
const d = detail ? ` ${dim("(" + detail + ")")}` : "";
|
|
3186
|
+
OUT.write(`${INDENT}${green(icons.check)} ${msg}${d}
|
|
3187
|
+
`);
|
|
3188
|
+
},
|
|
3189
|
+
warn(msg, hint) {
|
|
3190
|
+
OUT.write(`${INDENT}${yellow(icons.warn)} ${msg}
|
|
3191
|
+
`);
|
|
3192
|
+
if (hint)
|
|
3193
|
+
OUT.write(`${INDENT} ${dim(hint)}
|
|
3194
|
+
`);
|
|
3195
|
+
},
|
|
3196
|
+
err(msg, hint) {
|
|
3197
|
+
ERR.write(`${INDENT}${red(icons.cross)} ${msg}
|
|
3198
|
+
`);
|
|
3199
|
+
if (hint)
|
|
3200
|
+
ERR.write(`${INDENT} ${dim(hint)}
|
|
3201
|
+
`);
|
|
3202
|
+
},
|
|
3203
|
+
info(msg) {
|
|
3204
|
+
OUT.write(`${INDENT}${msg}
|
|
3205
|
+
`);
|
|
3206
|
+
},
|
|
3207
|
+
section(title) {
|
|
3208
|
+
OUT.write(`
|
|
3209
|
+
${INDENT}${dim("—")} ${clay(title)}
|
|
3210
|
+
|
|
3211
|
+
`);
|
|
3212
|
+
},
|
|
3213
|
+
heading(title) {
|
|
3214
|
+
OUT.write(`${INDENT}${bold(title)}
|
|
3215
|
+
`);
|
|
3216
|
+
},
|
|
3217
|
+
kv(pairs, opts) {
|
|
3218
|
+
const pad = opts?.padTo ?? Math.max(...pairs.map(([k]) => k.length)) + 2;
|
|
3219
|
+
for (const [k, v] of pairs) {
|
|
3220
|
+
OUT.write(`${INDENT}${dim(k.padEnd(pad, " "))}${v}
|
|
3221
|
+
`);
|
|
3222
|
+
}
|
|
3223
|
+
},
|
|
3224
|
+
code(snippet) {
|
|
3225
|
+
for (const line of snippet.split(`
|
|
3226
|
+
`)) {
|
|
3227
|
+
OUT.write(`${INDENT} ${cyan(line)}
|
|
3228
|
+
`);
|
|
3229
|
+
}
|
|
3230
|
+
},
|
|
3231
|
+
link(url) {
|
|
3232
|
+
OUT.write(`${INDENT}${clay(url)}
|
|
3233
|
+
`);
|
|
3234
|
+
},
|
|
3235
|
+
hint(msg) {
|
|
3236
|
+
OUT.write(`${INDENT}${dim(icons.arrow + " " + msg)}
|
|
3237
|
+
`);
|
|
3238
|
+
}
|
|
3239
|
+
};
|
|
3240
|
+
});
|
|
3241
|
+
|
|
3173
3242
|
// src/ui/screen.ts
|
|
3174
3243
|
import { createInterface as createInterface2 } from "node:readline";
|
|
3175
3244
|
function termSize() {
|
|
@@ -3526,7 +3595,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
3526
3595
|
claudeArgs: claudePassthrough
|
|
3527
3596
|
};
|
|
3528
3597
|
if (args.joinLink) {
|
|
3529
|
-
|
|
3598
|
+
render.info(dim("Joining mesh…"));
|
|
3530
3599
|
const invite = await parseInviteLink(args.joinLink);
|
|
3531
3600
|
const keypair = await generateKeypair();
|
|
3532
3601
|
const displayName2 = args.name ?? process.env.USER ?? process.env.USERNAME ?? hostname2();
|
|
@@ -3551,7 +3620,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
3551
3620
|
});
|
|
3552
3621
|
const { writeConfig: writeConfig2 } = await Promise.resolve().then(() => (init_facade(), exports_facade));
|
|
3553
3622
|
writeConfig2(config2);
|
|
3554
|
-
|
|
3623
|
+
render.ok(`joined ${bold(invite.payload.mesh_slug)}`, enroll.alreadyMember ? "already member" : undefined);
|
|
3555
3624
|
}
|
|
3556
3625
|
const config = readConfig();
|
|
3557
3626
|
let justSynced = false;
|
|
@@ -3622,14 +3691,14 @@ async function runLaunch(flags, rawArgs) {
|
|
|
3622
3691
|
`);
|
|
3623
3692
|
}
|
|
3624
3693
|
if (config.meshes.length === 0) {
|
|
3625
|
-
|
|
3694
|
+
render.err("No meshes joined.", "Run `claudemesh join <url>` or use --join <url>.");
|
|
3626
3695
|
process.exit(1);
|
|
3627
3696
|
}
|
|
3628
3697
|
let mesh;
|
|
3629
3698
|
if (args.meshSlug) {
|
|
3630
3699
|
const found = config.meshes.find((m) => m.slug === args.meshSlug);
|
|
3631
3700
|
if (!found) {
|
|
3632
|
-
|
|
3701
|
+
render.err(`Mesh "${args.meshSlug}" not found.`, `Joined: ${config.meshes.map((m) => m.slug).join(", ")}`);
|
|
3633
3702
|
process.exit(1);
|
|
3634
3703
|
}
|
|
3635
3704
|
mesh = found;
|
|
@@ -3852,9 +3921,9 @@ async function runLaunch(flags, rawArgs) {
|
|
|
3852
3921
|
if (result.error) {
|
|
3853
3922
|
const err = result.error;
|
|
3854
3923
|
if (err.code === "ENOENT") {
|
|
3855
|
-
|
|
3924
|
+
render.err("`claude` not found on PATH.", "Install Claude Code first.");
|
|
3856
3925
|
} else {
|
|
3857
|
-
|
|
3926
|
+
render.err(`failed to launch claude: ${err.message}`);
|
|
3858
3927
|
}
|
|
3859
3928
|
process.exit(1);
|
|
3860
3929
|
}
|
|
@@ -3869,6 +3938,7 @@ var init_launch = __esm(() => {
|
|
|
3869
3938
|
init_facade6();
|
|
3870
3939
|
init_facade5();
|
|
3871
3940
|
init_facade8();
|
|
3941
|
+
init_render();
|
|
3872
3942
|
init_styles();
|
|
3873
3943
|
init_screen();
|
|
3874
3944
|
init_spinner();
|
|
@@ -3918,13 +3988,13 @@ function prompt(question) {
|
|
|
3918
3988
|
});
|
|
3919
3989
|
}
|
|
3920
3990
|
async function loginWithToken() {
|
|
3921
|
-
|
|
3922
|
-
Paste a token from ${dim(URLS.API_BASE + "/token")}`);
|
|
3923
|
-
|
|
3924
|
-
|
|
3991
|
+
render.blank();
|
|
3992
|
+
render.info(`Paste a token from ${dim(URLS.API_BASE + "/token")}`);
|
|
3993
|
+
render.info(dim("Generate one in your browser, then paste it here."));
|
|
3994
|
+
render.blank();
|
|
3925
3995
|
const token = await prompt(" Token: ");
|
|
3926
3996
|
if (!token) {
|
|
3927
|
-
|
|
3997
|
+
render.err("No token provided.");
|
|
3928
3998
|
return EXIT.AUTH_FAILED;
|
|
3929
3999
|
}
|
|
3930
4000
|
let user = { id: "", display_name: "", email: "" };
|
|
@@ -3933,7 +4003,7 @@ async function loginWithToken() {
|
|
|
3933
4003
|
if (parts[1]) {
|
|
3934
4004
|
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
|
|
3935
4005
|
if (payload.exp && payload.exp < Date.now() / 1000) {
|
|
3936
|
-
|
|
4006
|
+
render.err("Token expired.", "Generate a new one.");
|
|
3937
4007
|
return EXIT.AUTH_FAILED;
|
|
3938
4008
|
}
|
|
3939
4009
|
user = {
|
|
@@ -3943,11 +4013,11 @@ async function loginWithToken() {
|
|
|
3943
4013
|
};
|
|
3944
4014
|
}
|
|
3945
4015
|
} catch {
|
|
3946
|
-
|
|
4016
|
+
render.err("Invalid token format.");
|
|
3947
4017
|
return EXIT.AUTH_FAILED;
|
|
3948
4018
|
}
|
|
3949
4019
|
storeToken({ session_token: token, user, token_source: "manual" });
|
|
3950
|
-
|
|
4020
|
+
render.ok(`signed in as ${bold(user.display_name || user.email || "user")}`);
|
|
3951
4021
|
return EXIT.SUCCESS;
|
|
3952
4022
|
}
|
|
3953
4023
|
async function syncMeshes(token) {
|
|
@@ -3955,7 +4025,7 @@ async function syncMeshes(token) {
|
|
|
3955
4025
|
const meshes = await exports_my.getMeshes(token);
|
|
3956
4026
|
if (meshes.length > 0) {
|
|
3957
4027
|
const names = meshes.map((m) => m.slug).join(", ");
|
|
3958
|
-
|
|
4028
|
+
render.ok(`synced ${meshes.length} mesh${meshes.length === 1 ? "" : "es"}`, names);
|
|
3959
4029
|
}
|
|
3960
4030
|
} catch {}
|
|
3961
4031
|
}
|
|
@@ -3963,23 +4033,27 @@ async function login() {
|
|
|
3963
4033
|
const existing = getStoredToken();
|
|
3964
4034
|
if (existing) {
|
|
3965
4035
|
const name = existing.user.display_name || existing.user.email || "unknown";
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
4036
|
+
render.blank();
|
|
4037
|
+
render.info(`Already signed in as ${bold(name)}.`);
|
|
4038
|
+
render.blank();
|
|
4039
|
+
process.stdout.write(` ${bold("1)")} Continue as ${name}
|
|
4040
|
+
`);
|
|
4041
|
+
process.stdout.write(` ${bold("2)")} Sign in via browser
|
|
4042
|
+
`);
|
|
4043
|
+
process.stdout.write(` ${bold("3)")} Paste a token from ${dim("claudemesh.com/token")}
|
|
4044
|
+
`);
|
|
4045
|
+
process.stdout.write(` ${bold("4)")} Sign out
|
|
4046
|
+
`);
|
|
4047
|
+
render.blank();
|
|
3974
4048
|
const choice = await prompt(" Choice [1]: ") || "1";
|
|
3975
4049
|
if (choice === "1") {
|
|
3976
|
-
|
|
3977
|
-
|
|
4050
|
+
render.blank();
|
|
4051
|
+
render.ok(`continuing as ${bold(name)}`);
|
|
3978
4052
|
return EXIT.SUCCESS;
|
|
3979
4053
|
}
|
|
3980
4054
|
if (choice === "4") {
|
|
3981
4055
|
clearToken();
|
|
3982
|
-
|
|
4056
|
+
render.ok("signed out");
|
|
3983
4057
|
return EXIT.SUCCESS;
|
|
3984
4058
|
}
|
|
3985
4059
|
if (choice === "3") {
|
|
@@ -3987,14 +4061,16 @@ async function login() {
|
|
|
3987
4061
|
return loginWithToken();
|
|
3988
4062
|
}
|
|
3989
4063
|
clearToken();
|
|
3990
|
-
|
|
4064
|
+
render.info(dim("Signing in…"));
|
|
3991
4065
|
} else {
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
4066
|
+
render.blank();
|
|
4067
|
+
render.heading(`${bold("claudemesh")} — sign in to connect your terminal`);
|
|
4068
|
+
render.blank();
|
|
4069
|
+
process.stdout.write(` ${bold("1)")} Sign in via browser ${dim("(opens automatically)")}
|
|
4070
|
+
`);
|
|
4071
|
+
process.stdout.write(` ${bold("2)")} Paste a token from ${dim("claudemesh.com/token")}
|
|
4072
|
+
`);
|
|
4073
|
+
render.blank();
|
|
3998
4074
|
const choice = await prompt(" Choice [1]: ") || "1";
|
|
3999
4075
|
if (choice === "2") {
|
|
4000
4076
|
return loginWithToken();
|
|
@@ -4002,91 +4078,23 @@ async function login() {
|
|
|
4002
4078
|
}
|
|
4003
4079
|
try {
|
|
4004
4080
|
const result = await loginWithDeviceCode();
|
|
4005
|
-
|
|
4081
|
+
render.ok(`signed in as ${bold(result.user.display_name)}`);
|
|
4006
4082
|
await syncMeshes(result.session_token);
|
|
4007
4083
|
return EXIT.SUCCESS;
|
|
4008
4084
|
} catch (err) {
|
|
4009
|
-
|
|
4085
|
+
render.err(`Login failed: ${err instanceof Error ? err.message : err}`);
|
|
4010
4086
|
return EXIT.AUTH_FAILED;
|
|
4011
4087
|
}
|
|
4012
4088
|
}
|
|
4013
4089
|
var init_login = __esm(() => {
|
|
4014
4090
|
init_facade6();
|
|
4015
4091
|
init_facade3();
|
|
4092
|
+
init_render();
|
|
4016
4093
|
init_styles();
|
|
4017
4094
|
init_exit_codes();
|
|
4018
4095
|
init_urls();
|
|
4019
4096
|
});
|
|
4020
4097
|
|
|
4021
|
-
// src/ui/render.ts
|
|
4022
|
-
var OUT, ERR, INDENT = " ", render;
|
|
4023
|
-
var init_render = __esm(() => {
|
|
4024
|
-
init_styles();
|
|
4025
|
-
OUT = process.stdout;
|
|
4026
|
-
ERR = process.stderr;
|
|
4027
|
-
render = {
|
|
4028
|
-
blank() {
|
|
4029
|
-
OUT.write(`
|
|
4030
|
-
`);
|
|
4031
|
-
},
|
|
4032
|
-
ok(msg, detail) {
|
|
4033
|
-
const d = detail ? ` ${dim("(" + detail + ")")}` : "";
|
|
4034
|
-
OUT.write(`${INDENT}${green(icons.check)} ${msg}${d}
|
|
4035
|
-
`);
|
|
4036
|
-
},
|
|
4037
|
-
warn(msg, hint) {
|
|
4038
|
-
OUT.write(`${INDENT}${yellow(icons.warn)} ${msg}
|
|
4039
|
-
`);
|
|
4040
|
-
if (hint)
|
|
4041
|
-
OUT.write(`${INDENT} ${dim(hint)}
|
|
4042
|
-
`);
|
|
4043
|
-
},
|
|
4044
|
-
err(msg, hint) {
|
|
4045
|
-
ERR.write(`${INDENT}${red(icons.cross)} ${msg}
|
|
4046
|
-
`);
|
|
4047
|
-
if (hint)
|
|
4048
|
-
ERR.write(`${INDENT} ${dim(hint)}
|
|
4049
|
-
`);
|
|
4050
|
-
},
|
|
4051
|
-
info(msg) {
|
|
4052
|
-
OUT.write(`${INDENT}${msg}
|
|
4053
|
-
`);
|
|
4054
|
-
},
|
|
4055
|
-
section(title) {
|
|
4056
|
-
OUT.write(`
|
|
4057
|
-
${INDENT}${dim("—")} ${clay(title)}
|
|
4058
|
-
|
|
4059
|
-
`);
|
|
4060
|
-
},
|
|
4061
|
-
heading(title) {
|
|
4062
|
-
OUT.write(`${INDENT}${bold(title)}
|
|
4063
|
-
`);
|
|
4064
|
-
},
|
|
4065
|
-
kv(pairs, opts) {
|
|
4066
|
-
const pad = opts?.padTo ?? Math.max(...pairs.map(([k]) => k.length)) + 2;
|
|
4067
|
-
for (const [k, v] of pairs) {
|
|
4068
|
-
OUT.write(`${INDENT}${dim(k.padEnd(pad, " "))}${v}
|
|
4069
|
-
`);
|
|
4070
|
-
}
|
|
4071
|
-
},
|
|
4072
|
-
code(snippet) {
|
|
4073
|
-
for (const line of snippet.split(`
|
|
4074
|
-
`)) {
|
|
4075
|
-
OUT.write(`${INDENT} ${cyan(line)}
|
|
4076
|
-
`);
|
|
4077
|
-
}
|
|
4078
|
-
},
|
|
4079
|
-
link(url) {
|
|
4080
|
-
OUT.write(`${INDENT}${clay(url)}
|
|
4081
|
-
`);
|
|
4082
|
-
},
|
|
4083
|
-
hint(msg) {
|
|
4084
|
-
OUT.write(`${INDENT}${dim(icons.arrow + " " + msg)}
|
|
4085
|
-
`);
|
|
4086
|
-
}
|
|
4087
|
-
};
|
|
4088
|
-
});
|
|
4089
|
-
|
|
4090
4098
|
// src/commands/welcome.ts
|
|
4091
4099
|
var exports_welcome = {};
|
|
4092
4100
|
__export(exports_welcome, {
|
|
@@ -4251,17 +4259,17 @@ __export(exports_new, {
|
|
|
4251
4259
|
});
|
|
4252
4260
|
async function newMesh(name, opts) {
|
|
4253
4261
|
if (!name) {
|
|
4254
|
-
|
|
4262
|
+
render.err("Usage: claudemesh create <name>");
|
|
4255
4263
|
return EXIT.INVALID_ARGS;
|
|
4256
4264
|
}
|
|
4257
4265
|
if (!getStoredToken()) {
|
|
4258
|
-
|
|
4259
|
-
|
|
4266
|
+
render.info(dim("not signed in — starting login…"));
|
|
4267
|
+
render.blank();
|
|
4260
4268
|
const { login: login2 } = await Promise.resolve().then(() => (init_login(), exports_login));
|
|
4261
4269
|
const loginResult = await login2();
|
|
4262
4270
|
if (loginResult !== EXIT.SUCCESS)
|
|
4263
4271
|
return loginResult;
|
|
4264
|
-
|
|
4272
|
+
render.blank();
|
|
4265
4273
|
}
|
|
4266
4274
|
try {
|
|
4267
4275
|
const result = await createMesh2(name, {
|
|
@@ -4270,22 +4278,24 @@ async function newMesh(name, opts) {
|
|
|
4270
4278
|
});
|
|
4271
4279
|
if (opts.json) {
|
|
4272
4280
|
console.log(JSON.stringify({ schema_version: "1.0", ...result }, null, 2));
|
|
4273
|
-
|
|
4274
|
-
console.log(`
|
|
4275
|
-
${green(icons.check)} Created "${result.slug}" (id: ${result.id})`);
|
|
4276
|
-
console.log(` ${green(icons.check)} You're the owner`);
|
|
4277
|
-
console.log(` ${green(icons.check)} Joined locally`);
|
|
4278
|
-
console.log(`
|
|
4279
|
-
Share with: claudemesh mesh share
|
|
4280
|
-
`);
|
|
4281
|
+
return EXIT.SUCCESS;
|
|
4281
4282
|
}
|
|
4283
|
+
render.section(`created ${bold(result.slug)}`);
|
|
4284
|
+
render.kv([
|
|
4285
|
+
["id", dim(result.id)],
|
|
4286
|
+
["role", clay("owner")],
|
|
4287
|
+
["local", "joined"]
|
|
4288
|
+
]);
|
|
4289
|
+
render.blank();
|
|
4290
|
+
render.hint(`share with: ${bold("claudemesh share")}`);
|
|
4291
|
+
render.blank();
|
|
4282
4292
|
return EXIT.SUCCESS;
|
|
4283
4293
|
} catch (err) {
|
|
4284
4294
|
const msg = err instanceof Error ? err.message : String(err);
|
|
4285
4295
|
if (msg.includes("409") || msg.includes("already exists")) {
|
|
4286
|
-
|
|
4296
|
+
render.err("A mesh with this name already exists.", "Try a different name.");
|
|
4287
4297
|
} else {
|
|
4288
|
-
|
|
4298
|
+
render.err(`Failed: ${msg}`);
|
|
4289
4299
|
}
|
|
4290
4300
|
return EXIT.INTERNAL_ERROR;
|
|
4291
4301
|
}
|
|
@@ -4293,6 +4303,7 @@ async function newMesh(name, opts) {
|
|
|
4293
4303
|
var init_new = __esm(() => {
|
|
4294
4304
|
init_facade10();
|
|
4295
4305
|
init_facade6();
|
|
4306
|
+
init_render();
|
|
4296
4307
|
init_styles();
|
|
4297
4308
|
init_exit_codes();
|
|
4298
4309
|
});
|
|
@@ -4737,24 +4748,20 @@ async function runList() {
|
|
|
4737
4748
|
const serverSlugs = new Set(serverMeshes.map((m) => m.slug));
|
|
4738
4749
|
const allSlugs = new Set([...localSlugs, ...serverSlugs]);
|
|
4739
4750
|
if (allSlugs.size === 0) {
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
`);
|
|
4743
|
-
|
|
4744
|
-
console.log(` Join one: claudemesh mesh add <invite-url>
|
|
4745
|
-
`);
|
|
4751
|
+
render.section("no meshes yet");
|
|
4752
|
+
render.info(`${dim("create one:")} ${bold("claudemesh create")} ${clay("<name>")}`);
|
|
4753
|
+
render.info(`${dim("join one:")} ${bold("claudemesh")} ${clay("<invite-url>")}`);
|
|
4754
|
+
render.blank();
|
|
4746
4755
|
return;
|
|
4747
4756
|
}
|
|
4748
|
-
|
|
4749
|
-
Your meshes:
|
|
4750
|
-
`);
|
|
4757
|
+
render.section(`your meshes (${allSlugs.size})`);
|
|
4751
4758
|
for (const slug of allSlugs) {
|
|
4752
4759
|
const local = config.meshes.find((m) => m.slug === slug);
|
|
4753
4760
|
const server = serverMeshes.find((m) => m.slug === slug);
|
|
4754
4761
|
const name = server?.name ?? local?.name ?? slug;
|
|
4755
4762
|
const role = server?.role ?? "member";
|
|
4756
4763
|
const isOwner = server?.is_owner ?? false;
|
|
4757
|
-
const roleLabel = isOwner ? "owner" : role;
|
|
4764
|
+
const roleLabel = isOwner ? clay("owner") : dim(role);
|
|
4758
4765
|
const memberCount = server?.member_count;
|
|
4759
4766
|
const activePeers = server?.active_peers ?? 0;
|
|
4760
4767
|
const inLocal = localSlugs.has(slug);
|
|
@@ -4773,15 +4780,18 @@ async function runList() {
|
|
|
4773
4780
|
}
|
|
4774
4781
|
const memberInfo = memberCount ? dim(`${memberCount} member${memberCount !== 1 ? "s" : ""}`) : "";
|
|
4775
4782
|
const parts = [roleLabel, memberInfo, status].filter(Boolean);
|
|
4776
|
-
|
|
4777
|
-
|
|
4783
|
+
process.stdout.write(` ${icon} ${bold(name)} ${dim(slug)}
|
|
4784
|
+
`);
|
|
4785
|
+
process.stdout.write(` ${parts.join(dim(" · "))}
|
|
4786
|
+
`);
|
|
4778
4787
|
}
|
|
4779
|
-
|
|
4788
|
+
process.stdout.write(`
|
|
4789
|
+
`);
|
|
4780
4790
|
if (serverMeshes.some((m) => !localSlugs.has(m.slug))) {
|
|
4781
|
-
|
|
4791
|
+
render.hint(`${dim("○")} = server only — run ${bold("claudemesh join")} to use locally`);
|
|
4782
4792
|
}
|
|
4783
|
-
|
|
4784
|
-
|
|
4793
|
+
render.hint(`config: ${dim(getConfigPath())}`);
|
|
4794
|
+
render.blank();
|
|
4785
4795
|
}
|
|
4786
4796
|
var BROKER_HTTP4;
|
|
4787
4797
|
var init_list2 = __esm(() => {
|
|
@@ -4790,6 +4800,7 @@ var init_list2 = __esm(() => {
|
|
|
4790
4800
|
init_facade3();
|
|
4791
4801
|
init_urls();
|
|
4792
4802
|
init_styles();
|
|
4803
|
+
init_render();
|
|
4793
4804
|
BROKER_HTTP4 = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
|
|
4794
4805
|
});
|
|
4795
4806
|
|
|
@@ -4816,11 +4827,12 @@ function getUserId(token) {
|
|
|
4816
4827
|
return "";
|
|
4817
4828
|
}
|
|
4818
4829
|
}
|
|
4819
|
-
async function isOwner(slug,
|
|
4830
|
+
async function isOwner(slug, auth) {
|
|
4820
4831
|
try {
|
|
4821
4832
|
const res = await request({
|
|
4822
|
-
path: `/cli/meshes
|
|
4823
|
-
baseUrl: BROKER_HTTP5
|
|
4833
|
+
path: `/cli/meshes`,
|
|
4834
|
+
baseUrl: BROKER_HTTP5,
|
|
4835
|
+
token: auth.session_token
|
|
4824
4836
|
});
|
|
4825
4837
|
return res.meshes?.find((m) => m.slug === slug)?.is_owner ?? false;
|
|
4826
4838
|
} catch {
|
|
@@ -4831,86 +4843,88 @@ async function deleteMesh(slug, opts = {}) {
|
|
|
4831
4843
|
const config = readConfig();
|
|
4832
4844
|
if (!slug) {
|
|
4833
4845
|
if (config.meshes.length === 0) {
|
|
4834
|
-
|
|
4846
|
+
render.err("No meshes to remove.");
|
|
4835
4847
|
return EXIT.NOT_FOUND;
|
|
4836
4848
|
}
|
|
4837
|
-
|
|
4838
|
-
Select mesh to remove:
|
|
4839
|
-
`);
|
|
4849
|
+
render.section("select mesh to remove");
|
|
4840
4850
|
config.meshes.forEach((m, i) => {
|
|
4841
|
-
|
|
4851
|
+
process.stdout.write(` ${bold(String(i + 1) + ")")} ${clay(m.slug)} ${dim("(" + m.name + ")")}
|
|
4852
|
+
`);
|
|
4842
4853
|
});
|
|
4843
|
-
|
|
4844
|
-
const choice = await prompt3("
|
|
4854
|
+
render.blank();
|
|
4855
|
+
const choice = await prompt3(` ${dim("choice:")} `);
|
|
4845
4856
|
const idx = parseInt(choice, 10) - 1;
|
|
4846
4857
|
if (idx < 0 || idx >= config.meshes.length) {
|
|
4847
|
-
|
|
4858
|
+
render.info(dim("cancelled."));
|
|
4848
4859
|
return EXIT.USER_CANCELLED;
|
|
4849
4860
|
}
|
|
4850
4861
|
slug = config.meshes[idx].slug;
|
|
4851
4862
|
}
|
|
4852
4863
|
const auth = getStoredToken();
|
|
4853
4864
|
const userId = auth ? getUserId(auth.session_token) : "";
|
|
4854
|
-
const ownerCheck =
|
|
4865
|
+
const ownerCheck = auth ? await isOwner(slug, auth) : false;
|
|
4855
4866
|
if (!opts.yes) {
|
|
4856
|
-
|
|
4857
|
-
${bold(slug)}
|
|
4858
|
-
`);
|
|
4867
|
+
render.section(slug);
|
|
4859
4868
|
if (ownerCheck) {
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4869
|
+
process.stdout.write(` ${bold("1)")} remove from this device only ${dim("(keep on server)")}
|
|
4870
|
+
`);
|
|
4871
|
+
process.stdout.write(` ${bold("2)")} ${red("delete everywhere")} ${dim("(removes for all members)")}
|
|
4872
|
+
`);
|
|
4873
|
+
process.stdout.write(` ${bold("3)")} cancel
|
|
4874
|
+
`);
|
|
4875
|
+
render.blank();
|
|
4876
|
+
const choice = await prompt3(` ${dim("choice [1]:")} `) || "1";
|
|
4865
4877
|
if (choice === "3") {
|
|
4866
|
-
|
|
4878
|
+
render.info(dim("cancelled."));
|
|
4867
4879
|
return EXIT.USER_CANCELLED;
|
|
4868
4880
|
}
|
|
4869
4881
|
if (choice === "2") {
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
const confirm = await prompt3(`
|
|
4882
|
+
render.blank();
|
|
4883
|
+
render.warn(`this will delete ${bold(slug)} for all members.`);
|
|
4884
|
+
const confirm = await prompt3(` ${dim(`type "${slug}" to confirm:`)} `);
|
|
4873
4885
|
if (confirm.toLowerCase() !== slug.toLowerCase()) {
|
|
4874
|
-
|
|
4886
|
+
render.info(dim("cancelled."));
|
|
4875
4887
|
return EXIT.USER_CANCELLED;
|
|
4876
4888
|
}
|
|
4877
4889
|
try {
|
|
4878
4890
|
await request({
|
|
4879
4891
|
path: `/cli/mesh/${slug}`,
|
|
4880
4892
|
method: "DELETE",
|
|
4881
|
-
|
|
4882
|
-
|
|
4893
|
+
baseUrl: BROKER_HTTP5,
|
|
4894
|
+
token: auth?.session_token,
|
|
4895
|
+
body: { user_id: userId }
|
|
4883
4896
|
});
|
|
4884
|
-
|
|
4897
|
+
render.ok(`deleted ${bold(slug)} from server.`);
|
|
4885
4898
|
} catch (err) {
|
|
4886
|
-
|
|
4887
|
-
console.error(` ${icons.cross} Server delete failed: ${msg}`);
|
|
4899
|
+
render.err(`server delete failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4888
4900
|
}
|
|
4889
4901
|
leaveMesh(slug);
|
|
4890
|
-
|
|
4902
|
+
render.ok("removed from local config.");
|
|
4891
4903
|
return EXIT.SUCCESS;
|
|
4892
4904
|
}
|
|
4893
4905
|
} else {
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
4906
|
+
process.stdout.write(` ${bold("1)")} remove from this device ${dim("(you can re-add later)")}
|
|
4907
|
+
`);
|
|
4908
|
+
process.stdout.write(` ${bold("2)")} cancel
|
|
4909
|
+
`);
|
|
4910
|
+
if (userId) {
|
|
4911
|
+
render.blank();
|
|
4912
|
+
render.warn("only the mesh owner can delete it from the server.");
|
|
4899
4913
|
}
|
|
4900
|
-
|
|
4901
|
-
const choice = await prompt3("
|
|
4914
|
+
render.blank();
|
|
4915
|
+
const choice = await prompt3(` ${dim("choice [1]:")} `) || "1";
|
|
4902
4916
|
if (choice === "2") {
|
|
4903
|
-
|
|
4917
|
+
render.info(dim("cancelled."));
|
|
4904
4918
|
return EXIT.USER_CANCELLED;
|
|
4905
4919
|
}
|
|
4906
4920
|
}
|
|
4907
4921
|
}
|
|
4908
4922
|
const removed = leaveMesh(slug);
|
|
4909
4923
|
if (removed) {
|
|
4910
|
-
|
|
4911
|
-
|
|
4924
|
+
render.ok(`removed ${bold(slug)} from this device.`);
|
|
4925
|
+
render.hint(`re-add anytime with: ${bold("claudemesh")} ${clay("<invite-url>")}`);
|
|
4912
4926
|
} else {
|
|
4913
|
-
|
|
4927
|
+
render.err(`mesh "${slug}" not found in local config.`);
|
|
4914
4928
|
}
|
|
4915
4929
|
return EXIT.SUCCESS;
|
|
4916
4930
|
}
|
|
@@ -4921,6 +4935,7 @@ var init_delete_mesh = __esm(() => {
|
|
|
4921
4935
|
init_facade6();
|
|
4922
4936
|
init_facade3();
|
|
4923
4937
|
init_urls();
|
|
4938
|
+
init_render();
|
|
4924
4939
|
init_styles();
|
|
4925
4940
|
init_exit_codes();
|
|
4926
4941
|
BROKER_HTTP5 = URLS.BROKER.replace("wss://", "https://").replace("ws://", "http://").replace("/ws", "");
|
|
@@ -6522,12 +6537,10 @@ __export(exports_state, {
|
|
|
6522
6537
|
runStateGet: () => runStateGet
|
|
6523
6538
|
});
|
|
6524
6539
|
async function runStateGet(flags, key) {
|
|
6525
|
-
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
6526
|
-
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
6527
6540
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
|
|
6528
6541
|
const entry = await client.getState(key);
|
|
6529
6542
|
if (!entry) {
|
|
6530
|
-
|
|
6543
|
+
render.info(dim("(not set)"));
|
|
6531
6544
|
return;
|
|
6532
6545
|
}
|
|
6533
6546
|
if (flags.json) {
|
|
@@ -6535,8 +6548,8 @@ async function runStateGet(flags, key) {
|
|
|
6535
6548
|
return;
|
|
6536
6549
|
}
|
|
6537
6550
|
const val = typeof entry.value === "string" ? entry.value : JSON.stringify(entry.value);
|
|
6538
|
-
|
|
6539
|
-
|
|
6551
|
+
render.info(val);
|
|
6552
|
+
render.info(dim(` set by ${entry.updatedBy} at ${new Date(entry.updatedAt).toLocaleString()}`));
|
|
6540
6553
|
});
|
|
6541
6554
|
}
|
|
6542
6555
|
async function runStateSet(flags, key, value) {
|
|
@@ -6548,13 +6561,10 @@ async function runStateSet(flags, key, value) {
|
|
|
6548
6561
|
}
|
|
6549
6562
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
|
|
6550
6563
|
await client.setState(key, parsed);
|
|
6551
|
-
|
|
6564
|
+
render.ok(`${bold(key)} = ${JSON.stringify(parsed)}`);
|
|
6552
6565
|
});
|
|
6553
6566
|
}
|
|
6554
6567
|
async function runStateList(flags) {
|
|
6555
|
-
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
6556
|
-
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
6557
|
-
const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
6558
6568
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client, mesh) => {
|
|
6559
6569
|
const entries = await client.listState();
|
|
6560
6570
|
if (flags.json) {
|
|
@@ -6562,18 +6572,23 @@ async function runStateList(flags) {
|
|
|
6562
6572
|
return;
|
|
6563
6573
|
}
|
|
6564
6574
|
if (entries.length === 0) {
|
|
6565
|
-
|
|
6575
|
+
render.info(dim(`No state on mesh "${mesh.slug}".`));
|
|
6566
6576
|
return;
|
|
6567
6577
|
}
|
|
6578
|
+
render.section(`state (${entries.length})`);
|
|
6568
6579
|
for (const e of entries) {
|
|
6569
6580
|
const val = typeof e.value === "string" ? e.value : JSON.stringify(e.value);
|
|
6570
|
-
|
|
6571
|
-
|
|
6581
|
+
process.stdout.write(` ${bold(e.key)}: ${val}
|
|
6582
|
+
`);
|
|
6583
|
+
process.stdout.write(` ${dim(e.updatedBy + " · " + new Date(e.updatedAt).toLocaleString())}
|
|
6584
|
+
`);
|
|
6572
6585
|
}
|
|
6573
6586
|
});
|
|
6574
6587
|
}
|
|
6575
6588
|
var init_state = __esm(() => {
|
|
6576
6589
|
init_connect();
|
|
6590
|
+
init_render();
|
|
6591
|
+
init_styles();
|
|
6577
6592
|
});
|
|
6578
6593
|
|
|
6579
6594
|
// src/commands/info.ts
|
|
@@ -6637,7 +6652,7 @@ __export(exports_remember, {
|
|
|
6637
6652
|
async function remember(content, opts = {}) {
|
|
6638
6653
|
const client = allClients()[0];
|
|
6639
6654
|
if (!client) {
|
|
6640
|
-
|
|
6655
|
+
render.err("Not connected to any mesh.");
|
|
6641
6656
|
return EXIT.NETWORK_ERROR;
|
|
6642
6657
|
}
|
|
6643
6658
|
const tags = opts.tags?.split(",").map((t) => t.trim()).filter(Boolean);
|
|
@@ -6647,14 +6662,16 @@ async function remember(content, opts = {}) {
|
|
|
6647
6662
|
return EXIT.SUCCESS;
|
|
6648
6663
|
}
|
|
6649
6664
|
if (id) {
|
|
6650
|
-
|
|
6665
|
+
render.ok("remembered", dim(id.slice(0, 8)));
|
|
6651
6666
|
return EXIT.SUCCESS;
|
|
6652
6667
|
}
|
|
6653
|
-
|
|
6668
|
+
render.err("failed to store memory");
|
|
6654
6669
|
return EXIT.INTERNAL_ERROR;
|
|
6655
6670
|
}
|
|
6656
6671
|
var init_remember = __esm(() => {
|
|
6657
6672
|
init_facade8();
|
|
6673
|
+
init_render();
|
|
6674
|
+
init_styles();
|
|
6658
6675
|
init_exit_codes();
|
|
6659
6676
|
});
|
|
6660
6677
|
|
|
@@ -6666,7 +6683,7 @@ __export(exports_recall, {
|
|
|
6666
6683
|
async function recall(query, opts = {}) {
|
|
6667
6684
|
const client = allClients()[0];
|
|
6668
6685
|
if (!client) {
|
|
6669
|
-
|
|
6686
|
+
render.err("Not connected to any mesh.");
|
|
6670
6687
|
return EXIT.NETWORK_ERROR;
|
|
6671
6688
|
}
|
|
6672
6689
|
const memories = await client.recall(query);
|
|
@@ -6675,20 +6692,25 @@ async function recall(query, opts = {}) {
|
|
|
6675
6692
|
return EXIT.SUCCESS;
|
|
6676
6693
|
}
|
|
6677
6694
|
if (memories.length === 0) {
|
|
6678
|
-
|
|
6695
|
+
render.info(dim("no memories found."));
|
|
6679
6696
|
return EXIT.SUCCESS;
|
|
6680
6697
|
}
|
|
6698
|
+
render.section(`memories (${memories.length})`);
|
|
6681
6699
|
for (const m of memories) {
|
|
6682
|
-
const tags = m.tags.length ? dim(` [${m.tags.join(", ")}]`) : "";
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6700
|
+
const tags = m.tags.length ? dim(` [${m.tags.map((t) => clay(t)).join(dim(", "))}]`) : "";
|
|
6701
|
+
process.stdout.write(` ${bold(m.id.slice(0, 8))}${tags}
|
|
6702
|
+
`);
|
|
6703
|
+
process.stdout.write(` ${m.content}
|
|
6704
|
+
`);
|
|
6705
|
+
process.stdout.write(` ${dim(m.rememberedBy + " · " + new Date(m.rememberedAt).toLocaleString())}
|
|
6706
|
+
|
|
6707
|
+
`);
|
|
6687
6708
|
}
|
|
6688
6709
|
return EXIT.SUCCESS;
|
|
6689
6710
|
}
|
|
6690
6711
|
var init_recall = __esm(() => {
|
|
6691
6712
|
init_facade8();
|
|
6713
|
+
init_render();
|
|
6692
6714
|
init_styles();
|
|
6693
6715
|
init_exit_codes();
|
|
6694
6716
|
});
|
|
@@ -6735,9 +6757,6 @@ function parseDeliverAt(flags) {
|
|
|
6735
6757
|
return null;
|
|
6736
6758
|
}
|
|
6737
6759
|
async function runRemind(flags, positional) {
|
|
6738
|
-
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
6739
|
-
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
6740
|
-
const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
6741
6760
|
const action = positional[0];
|
|
6742
6761
|
if (action === "list") {
|
|
6743
6762
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
|
|
@@ -6747,15 +6766,18 @@ async function runRemind(flags, positional) {
|
|
|
6747
6766
|
return;
|
|
6748
6767
|
}
|
|
6749
6768
|
if (scheduled.length === 0) {
|
|
6750
|
-
|
|
6769
|
+
render.info(dim("No pending reminders."));
|
|
6751
6770
|
return;
|
|
6752
6771
|
}
|
|
6772
|
+
render.section(`reminders (${scheduled.length})`);
|
|
6753
6773
|
for (const m of scheduled) {
|
|
6754
6774
|
const when = new Date(m.deliverAt).toLocaleString();
|
|
6755
|
-
const to = m.to === client.getSessionPubkey() ?
|
|
6756
|
-
|
|
6757
|
-
|
|
6758
|
-
|
|
6775
|
+
const to = m.to === client.getSessionPubkey() ? dim("(self)") : m.to;
|
|
6776
|
+
process.stdout.write(` ${bold(m.id.slice(0, 8))} ${dim("→")} ${to} ${dim("at")} ${when}
|
|
6777
|
+
`);
|
|
6778
|
+
process.stdout.write(` ${dim(m.message.slice(0, 80))}
|
|
6779
|
+
|
|
6780
|
+
`);
|
|
6759
6781
|
}
|
|
6760
6782
|
});
|
|
6761
6783
|
return;
|
|
@@ -6763,15 +6785,15 @@ async function runRemind(flags, positional) {
|
|
|
6763
6785
|
if (action === "cancel") {
|
|
6764
6786
|
const id = positional[1];
|
|
6765
6787
|
if (!id) {
|
|
6766
|
-
|
|
6788
|
+
render.err("Usage: claudemesh remind cancel <id>");
|
|
6767
6789
|
process.exit(1);
|
|
6768
6790
|
}
|
|
6769
6791
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
|
|
6770
6792
|
const ok = await client.cancelScheduled(id);
|
|
6771
6793
|
if (ok)
|
|
6772
|
-
|
|
6794
|
+
render.ok(`cancelled ${bold(id.slice(0, 8))}`);
|
|
6773
6795
|
else {
|
|
6774
|
-
|
|
6796
|
+
render.err(`not found or already fired: ${id}`);
|
|
6775
6797
|
process.exit(1);
|
|
6776
6798
|
}
|
|
6777
6799
|
});
|
|
@@ -6779,17 +6801,17 @@ async function runRemind(flags, positional) {
|
|
|
6779
6801
|
}
|
|
6780
6802
|
const message = action ?? positional.join(" ");
|
|
6781
6803
|
if (!message) {
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6804
|
+
render.err("Usage: claudemesh remind <message> --in <duration>");
|
|
6805
|
+
render.info(dim(" claudemesh remind <message> --at <time>"));
|
|
6806
|
+
render.info(dim(' claudemesh remind <message> --cron "0 */2 * * *"'));
|
|
6807
|
+
render.info(dim(" claudemesh remind list"));
|
|
6808
|
+
render.info(dim(" claudemesh remind cancel <id>"));
|
|
6787
6809
|
process.exit(1);
|
|
6788
6810
|
}
|
|
6789
6811
|
const isCron = !!flags.cron;
|
|
6790
6812
|
const deliverAt = isCron ? 0 : parseDeliverAt(flags);
|
|
6791
6813
|
if (!isCron && deliverAt === null) {
|
|
6792
|
-
|
|
6814
|
+
render.err("Specify when", 'use --in <duration> (e.g. "2h", "30m"), --at <time> (e.g. "15:00"), or --cron <expression>');
|
|
6793
6815
|
process.exit(1);
|
|
6794
6816
|
}
|
|
6795
6817
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client) => {
|
|
@@ -6801,7 +6823,7 @@ async function runRemind(flags, positional) {
|
|
|
6801
6823
|
const peers = await client.listPeers();
|
|
6802
6824
|
const match = peers.find((p) => p.displayName.toLowerCase() === flags.to.toLowerCase());
|
|
6803
6825
|
if (!match) {
|
|
6804
|
-
|
|
6826
|
+
render.err(`Peer "${flags.to}" not found`, `online: ${peers.map((p) => p.displayName).join(", ") || "(none)"}`);
|
|
6805
6827
|
process.exit(1);
|
|
6806
6828
|
}
|
|
6807
6829
|
targetSpec = match.pubkey;
|
|
@@ -6811,7 +6833,7 @@ async function runRemind(flags, positional) {
|
|
|
6811
6833
|
}
|
|
6812
6834
|
const result = await client.scheduleMessage(targetSpec, message, deliverAt ?? 0, false, flags.cron);
|
|
6813
6835
|
if (!result) {
|
|
6814
|
-
|
|
6836
|
+
render.err("Broker did not acknowledge — check connection");
|
|
6815
6837
|
process.exit(1);
|
|
6816
6838
|
}
|
|
6817
6839
|
if (flags.json) {
|
|
@@ -6821,15 +6843,17 @@ async function runRemind(flags, positional) {
|
|
|
6821
6843
|
const toLabel = !flags.to || flags.to === "self" ? "yourself" : flags.to;
|
|
6822
6844
|
if (isCron) {
|
|
6823
6845
|
const nextFire = new Date(result.deliverAt).toLocaleString();
|
|
6824
|
-
|
|
6846
|
+
render.ok(`recurring reminder set`, `${result.scheduledId.slice(0, 8)} · ${clay(message)} → ${toLabel} · cron ${flags.cron} · next ${nextFire}`);
|
|
6825
6847
|
} else {
|
|
6826
6848
|
const when = new Date(result.deliverAt).toLocaleString();
|
|
6827
|
-
|
|
6849
|
+
render.ok(`reminder set`, `${result.scheduledId.slice(0, 8)} · ${clay(message)} → ${toLabel} at ${when}`);
|
|
6828
6850
|
}
|
|
6829
6851
|
});
|
|
6830
6852
|
}
|
|
6831
6853
|
var init_remind = __esm(() => {
|
|
6832
6854
|
init_connect();
|
|
6855
|
+
init_render();
|
|
6856
|
+
init_styles();
|
|
6833
6857
|
});
|
|
6834
6858
|
|
|
6835
6859
|
// src/commands/profile.ts
|
|
@@ -6969,20 +6993,21 @@ async function whoami(opts) {
|
|
|
6969
6993
|
return EXIT.SUCCESS;
|
|
6970
6994
|
}
|
|
6971
6995
|
if (!result.signed_in) {
|
|
6972
|
-
|
|
6996
|
+
render.err("Not signed in", "Run `claudemesh login` to sign in.");
|
|
6973
6997
|
return EXIT.AUTH_FAILED;
|
|
6974
6998
|
}
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6999
|
+
render.section("whoami");
|
|
7000
|
+
render.kv([
|
|
7001
|
+
["user", `${bold(result.user.display_name)} ${dim(`(${result.user.email})`)}`],
|
|
7002
|
+
["token", `${result.token_source} ${dim("(~/.claudemesh/auth.json)")}`],
|
|
7003
|
+
...result.meshes ? [["meshes", `${result.meshes.owned} owned · ${result.meshes.guest} guest`]] : []
|
|
7004
|
+
]);
|
|
7005
|
+
render.blank();
|
|
6982
7006
|
return EXIT.SUCCESS;
|
|
6983
7007
|
}
|
|
6984
7008
|
var init_whoami = __esm(() => {
|
|
6985
7009
|
init_facade6();
|
|
7010
|
+
init_render();
|
|
6986
7011
|
init_styles();
|
|
6987
7012
|
init_exit_codes();
|
|
6988
7013
|
});
|
|
@@ -7198,16 +7223,15 @@ function installStatusLine() {
|
|
|
7198
7223
|
function runInstall(args = []) {
|
|
7199
7224
|
const skipHooks = args.includes("--no-hooks");
|
|
7200
7225
|
const wantStatusLine = args.includes("--status-line");
|
|
7201
|
-
|
|
7202
|
-
console.log("------------------");
|
|
7226
|
+
render.section("claudemesh install");
|
|
7203
7227
|
const entry = resolveEntry();
|
|
7204
7228
|
const isBundled = entry.endsWith("/dist/index.js") || entry.endsWith("\\dist\\index.js");
|
|
7205
7229
|
if (!isBundled && !bunAvailable()) {
|
|
7206
|
-
|
|
7230
|
+
render.err("`bun` is not on PATH.", "Install Bun first: https://bun.com");
|
|
7207
7231
|
process.exit(1);
|
|
7208
7232
|
}
|
|
7209
7233
|
if (!existsSync5(entry)) {
|
|
7210
|
-
|
|
7234
|
+
render.err(`MCP entry not found at ${entry}`);
|
|
7211
7235
|
process.exit(1);
|
|
7212
7236
|
}
|
|
7213
7237
|
const desired = buildMcpEntry(entry);
|
|
@@ -7216,56 +7240,53 @@ function runInstall(args = []) {
|
|
|
7216
7240
|
const verifyServers = verify2.mcpServers ?? {};
|
|
7217
7241
|
const stored = verifyServers[MCP_NAME];
|
|
7218
7242
|
if (!stored || !entriesEqual(stored, desired)) {
|
|
7219
|
-
|
|
7243
|
+
render.err("post-write verification failed", `${CLAUDE_CONFIG} may be corrupt`);
|
|
7220
7244
|
process.exit(1);
|
|
7221
7245
|
}
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
console.log(dim2(` config: ${CLAUDE_CONFIG}`));
|
|
7228
|
-
console.log(dim2(` command: ${desired.command}${desired.args?.length ? " " + desired.args.join(" ") : ""}`));
|
|
7246
|
+
render.ok(`MCP server "${bold(MCP_NAME)}" ${action}`);
|
|
7247
|
+
render.kv([
|
|
7248
|
+
["config", dim(CLAUDE_CONFIG)],
|
|
7249
|
+
["command", dim(`${desired.command}${desired.args?.length ? " " + desired.args.join(" ") : ""}`)]
|
|
7250
|
+
]);
|
|
7229
7251
|
try {
|
|
7230
7252
|
const { added, unchanged } = installAllowedTools();
|
|
7231
7253
|
if (added.length > 0) {
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7254
|
+
render.ok(`allowedTools: ${added.length} claudemesh tools pre-approved`, unchanged > 0 ? `${unchanged} already present` : undefined);
|
|
7255
|
+
render.info(dim("This lets claudemesh tools run without --dangerously-skip-permissions."));
|
|
7256
|
+
render.info(dim("Your existing allowedTools entries were preserved."));
|
|
7235
7257
|
} else {
|
|
7236
|
-
|
|
7258
|
+
render.ok(`allowedTools: all ${unchanged} claudemesh tools already pre-approved`);
|
|
7237
7259
|
}
|
|
7238
|
-
|
|
7260
|
+
render.info(dim(` config: ${CLAUDE_SETTINGS}`));
|
|
7239
7261
|
} catch (e) {
|
|
7240
|
-
|
|
7262
|
+
render.warn(`allowedTools update failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
7241
7263
|
}
|
|
7242
7264
|
if (!skipHooks) {
|
|
7243
7265
|
try {
|
|
7244
7266
|
const { added, unchanged } = installHooks();
|
|
7245
7267
|
if (added > 0) {
|
|
7246
|
-
|
|
7268
|
+
render.ok(`Hooks registered (Stop + UserPromptSubmit)`, `${added} added, ${unchanged} already present`);
|
|
7247
7269
|
} else {
|
|
7248
|
-
|
|
7270
|
+
render.ok(`Hooks already registered`, `${unchanged} present`);
|
|
7249
7271
|
}
|
|
7250
|
-
|
|
7272
|
+
render.info(dim(` config: ${CLAUDE_SETTINGS}`));
|
|
7251
7273
|
} catch (e) {
|
|
7252
|
-
|
|
7253
|
-
console.error(" (MCP is still installed — hooks just skip. Retry with --no-hooks to suppress.)");
|
|
7274
|
+
render.warn(`hook registration failed: ${e instanceof Error ? e.message : String(e)}`, "MCP is still installed — hooks just skip. Retry with --no-hooks to suppress.");
|
|
7254
7275
|
}
|
|
7255
7276
|
} else {
|
|
7256
|
-
|
|
7277
|
+
render.info(dim("· Hooks skipped (--no-hooks)"));
|
|
7257
7278
|
}
|
|
7258
7279
|
if (wantStatusLine) {
|
|
7259
7280
|
try {
|
|
7260
7281
|
const { installed } = installStatusLine();
|
|
7261
7282
|
if (installed) {
|
|
7262
|
-
|
|
7263
|
-
|
|
7283
|
+
render.ok(`Claude Code statusLine → ${clay("claudemesh status-line")}`);
|
|
7284
|
+
render.info(dim(" Shows: ◇ <mesh> · <online>/<total> online · <you>"));
|
|
7264
7285
|
} else {
|
|
7265
|
-
|
|
7286
|
+
render.info(dim("· statusLine already set to a custom command — left alone"));
|
|
7266
7287
|
}
|
|
7267
7288
|
} catch (e) {
|
|
7268
|
-
|
|
7289
|
+
render.warn(`statusLine install failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
7269
7290
|
}
|
|
7270
7291
|
}
|
|
7271
7292
|
let hasMeshes = false;
|
|
@@ -7273,57 +7294,58 @@ function runInstall(args = []) {
|
|
|
7273
7294
|
const meshConfig = readConfig();
|
|
7274
7295
|
hasMeshes = meshConfig.meshes.length > 0;
|
|
7275
7296
|
} catch {}
|
|
7276
|
-
|
|
7277
|
-
|
|
7297
|
+
render.blank();
|
|
7298
|
+
render.warn(`${bold("RESTART CLAUDE CODE")} ${yellow("for MCP tools to appear.")}`);
|
|
7278
7299
|
if (!hasMeshes) {
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
|
|
7282
|
-
|
|
7300
|
+
render.blank();
|
|
7301
|
+
render.info(`${yellow("No meshes joined.")} To connect with peers:`);
|
|
7302
|
+
render.info(` ${bold("claudemesh <invite-url>")}${dim(" — joins + launches in one step")}`);
|
|
7303
|
+
render.info(` ${dim("Create one at")} ${bold("https://claudemesh.com/dashboard")}`);
|
|
7283
7304
|
} else {
|
|
7284
|
-
|
|
7285
|
-
|
|
7305
|
+
render.blank();
|
|
7306
|
+
render.info(`Next: ${bold("claudemesh")}${dim(" — launch with your joined mesh")}`);
|
|
7286
7307
|
}
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7308
|
+
render.blank();
|
|
7309
|
+
render.info(dim("Optional:"));
|
|
7310
|
+
render.info(dim(` claudemesh url-handler install # click-to-launch from email`));
|
|
7311
|
+
render.info(dim(` claudemesh install --status-line # live peer count in Claude Code`));
|
|
7312
|
+
render.info(dim(` claudemesh completions zsh # shell completions`));
|
|
7292
7313
|
}
|
|
7293
7314
|
function runUninstall() {
|
|
7294
|
-
|
|
7295
|
-
console.log("--------------------");
|
|
7315
|
+
render.section("claudemesh uninstall");
|
|
7296
7316
|
if (removeMcpServer()) {
|
|
7297
|
-
|
|
7317
|
+
render.ok(`MCP server "${bold(MCP_NAME)}" removed`);
|
|
7298
7318
|
} else {
|
|
7299
|
-
|
|
7319
|
+
render.info(dim(`· MCP server "${MCP_NAME}" not present`));
|
|
7300
7320
|
}
|
|
7301
7321
|
try {
|
|
7302
7322
|
const removed = uninstallAllowedTools();
|
|
7303
7323
|
if (removed > 0) {
|
|
7304
|
-
|
|
7324
|
+
render.ok(`allowedTools: ${removed} claudemesh tools removed`);
|
|
7305
7325
|
} else {
|
|
7306
|
-
|
|
7326
|
+
render.info(dim("· No claudemesh allowedTools to remove"));
|
|
7307
7327
|
}
|
|
7308
7328
|
} catch (e) {
|
|
7309
|
-
|
|
7329
|
+
render.warn(`allowedTools removal failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
7310
7330
|
}
|
|
7311
7331
|
try {
|
|
7312
7332
|
const removed = uninstallHooks();
|
|
7313
7333
|
if (removed > 0) {
|
|
7314
|
-
|
|
7334
|
+
render.ok(`Hooks removed`, `${removed} entries`);
|
|
7315
7335
|
} else {
|
|
7316
|
-
|
|
7336
|
+
render.info(dim("· No claudemesh hooks to remove"));
|
|
7317
7337
|
}
|
|
7318
7338
|
} catch (e) {
|
|
7319
|
-
|
|
7339
|
+
render.warn(`hook removal failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
7320
7340
|
}
|
|
7321
|
-
|
|
7322
|
-
|
|
7341
|
+
render.blank();
|
|
7342
|
+
render.info("Restart Claude Code to drop the MCP connection + hooks.");
|
|
7323
7343
|
}
|
|
7324
7344
|
var MCP_NAME = "claudemesh", CLAUDE_CONFIG, CLAUDE_SETTINGS, HOOK_COMMAND_STOP = "claudemesh hook idle", HOOK_COMMAND_USER_PROMPT = "claudemesh hook working", HOOK_MARKER = "claudemesh hook ", CLAUDEMESH_TOOLS;
|
|
7325
7345
|
var init_install = __esm(() => {
|
|
7326
7346
|
init_facade();
|
|
7347
|
+
init_render();
|
|
7348
|
+
init_styles();
|
|
7327
7349
|
CLAUDE_CONFIG = join4(homedir4(), ".claude.json");
|
|
7328
7350
|
CLAUDE_SETTINGS = join4(homedir4(), ".claude", "settings.json");
|
|
7329
7351
|
CLAUDEMESH_TOOLS = [
|
|
@@ -7392,7 +7414,7 @@ async function uninstall() {
|
|
|
7392
7414
|
delete servers.claudemesh;
|
|
7393
7415
|
writeFileSync6(PATHS.CLAUDE_JSON, JSON.stringify(config, null, 2) + `
|
|
7394
7416
|
`, "utf-8");
|
|
7395
|
-
|
|
7417
|
+
render.ok("removed MCP server", dim("~/.claude.json"));
|
|
7396
7418
|
removed++;
|
|
7397
7419
|
}
|
|
7398
7420
|
} catch {}
|
|
@@ -7422,19 +7444,20 @@ async function uninstall() {
|
|
|
7422
7444
|
if (removedHooks > 0) {
|
|
7423
7445
|
writeFileSync6(PATHS.CLAUDE_SETTINGS, JSON.stringify(config, null, 2) + `
|
|
7424
7446
|
`, "utf-8");
|
|
7425
|
-
|
|
7447
|
+
render.ok(`removed ${removedHooks} claudemesh hook${removedHooks === 1 ? "" : "s"}`, dim("settings.json"));
|
|
7426
7448
|
removed++;
|
|
7427
7449
|
}
|
|
7428
7450
|
}
|
|
7429
7451
|
} catch {}
|
|
7430
7452
|
}
|
|
7431
7453
|
if (removed === 0) {
|
|
7432
|
-
|
|
7454
|
+
render.info(dim("Nothing to remove — claudemesh was not installed."));
|
|
7433
7455
|
}
|
|
7434
7456
|
return EXIT.SUCCESS;
|
|
7435
7457
|
}
|
|
7436
7458
|
var init_uninstall = __esm(() => {
|
|
7437
7459
|
init_paths();
|
|
7460
|
+
init_render();
|
|
7438
7461
|
init_styles();
|
|
7439
7462
|
init_exit_codes();
|
|
7440
7463
|
});
|
|
@@ -7664,7 +7687,7 @@ async function runDoctor() {
|
|
|
7664
7687
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
7665
7688
|
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
7666
7689
|
const green3 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
|
|
7667
|
-
const
|
|
7690
|
+
const red2 = (s) => useColor ? `\x1B[31m${s}\x1B[39m` : s;
|
|
7668
7691
|
console.log(`claudemesh doctor (v${VERSION})`);
|
|
7669
7692
|
console.log("─".repeat(60));
|
|
7670
7693
|
const checks = [
|
|
@@ -7678,7 +7701,7 @@ async function runDoctor() {
|
|
|
7678
7701
|
await checkNpmLatest()
|
|
7679
7702
|
];
|
|
7680
7703
|
for (const c of checks) {
|
|
7681
|
-
const mark = c.pass ? green3("✓") :
|
|
7704
|
+
const mark = c.pass ? green3("✓") : red2("✗");
|
|
7682
7705
|
const detail = c.detail ? dim2(` (${c.detail})`) : "";
|
|
7683
7706
|
console.log(`${mark} ${c.name}${detail}`);
|
|
7684
7707
|
if (!c.pass && c.fix) {
|
|
@@ -7691,7 +7714,7 @@ async function runDoctor() {
|
|
|
7691
7714
|
console.log(green3("All checks passed."));
|
|
7692
7715
|
process.exit(0);
|
|
7693
7716
|
} else {
|
|
7694
|
-
console.log(
|
|
7717
|
+
console.log(red2(`${failing.length} check(s) failed.`));
|
|
7695
7718
|
process.exit(1);
|
|
7696
7719
|
}
|
|
7697
7720
|
}
|
|
@@ -8269,7 +8292,7 @@ complete -c claudemesh -l join -d 'invite url'
|
|
|
8269
8292
|
}
|
|
8270
8293
|
async function runCompletions(shell) {
|
|
8271
8294
|
if (!shell) {
|
|
8272
|
-
|
|
8295
|
+
render.err("Usage: claudemesh completions <bash|zsh|fish>");
|
|
8273
8296
|
return EXIT.INVALID_ARGS;
|
|
8274
8297
|
}
|
|
8275
8298
|
switch (shell.toLowerCase()) {
|
|
@@ -8283,13 +8306,14 @@ async function runCompletions(shell) {
|
|
|
8283
8306
|
process.stdout.write(fish());
|
|
8284
8307
|
return EXIT.SUCCESS;
|
|
8285
8308
|
default:
|
|
8286
|
-
|
|
8309
|
+
render.err(`Unsupported shell: ${shell}`, "use bash, zsh, or fish.");
|
|
8287
8310
|
return EXIT.INVALID_ARGS;
|
|
8288
8311
|
}
|
|
8289
8312
|
}
|
|
8290
8313
|
var COMMANDS, FLAGS;
|
|
8291
8314
|
var init_completions = __esm(() => {
|
|
8292
8315
|
init_exit_codes();
|
|
8316
|
+
init_render();
|
|
8293
8317
|
COMMANDS = [
|
|
8294
8318
|
"create",
|
|
8295
8319
|
"new",
|
|
@@ -8372,26 +8396,22 @@ function safetyNumber(myPubkey, peerPubkey) {
|
|
|
8372
8396
|
return groups.join(" ");
|
|
8373
8397
|
}
|
|
8374
8398
|
async function runVerify(target, opts = {}) {
|
|
8375
|
-
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
8376
|
-
const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
8377
|
-
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
8378
|
-
const clay2 = (s) => useColor ? `\x1B[38;2;217;119;87m${s}\x1B[39m` : s;
|
|
8379
8399
|
const config = readConfig();
|
|
8380
8400
|
const meshSlug = opts.mesh ?? config.meshes[0]?.slug;
|
|
8381
8401
|
if (!meshSlug) {
|
|
8382
|
-
|
|
8402
|
+
render.err("No meshes joined.", "Run `claudemesh join <url>` first.");
|
|
8383
8403
|
return EXIT.NOT_FOUND;
|
|
8384
8404
|
}
|
|
8385
8405
|
const mesh = config.meshes.find((m) => m.slug === meshSlug);
|
|
8386
8406
|
if (!mesh) {
|
|
8387
|
-
|
|
8407
|
+
render.err(`Mesh "${meshSlug}" not found locally.`);
|
|
8388
8408
|
return EXIT.NOT_FOUND;
|
|
8389
8409
|
}
|
|
8390
8410
|
return await withMesh({ meshSlug }, async (client) => {
|
|
8391
8411
|
const peers = await client.listPeers();
|
|
8392
8412
|
const targets = target ? peers.filter((p) => p.displayName === target || p.pubkey === target || p.pubkey.startsWith(target)) : peers;
|
|
8393
8413
|
if (targets.length === 0) {
|
|
8394
|
-
|
|
8414
|
+
render.err(`No peer matching "${target ?? "(all)"}" on mesh ${meshSlug}.`);
|
|
8395
8415
|
return EXIT.NOT_FOUND;
|
|
8396
8416
|
}
|
|
8397
8417
|
if (opts.json) {
|
|
@@ -8403,19 +8423,20 @@ async function runVerify(target, opts = {}) {
|
|
|
8403
8423
|
})), null, 2));
|
|
8404
8424
|
return EXIT.SUCCESS;
|
|
8405
8425
|
}
|
|
8406
|
-
|
|
8407
|
-
console.log(` ${dim2("— safety numbers on")} ${bold2(meshSlug)}`);
|
|
8408
|
-
console.log("");
|
|
8426
|
+
render.section(`safety numbers on ${meshSlug}`);
|
|
8409
8427
|
for (const p of targets) {
|
|
8410
8428
|
const sn = safetyNumber(mesh.pubkey, p.pubkey);
|
|
8411
|
-
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8429
|
+
process.stdout.write(` ${bold(p.displayName)}
|
|
8430
|
+
`);
|
|
8431
|
+
process.stdout.write(` ${clay(sn)}
|
|
8432
|
+
`);
|
|
8433
|
+
process.stdout.write(` ${dim(`pubkey ${p.pubkey.slice(0, 16)}…`)}
|
|
8434
|
+
|
|
8435
|
+
`);
|
|
8415
8436
|
}
|
|
8416
|
-
|
|
8417
|
-
|
|
8418
|
-
|
|
8437
|
+
render.hint("Compare these digits with your peer (phone, in person — not chat).");
|
|
8438
|
+
render.hint("If they match on both sides, the channel is not being intercepted.");
|
|
8439
|
+
render.blank();
|
|
8419
8440
|
return EXIT.SUCCESS;
|
|
8420
8441
|
});
|
|
8421
8442
|
}
|
|
@@ -8423,6 +8444,8 @@ var init_verify = __esm(() => {
|
|
|
8423
8444
|
init_connect();
|
|
8424
8445
|
init_facade();
|
|
8425
8446
|
init_exit_codes();
|
|
8447
|
+
init_render();
|
|
8448
|
+
init_styles();
|
|
8426
8449
|
});
|
|
8427
8450
|
|
|
8428
8451
|
// src/commands/url-handler.ts
|
|
@@ -8484,10 +8507,9 @@ EOF
|
|
|
8484
8507
|
chmodSync4(shimPath, 493);
|
|
8485
8508
|
const lsreg = spawnSync5("/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister", ["-f", appDir], { encoding: "utf-8" });
|
|
8486
8509
|
if (lsreg.status !== 0) {
|
|
8487
|
-
|
|
8510
|
+
render.warn("lsregister returned non-zero", "scheme may not activate until Finder rescans.");
|
|
8488
8511
|
}
|
|
8489
|
-
|
|
8490
|
-
console.log(` app bundle: ${appDir}`);
|
|
8512
|
+
render.ok("registered claudemesh:// scheme on macOS", dim(appDir));
|
|
8491
8513
|
return EXIT.SUCCESS;
|
|
8492
8514
|
}
|
|
8493
8515
|
function installLinux() {
|
|
@@ -8508,12 +8530,11 @@ NoDisplay=true
|
|
|
8508
8530
|
writeFileSync7(desktopPath, desktop);
|
|
8509
8531
|
const xdg1 = spawnSync5("xdg-mime", ["default", "claudemesh.desktop", "x-scheme-handler/claudemesh"], { encoding: "utf-8" });
|
|
8510
8532
|
if (xdg1.status !== 0) {
|
|
8511
|
-
|
|
8533
|
+
render.warn("xdg-mime not available — skipped mime default registration");
|
|
8512
8534
|
}
|
|
8513
8535
|
const xdg2 = spawnSync5("update-desktop-database", [appsDir], { encoding: "utf-8" });
|
|
8514
8536
|
xdg2.status;
|
|
8515
|
-
|
|
8516
|
-
console.log(` desktop entry: ${desktopPath}`);
|
|
8537
|
+
render.ok("registered claudemesh:// scheme on Linux", dim(desktopPath));
|
|
8517
8538
|
return EXIT.SUCCESS;
|
|
8518
8539
|
}
|
|
8519
8540
|
function installWindows() {
|
|
@@ -8533,29 +8554,29 @@ function installWindows() {
|
|
|
8533
8554
|
`));
|
|
8534
8555
|
const res = spawnSync5("reg.exe", ["import", regPath], { encoding: "utf-8" });
|
|
8535
8556
|
if (res.status !== 0) {
|
|
8536
|
-
|
|
8557
|
+
render.warn("reg.exe import failed", `manual: double-click ${regPath}`);
|
|
8537
8558
|
return EXIT.INTERNAL_ERROR;
|
|
8538
8559
|
}
|
|
8539
|
-
|
|
8560
|
+
render.ok("registered claudemesh:// scheme on Windows");
|
|
8540
8561
|
return EXIT.SUCCESS;
|
|
8541
8562
|
}
|
|
8542
8563
|
function uninstallDarwin() {
|
|
8543
8564
|
const appDir = join6(homedir6(), "Library", "Application Support", "claudemesh", "ClaudemeshHandler.app");
|
|
8544
8565
|
if (existsSync13(appDir))
|
|
8545
8566
|
rmSync2(appDir, { recursive: true, force: true });
|
|
8546
|
-
|
|
8567
|
+
render.ok("removed claudemesh:// handler on macOS");
|
|
8547
8568
|
return EXIT.SUCCESS;
|
|
8548
8569
|
}
|
|
8549
8570
|
function uninstallLinux() {
|
|
8550
8571
|
const desktopPath = join6(homedir6(), ".local", "share", "applications", "claudemesh.desktop");
|
|
8551
8572
|
if (existsSync13(desktopPath))
|
|
8552
8573
|
rmSync2(desktopPath, { force: true });
|
|
8553
|
-
|
|
8574
|
+
render.ok("removed claudemesh:// handler on Linux");
|
|
8554
8575
|
return EXIT.SUCCESS;
|
|
8555
8576
|
}
|
|
8556
8577
|
function uninstallWindows() {
|
|
8557
8578
|
spawnSync5("reg.exe", ["delete", "HKCU\\Software\\Classes\\claudemesh", "/f"], { encoding: "utf-8" });
|
|
8558
|
-
|
|
8579
|
+
render.ok("removed claudemesh:// handler on Windows");
|
|
8559
8580
|
return EXIT.SUCCESS;
|
|
8560
8581
|
}
|
|
8561
8582
|
async function runUrlHandler(action) {
|
|
@@ -8576,14 +8597,16 @@ async function runUrlHandler(action) {
|
|
|
8576
8597
|
if (p === "win32")
|
|
8577
8598
|
return uninstallWindows();
|
|
8578
8599
|
} else {
|
|
8579
|
-
|
|
8600
|
+
render.err("Usage: claudemesh url-handler <install|uninstall>");
|
|
8580
8601
|
return EXIT.INVALID_ARGS;
|
|
8581
8602
|
}
|
|
8582
|
-
|
|
8603
|
+
render.err(`Unsupported platform: ${p}`);
|
|
8583
8604
|
return EXIT.INTERNAL_ERROR;
|
|
8584
8605
|
}
|
|
8585
8606
|
var init_url_handler = __esm(() => {
|
|
8586
8607
|
init_exit_codes();
|
|
8608
|
+
init_render();
|
|
8609
|
+
init_styles();
|
|
8587
8610
|
});
|
|
8588
8611
|
|
|
8589
8612
|
// src/commands/status-line.ts
|
|
@@ -10145,7 +10168,19 @@ async function startMcpServer() {
|
|
|
10145
10168
|
if (serviceIdx !== -1 && process.argv[serviceIdx + 1]) {
|
|
10146
10169
|
return startServiceProxy(process.argv[serviceIdx + 1]);
|
|
10147
10170
|
}
|
|
10171
|
+
const meshIdx = process.argv.indexOf("--mesh");
|
|
10172
|
+
const onlyMesh = meshIdx !== -1 ? process.argv[meshIdx + 1] : null;
|
|
10148
10173
|
const config = readConfig();
|
|
10174
|
+
if (onlyMesh) {
|
|
10175
|
+
const available = config.meshes.map((m) => m.slug);
|
|
10176
|
+
const filtered = config.meshes.filter((m) => m.slug === onlyMesh);
|
|
10177
|
+
if (filtered.length === 0) {
|
|
10178
|
+
process.stderr.write(`[claudemesh] --mesh "${onlyMesh}" not found in config. ` + `Joined meshes: ${available.join(", ") || "(none)"}
|
|
10179
|
+
`);
|
|
10180
|
+
process.exit(1);
|
|
10181
|
+
}
|
|
10182
|
+
config.meshes = filtered;
|
|
10183
|
+
}
|
|
10149
10184
|
const myName = config.displayName ?? "unnamed";
|
|
10150
10185
|
const myRole = config.role ?? process.env.CLAUDEMESH_ROLE ?? null;
|
|
10151
10186
|
const myGroups = (config.groups ?? []).map((g) => `@${g.name}${g.role ? ":" + g.role : ""}`).join(", ") || "none";
|
|
@@ -12301,9 +12336,8 @@ __export(exports_seed_test_mesh, {
|
|
|
12301
12336
|
function runSeedTestMesh(args) {
|
|
12302
12337
|
const [brokerUrl, meshId, memberId, pubkey, slug] = args;
|
|
12303
12338
|
if (!brokerUrl || !meshId || !memberId || !pubkey || !slug) {
|
|
12304
|
-
|
|
12305
|
-
|
|
12306
|
-
console.error('Example: claudemesh seed-test-mesh "ws://localhost:7900/ws" mesh-123 member-abc aaa..aaa smoke-test');
|
|
12339
|
+
render.err("Usage: claudemesh seed-test-mesh <broker-ws-url> <mesh-id> <member-id> <pubkey> <slug>");
|
|
12340
|
+
render.info(dim('Example: claudemesh seed-test-mesh "ws://localhost:7900/ws" mesh-123 member-abc aaa..aaa smoke-test'));
|
|
12307
12341
|
process.exit(1);
|
|
12308
12342
|
}
|
|
12309
12343
|
const config = readConfig();
|
|
@@ -12319,11 +12353,13 @@ function runSeedTestMesh(args) {
|
|
|
12319
12353
|
joinedAt: new Date().toISOString()
|
|
12320
12354
|
});
|
|
12321
12355
|
writeConfig(config);
|
|
12322
|
-
|
|
12323
|
-
|
|
12356
|
+
render.ok(`seeded ${bold(slug)}`, dim(meshId));
|
|
12357
|
+
render.hint(`run ${bold("claudemesh mcp")} to connect, or register with Claude Code via ${bold("claudemesh install")}`);
|
|
12324
12358
|
}
|
|
12325
12359
|
var init_seed_test_mesh = __esm(() => {
|
|
12326
12360
|
init_facade();
|
|
12361
|
+
init_render();
|
|
12362
|
+
init_styles();
|
|
12327
12363
|
});
|
|
12328
12364
|
|
|
12329
12365
|
// src/cli/argv.ts
|
|
@@ -12830,4 +12866,4 @@ main().catch((err) => {
|
|
|
12830
12866
|
process.exit(EXIT.INTERNAL_ERROR);
|
|
12831
12867
|
});
|
|
12832
12868
|
|
|
12833
|
-
//# debugId=
|
|
12869
|
+
//# debugId=AC9613431467FF4964756E2164756E21
|