claudemesh-cli 1.19.3 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -88,7 +88,7 @@ __export(exports_urls, {
88
88
  VERSION: () => VERSION,
89
89
  URLS: () => URLS
90
90
  });
91
- var URLS, VERSION = "1.19.3", env;
91
+ var URLS, VERSION = "1.20.0", env;
92
92
  var init_urls = __esm(() => {
93
93
  URLS = {
94
94
  BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
@@ -398,6 +398,7 @@ var init_client = __esm(() => {
398
398
  var exports_my = {};
399
399
  __export(exports_my, {
400
400
  revokeSession: () => revokeSession,
401
+ reslugMesh: () => reslugMesh,
401
402
  renameMesh: () => renameMesh,
402
403
  getProfile: () => getProfile,
403
404
  getMeshes: () => getMeshes,
@@ -422,6 +423,14 @@ async function renameMesh(token, slug, newName) {
422
423
  token
423
424
  });
424
425
  }
426
+ async function reslugMesh(token, oldSlug, newSlug) {
427
+ return request({
428
+ path: `/api/cli/meshes/${oldSlug}`,
429
+ method: "PATCH",
430
+ body: { slug: newSlug },
431
+ token
432
+ });
433
+ }
425
434
  async function createInvite(token, meshSlug, body) {
426
435
  return post(`/api/my/meshes/${meshSlug}/invites`, body, token);
427
436
  }
@@ -4393,6 +4402,18 @@ var init_rename = __esm(() => {
4393
4402
  init_facade6();
4394
4403
  });
4395
4404
 
4405
+ // src/services/mesh/reslug.ts
4406
+ async function reslugMesh2(oldSlug, newSlug) {
4407
+ const auth = getStoredToken();
4408
+ if (!auth)
4409
+ throw new Error("Not signed in");
4410
+ return await exports_my.reslugMesh(auth.session_token, oldSlug, newSlug);
4411
+ }
4412
+ var init_reslug = __esm(() => {
4413
+ init_facade3();
4414
+ init_facade6();
4415
+ });
4416
+
4396
4417
  // src/services/mesh/leave.ts
4397
4418
  function leaveMesh(slug) {
4398
4419
  return removeMeshConfig(slug);
@@ -4434,6 +4455,7 @@ var init_facade10 = __esm(() => {
4434
4455
  init_list();
4435
4456
  init_create();
4436
4457
  init_rename();
4458
+ init_reslug();
4437
4459
  init_leave();
4438
4460
  init_join();
4439
4461
  init_resolve_target();
@@ -5178,6 +5200,76 @@ var init_rename2 = __esm(() => {
5178
5200
  init_exit_codes();
5179
5201
  });
5180
5202
 
5203
+ // src/commands/slug.ts
5204
+ var exports_slug = {};
5205
+ __export(exports_slug, {
5206
+ slug: () => slug
5207
+ });
5208
+ async function slug(oldSlug, newSlug) {
5209
+ if (!oldSlug || !newSlug) {
5210
+ console.error(` ${icons.cross} Usage: ${bold("claudemesh slug")} <old-slug> <new-slug>`);
5211
+ return EXIT.INVALID_ARGS;
5212
+ }
5213
+ if (!SLUG_RE.test(newSlug)) {
5214
+ console.error(` ${icons.cross} Invalid slug: must be 2-32 chars, lowercase alnum + hyphens, start with alnum`);
5215
+ return EXIT.INVALID_ARGS;
5216
+ }
5217
+ if (oldSlug === newSlug) {
5218
+ console.error(` ${icons.cross} Old and new slug are the same.`);
5219
+ return EXIT.INVALID_ARGS;
5220
+ }
5221
+ const auth = getStoredToken();
5222
+ if (!auth) {
5223
+ console.error(` ${icons.cross} Renaming a mesh requires a claudemesh.com account session.`);
5224
+ console.error(` ${dim("Run")} ${bold("claudemesh login")} ${dim("first.")}`);
5225
+ return EXIT.AUTH_FAILED;
5226
+ }
5227
+ const cfg = readConfig();
5228
+ const collision = cfg.meshes.find((m) => m.slug === newSlug && m.slug !== oldSlug);
5229
+ if (collision) {
5230
+ console.error(` ${icons.cross} Slug "${newSlug}" already used locally by another joined mesh.`);
5231
+ console.error(` ${dim("Pick a different slug, or leave the other mesh first.")}`);
5232
+ return EXIT.ALREADY_EXISTS;
5233
+ }
5234
+ try {
5235
+ const updated = await reslugMesh2(oldSlug, newSlug);
5236
+ const local = cfg.meshes.find((m) => m.slug === oldSlug);
5237
+ if (local) {
5238
+ removeMeshConfig(oldSlug);
5239
+ setMeshConfig(updated.slug, { ...local, slug: updated.slug, name: updated.name });
5240
+ }
5241
+ console.log(` ${green(icons.check)} Slug changed: "${oldSlug}" → "${updated.slug}"`);
5242
+ console.log(` ${dim("Other peers will pick up the new slug after they run")} ${bold("claudemesh sync")}`);
5243
+ return EXIT.SUCCESS;
5244
+ } catch (err) {
5245
+ if (err instanceof ApiError) {
5246
+ const body = err.body;
5247
+ console.error(` ${icons.cross} ${body?.error ?? err.statusText}`);
5248
+ if (err.status === 401)
5249
+ return EXIT.AUTH_FAILED;
5250
+ if (err.status === 403)
5251
+ return EXIT.PERMISSION_DENIED;
5252
+ if (err.status === 404)
5253
+ return EXIT.NOT_FOUND;
5254
+ if (err.status === 400)
5255
+ return EXIT.INVALID_ARGS;
5256
+ return EXIT.INTERNAL_ERROR;
5257
+ }
5258
+ console.error(` ${icons.cross} Failed: ${err instanceof Error ? err.message : err}`);
5259
+ return EXIT.INTERNAL_ERROR;
5260
+ }
5261
+ }
5262
+ var SLUG_RE;
5263
+ var init_slug = __esm(() => {
5264
+ init_facade10();
5265
+ init_facade6();
5266
+ init_facade3();
5267
+ init_facade();
5268
+ init_styles();
5269
+ init_exit_codes();
5270
+ SLUG_RE = /^[a-z0-9][a-z0-9-]{1,31}$/;
5271
+ });
5272
+
5181
5273
  // src/services/clipboard/read.ts
5182
5274
  import { execSync } from "node:child_process";
5183
5275
  import { platform as platform4 } from "node:os";
@@ -6725,17 +6817,17 @@ function projectFields(record, fields) {
6725
6817
  }
6726
6818
  return out;
6727
6819
  }
6728
- async function listPeersForMesh(slug) {
6820
+ async function listPeersForMesh(slug2) {
6729
6821
  const config = readConfig();
6730
- const joined = config.meshes.find((m) => m.slug === slug);
6822
+ const joined = config.meshes.find((m) => m.slug === slug2);
6731
6823
  const selfMemberPubkey = joined?.pubkey ?? null;
6732
- const bridged = await tryBridge(slug, "peers");
6824
+ const bridged = await tryBridge(slug2, "peers");
6733
6825
  if (bridged && bridged.ok) {
6734
6826
  const peers = bridged.result;
6735
6827
  return peers.map((p) => annotateSelf(p, selfMemberPubkey, null));
6736
6828
  }
6737
6829
  let result = [];
6738
- await withMesh({ meshSlug: slug }, async (client) => {
6830
+ await withMesh({ meshSlug: slug2 }, async (client) => {
6739
6831
  const all = await client.listPeers();
6740
6832
  const selfSessionPubkey = client.getSessionPubkey();
6741
6833
  result = all.map((p) => annotateSelf(p, selfMemberPubkey, selfSessionPubkey));
@@ -6758,15 +6850,15 @@ async function runPeers(flags) {
6758
6850
  const fieldList = typeof flags.json === "string" && flags.json.length > 0 ? flags.json.split(",").map((s) => s.trim()).filter(Boolean) : null;
6759
6851
  const wantsJson = flags.json !== undefined && flags.json !== false;
6760
6852
  const allJson = [];
6761
- for (const slug of slugs) {
6853
+ for (const slug2 of slugs) {
6762
6854
  try {
6763
- const peers = await listPeersForMesh(slug);
6855
+ const peers = await listPeersForMesh(slug2);
6764
6856
  if (wantsJson) {
6765
6857
  const projected = fieldList ? peers.map((p) => projectFields(p, fieldList)) : peers;
6766
- allJson.push({ mesh: slug, peers: projected });
6858
+ allJson.push({ mesh: slug2, peers: projected });
6767
6859
  continue;
6768
6860
  }
6769
- render.section(`peers on ${slug} (${peers.length})`);
6861
+ render.section(`peers on ${slug2} (${peers.length})`);
6770
6862
  if (peers.length === 0) {
6771
6863
  render.info(dim(" (no peers connected)"));
6772
6864
  continue;
@@ -6791,7 +6883,7 @@ async function runPeers(flags) {
6791
6883
  render.info(dim(` cwd: ${p.cwd}`));
6792
6884
  }
6793
6885
  } catch (e) {
6794
- render.err(`${slug}: ${e instanceof Error ? e.message : String(e)}`);
6886
+ render.err(`${slug2}: ${e instanceof Error ? e.message : String(e)}`);
6795
6887
  }
6796
6888
  }
6797
6889
  if (wantsJson) {
@@ -7080,11 +7172,11 @@ async function runMe(flags) {
7080
7172
  }
7081
7173
  const slugWidth = Math.max(...ws.meshes.map((m) => m.slug.length), 8);
7082
7174
  for (const m of ws.meshes) {
7083
- const slug = cyan(m.slug.padEnd(slugWidth));
7175
+ const slug2 = cyan(m.slug.padEnd(slugWidth));
7084
7176
  const peers = `${m.online}/${m.peers}`;
7085
7177
  const role = dim(m.myRole);
7086
7178
  const unread = m.unreadMentions > 0 ? " " + yellow(`${m.unreadMentions} @you`) : "";
7087
- process.stdout.write(` ${slug} ${peers.padStart(5)} online ${dim(String(m.topics).padStart(2) + " topics")} ${role}${unread}
7179
+ process.stdout.write(` ${slug2} ${peers.padStart(5)} online ${dim(String(m.topics).padStart(2) + " topics")} ${role}${unread}
7088
7180
  `);
7089
7181
  }
7090
7182
  return EXIT.SUCCESS;
@@ -7114,11 +7206,11 @@ async function runMeTopics(flags) {
7114
7206
  const slugWidth = Math.max(...visible.map((t) => t.meshSlug.length), 6);
7115
7207
  const nameWidth = Math.max(...visible.map((t) => t.name.length), 8);
7116
7208
  for (const t of visible) {
7117
- const slug = dim(t.meshSlug.padEnd(slugWidth));
7209
+ const slug2 = dim(t.meshSlug.padEnd(slugWidth));
7118
7210
  const name = cyan(t.name.padEnd(nameWidth));
7119
7211
  const unread = t.unread > 0 ? yellow(`${t.unread} unread`.padStart(10)) : dim("·".padStart(10));
7120
7212
  const last = t.lastMessageAt ? dim(formatRelativeTime(t.lastMessageAt)) : dim("never");
7121
- process.stdout.write(` ${slug} ${name} ${unread} ${last}
7213
+ process.stdout.write(` ${slug2} ${name} ${unread} ${last}
7122
7214
  `);
7123
7215
  }
7124
7216
  return EXIT.SUCCESS;
@@ -7154,13 +7246,13 @@ async function runMeNotifications(flags) {
7154
7246
  }
7155
7247
  const slugWidth = Math.max(...ws.notifications.map((n) => n.meshSlug.length), 6);
7156
7248
  for (const n of ws.notifications) {
7157
- const slug = dim(n.meshSlug.padEnd(slugWidth));
7249
+ const slug2 = dim(n.meshSlug.padEnd(slugWidth));
7158
7250
  const topic = cyan(`#${n.topicName}`);
7159
7251
  const sender = n.senderName ? `from ${n.senderName}` : "from ?";
7160
7252
  const ago = formatRelativeTime(n.createdAt);
7161
7253
  const dot = n.read ? dim("·") : yellow("●");
7162
7254
  const snippet = n.snippet ?? (n.ciphertext ? dim("[encrypted]") : dim("[empty]"));
7163
- process.stdout.write(` ${dot} ${slug} ${topic} ${dim(sender)} ${dim(ago)}
7255
+ process.stdout.write(` ${dot} ${slug2} ${topic} ${dim(sender)} ${dim(ago)}
7164
7256
  ` + ` ${snippet.length > 200 ? snippet.slice(0, 200) + "…" : snippet}
7165
7257
  `);
7166
7258
  }
@@ -7193,12 +7285,12 @@ async function runMeActivity(flags) {
7193
7285
  }
7194
7286
  const slugWidth = Math.max(...ws.activity.map((a) => a.meshSlug.length), 6);
7195
7287
  for (const a of ws.activity) {
7196
- const slug = dim(a.meshSlug.padEnd(slugWidth));
7288
+ const slug2 = dim(a.meshSlug.padEnd(slugWidth));
7197
7289
  const topic = cyan(`#${a.topicName}`);
7198
7290
  const sender = a.senderName ?? "?";
7199
7291
  const ago = formatRelativeTime(a.createdAt);
7200
7292
  const snippet = a.snippet ?? (a.ciphertext ? dim("[encrypted]") : dim("[empty]"));
7201
- process.stdout.write(` ${slug} ${topic} ${dim(sender + " ·")} ${dim(ago)}
7293
+ process.stdout.write(` ${slug2} ${topic} ${dim(sender + " ·")} ${dim(ago)}
7202
7294
  ` + ` ${snippet.length > 200 ? snippet.slice(0, 200) + "…" : snippet}
7203
7295
  `);
7204
7296
  }
@@ -7237,10 +7329,10 @@ async function runMeSearch(flags) {
7237
7329
  `));
7238
7330
  const slugWidth = Math.max(...ws.topics.map((t) => t.meshSlug.length), 6);
7239
7331
  for (const t of ws.topics) {
7240
- const slug = dim(t.meshSlug.padEnd(slugWidth));
7332
+ const slug2 = dim(t.meshSlug.padEnd(slugWidth));
7241
7333
  const name = cyan(`#${t.name}`);
7242
7334
  const desc = t.description ? dim(` — ${t.description}`) : "";
7243
- process.stdout.write(` ${slug} ${name}${desc}
7335
+ process.stdout.write(` ${slug2} ${name}${desc}
7244
7336
  `);
7245
7337
  }
7246
7338
  }
@@ -7250,13 +7342,13 @@ async function runMeSearch(flags) {
7250
7342
  `));
7251
7343
  const slugWidth = Math.max(...ws.messages.map((m) => m.meshSlug.length), 6);
7252
7344
  for (const m of ws.messages) {
7253
- const slug = dim(m.meshSlug.padEnd(slugWidth));
7345
+ const slug2 = dim(m.meshSlug.padEnd(slugWidth));
7254
7346
  const topic = cyan(`#${m.topicName}`);
7255
7347
  const sender = m.senderName;
7256
7348
  const ago = formatRelativeTime(m.createdAt);
7257
7349
  const snippet = m.snippet ?? (m.bodyVersion === 2 ? dim("[encrypted — open the topic to decrypt]") : dim("[empty]"));
7258
7350
  const highlighted = m.snippet ? highlightMatch(snippet, flags.query) : snippet;
7259
- process.stdout.write(` ${slug} ${topic} ${dim(sender + " ·")} ${dim(ago)}
7351
+ process.stdout.write(` ${slug2} ${topic} ${dim(sender + " ·")} ${dim(ago)}
7260
7352
  ` + ` ${highlighted}
7261
7353
  `);
7262
7354
  }
@@ -7301,11 +7393,11 @@ async function runMeTasks(flags) {
7301
7393
  }
7302
7394
  const slugWidth = Math.max(...ws.tasks.map((t) => t.meshSlug.length), 6);
7303
7395
  for (const t of ws.tasks) {
7304
- const slug = dim(t.meshSlug.padEnd(slugWidth));
7396
+ const slug2 = dim(t.meshSlug.padEnd(slugWidth));
7305
7397
  const status = t.status === "open" ? yellow("open ") : t.status === "claimed" ? cyan("working ") : green("done ");
7306
7398
  const prio = t.priority === "urgent" ? yellow("!") : t.priority === "low" ? dim("·") : " ";
7307
7399
  const claimer = t.claimedByName ? dim(` ← ${t.claimedByName}`) : "";
7308
- process.stdout.write(` ${slug} ${prio} ${status} ${t.title}${claimer}
7400
+ process.stdout.write(` ${slug2} ${prio} ${status} ${t.title}${claimer}
7309
7401
  `);
7310
7402
  }
7311
7403
  return EXIT.SUCCESS;
@@ -7338,12 +7430,12 @@ async function runMeState(flags) {
7338
7430
  const slugWidth = Math.max(...ws.entries.map((e) => e.meshSlug.length), 6);
7339
7431
  const keyWidth = Math.max(...ws.entries.map((e) => e.key.length), 8);
7340
7432
  for (const e of ws.entries) {
7341
- const slug = dim(e.meshSlug.padEnd(slugWidth));
7433
+ const slug2 = dim(e.meshSlug.padEnd(slugWidth));
7342
7434
  const key = cyan(e.key.padEnd(keyWidth));
7343
7435
  const valueStr = typeof e.value === "string" ? e.value : JSON.stringify(e.value);
7344
7436
  const trimmed = valueStr.length > 80 ? valueStr.slice(0, 80) + "…" : valueStr;
7345
7437
  const ago = dim(formatRelativeTime(e.updatedAt));
7346
- process.stdout.write(` ${slug} ${key} ${trimmed} ${ago}
7438
+ process.stdout.write(` ${slug2} ${key} ${trimmed} ${ago}
7347
7439
  `);
7348
7440
  }
7349
7441
  return EXIT.SUCCESS;
@@ -7376,11 +7468,11 @@ async function runMeMemory(flags) {
7376
7468
  }
7377
7469
  const slugWidth = Math.max(...ws.memories.map((m) => m.meshSlug.length), 6);
7378
7470
  for (const m of ws.memories) {
7379
- const slug = dim(m.meshSlug.padEnd(slugWidth));
7471
+ const slug2 = dim(m.meshSlug.padEnd(slugWidth));
7380
7472
  const ago = dim(formatRelativeTime(m.rememberedAt));
7381
7473
  const tags = m.tags.length > 0 ? " " + dim("[" + m.tags.join(", ") + "]") : "";
7382
7474
  const content = m.content.length > 240 ? m.content.slice(0, 240) + "…" : m.content;
7383
- process.stdout.write(` ${slug} ${ago}${tags}
7475
+ process.stdout.write(` ${slug2} ${ago}${tags}
7384
7476
  ${content}
7385
7477
  `);
7386
7478
  }
@@ -10164,10 +10256,10 @@ async function resolvePeer(meshSlug, name) {
10164
10256
  return { displayName: match.displayName, pubkey: key };
10165
10257
  });
10166
10258
  }
10167
- function pickMesh2(slug) {
10259
+ function pickMesh2(slug2) {
10168
10260
  const cfg = readConfig();
10169
- if (slug)
10170
- return cfg.meshes.find((m) => m.slug === slug) ? slug : null;
10261
+ if (slug2)
10262
+ return cfg.meshes.find((m) => m.slug === slug2) ? slug2 : null;
10171
10263
  return cfg.meshes[0]?.slug ?? null;
10172
10264
  }
10173
10265
  async function runGrant(peer, caps, opts = {}) {
@@ -14439,26 +14531,26 @@ __export(exports_seed_test_mesh, {
14439
14531
  runSeedTestMesh: () => runSeedTestMesh
14440
14532
  });
14441
14533
  function runSeedTestMesh(args) {
14442
- const [brokerUrl, meshId, memberId, pubkey, slug] = args;
14443
- if (!brokerUrl || !meshId || !memberId || !pubkey || !slug) {
14534
+ const [brokerUrl, meshId, memberId, pubkey, slug2] = args;
14535
+ if (!brokerUrl || !meshId || !memberId || !pubkey || !slug2) {
14444
14536
  render.err("Usage: claudemesh seed-test-mesh <broker-ws-url> <mesh-id> <member-id> <pubkey> <slug>");
14445
14537
  render.info(dim('Example: claudemesh seed-test-mesh "ws://localhost:7900/ws" mesh-123 member-abc aaa..aaa smoke-test'));
14446
14538
  process.exit(1);
14447
14539
  }
14448
14540
  const config = readConfig();
14449
- config.meshes = config.meshes.filter((m) => m.slug !== slug);
14541
+ config.meshes = config.meshes.filter((m) => m.slug !== slug2);
14450
14542
  config.meshes.push({
14451
14543
  meshId,
14452
14544
  memberId,
14453
- slug,
14454
- name: `Test: ${slug}`,
14545
+ slug: slug2,
14546
+ name: `Test: ${slug2}`,
14455
14547
  pubkey,
14456
14548
  secretKey: "dev-only-stub",
14457
14549
  brokerUrl,
14458
14550
  joinedAt: new Date().toISOString()
14459
14551
  });
14460
14552
  writeConfig(config);
14461
- render.ok(`seeded ${bold(slug)}`, dim(meshId));
14553
+ render.ok(`seeded ${bold(slug2)}`, dim(meshId));
14462
14554
  render.hint(`run ${bold("claudemesh mcp")} to connect, or register with Claude Code via ${bold("claudemesh install")}`);
14463
14555
  }
14464
14556
  var init_seed_test_mesh = __esm(() => {
@@ -15044,7 +15136,8 @@ Mesh
15044
15136
  claudemesh launch [slug] launch Claude Code on a mesh (alias: connect)
15045
15137
  claudemesh list show your meshes (alias: ls)
15046
15138
  claudemesh delete [slug] delete a mesh (alias: rm)
15047
- claudemesh rename <slug> <name> rename a mesh
15139
+ claudemesh rename <slug> <name> rename a mesh's display name (slug stays)
15140
+ claudemesh slug <old> <new> change a mesh's slug (URL-safe identifier)
15048
15141
  claudemesh share [email] share mesh (invite link / send email)
15049
15142
 
15050
15143
  Peer (resource form, recommended)
@@ -15295,6 +15388,11 @@ async function main() {
15295
15388
  process.exit(await rename2(positionals[0] ?? "", positionals[1] ?? ""));
15296
15389
  break;
15297
15390
  }
15391
+ case "slug": {
15392
+ const { slug: slug2 } = await Promise.resolve().then(() => (init_slug(), exports_slug));
15393
+ process.exit(await slug2(positionals[0] ?? "", positionals[1] ?? ""));
15394
+ break;
15395
+ }
15298
15396
  case "share":
15299
15397
  case "invite": {
15300
15398
  const { invite: invite2 } = await Promise.resolve().then(() => (init_invite(), exports_invite));
@@ -16108,4 +16206,4 @@ main().catch((err) => {
16108
16206
  process.exit(EXIT.INTERNAL_ERROR);
16109
16207
  });
16110
16208
 
16111
- //# debugId=77BC12B35C8B56DE64756E2164756E21
16209
+ //# debugId=E34B419F39DEAC7964756E2164756E21