claudemesh-cli 0.9.3 → 0.9.4

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.
Files changed (2) hide show
  1. package/dist/index.js +566 -206
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ var __create = Object.create;
4
4
  var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
9
  var __toESM = (mod, isNodeMode, target) => {
9
10
  target = mod != null ? __create(__getProtoOf(mod)) : {};
@@ -16,6 +17,20 @@ var __toESM = (mod, isNodeMode, target) => {
16
17
  });
17
18
  return to;
18
19
  };
20
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
21
+ var __toCommonJS = (from) => {
22
+ var entry = __moduleCache.get(from), desc;
23
+ if (entry)
24
+ return entry;
25
+ entry = __defProp({}, "__esModule", { value: true });
26
+ if (from && typeof from === "object" || typeof from === "function")
27
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
28
+ get: () => from[key],
29
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
30
+ }));
31
+ __moduleCache.set(from, entry);
32
+ return entry;
33
+ };
19
34
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
20
35
  var __export = (target, all) => {
21
36
  for (var name in all)
@@ -40047,6 +40062,201 @@ function deriveHttpUrl(wssUrl) {
40047
40062
  return url.toString().replace(/\/$/, "");
40048
40063
  }
40049
40064
 
40065
+ // src/tui/colors.ts
40066
+ function moveTo(row, col) {
40067
+ return isTTY ? `\x1B[${row};${col}H` : "";
40068
+ }
40069
+ function visibleLength(s) {
40070
+ return s.replace(/\x1b\[[^m]*m/g, "").length;
40071
+ }
40072
+ var isTTY, esc2 = (code) => (s) => isTTY ? `${code}${s}\x1B[0m` : s, orange, clay, amber, bold2, dim, green, yellow, red, cyan2, boldOrange, HIDE_CURSOR, SHOW_CURSOR, CLEAR_SCREEN, CLEAR_LINE;
40073
+ var init_colors = __esm(() => {
40074
+ isTTY = process.stdout.isTTY && !process.env.NO_COLOR && process.env.TERM !== "dumb";
40075
+ orange = esc2("\x1B[38;5;208m");
40076
+ clay = esc2("\x1B[38;5;173m");
40077
+ amber = esc2("\x1B[38;5;214m");
40078
+ bold2 = esc2("\x1B[1m");
40079
+ dim = esc2("\x1B[2m");
40080
+ green = esc2("\x1B[32m");
40081
+ yellow = esc2("\x1B[33m");
40082
+ red = esc2("\x1B[31m");
40083
+ cyan2 = esc2("\x1B[36m");
40084
+ boldOrange = esc2("\x1B[1m\x1B[38;5;208m");
40085
+ HIDE_CURSOR = isTTY ? "\x1B[?25l" : "";
40086
+ SHOW_CURSOR = isTTY ? "\x1B[?25h" : "";
40087
+ CLEAR_SCREEN = isTTY ? "\x1B[2J\x1B[H" : "";
40088
+ CLEAR_LINE = isTTY ? "\x1B[K" : "";
40089
+ });
40090
+
40091
+ // package.json
40092
+ var package_default;
40093
+ var init_package = __esm(() => {
40094
+ package_default = {
40095
+ name: "claudemesh-cli",
40096
+ version: "0.9.4",
40097
+ description: "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
40098
+ keywords: [
40099
+ "claude-code",
40100
+ "mcp",
40101
+ "model-context-protocol",
40102
+ "claudemesh",
40103
+ "peer-messaging",
40104
+ "multi-agent"
40105
+ ],
40106
+ author: "Alejandro Gutiérrez",
40107
+ license: "MIT",
40108
+ homepage: "https://claudemesh.com",
40109
+ repository: {
40110
+ type: "git",
40111
+ url: "https://github.com/alezmad/claudemesh.git",
40112
+ directory: "apps/cli"
40113
+ },
40114
+ type: "module",
40115
+ bin: {
40116
+ claudemesh: "./dist/index.js"
40117
+ },
40118
+ files: [
40119
+ "dist",
40120
+ "README.md",
40121
+ "LICENSE"
40122
+ ],
40123
+ publishConfig: {
40124
+ access: "public"
40125
+ },
40126
+ scripts: {
40127
+ build: 'bun build src/index.ts --target=node --outfile dist/index.js --banner "#!/usr/bin/env node" && chmod +x dist/index.js',
40128
+ clean: "git clean -xdf .cache .turbo dist node_modules",
40129
+ dev: "bun --hot src/index.ts",
40130
+ start: "bun src/index.ts",
40131
+ format: "prettier --check . --ignore-path ../../.gitignore",
40132
+ lint: "eslint",
40133
+ prepublishOnly: "bun run build",
40134
+ test: "vitest run",
40135
+ typecheck: "tsc --noEmit"
40136
+ },
40137
+ prettier: "@turbostarter/prettier-config",
40138
+ engines: {
40139
+ node: ">=20"
40140
+ },
40141
+ dependencies: {
40142
+ "@modelcontextprotocol/sdk": "1.27.1",
40143
+ citty: "0.2.2",
40144
+ "libsodium-wrappers": "0.7.15",
40145
+ ws: "8.20.0",
40146
+ zod: "4.1.13"
40147
+ },
40148
+ devDependencies: {
40149
+ "@turbostarter/eslint-config": "workspace:*",
40150
+ "@turbostarter/prettier-config": "workspace:*",
40151
+ "@turbostarter/tsconfig": "workspace:*",
40152
+ "@turbostarter/vitest-config": "workspace:*",
40153
+ "@types/libsodium-wrappers": "0.7.14",
40154
+ "@types/ws": "8.5.13",
40155
+ eslint: "catalog:",
40156
+ prettier: "catalog:",
40157
+ typescript: "catalog:",
40158
+ vitest: "catalog:"
40159
+ }
40160
+ };
40161
+ });
40162
+
40163
+ // src/version.ts
40164
+ var exports_version = {};
40165
+ __export(exports_version, {
40166
+ VERSION: () => VERSION
40167
+ });
40168
+ var VERSION;
40169
+ var init_version = __esm(() => {
40170
+ init_package();
40171
+ VERSION = package_default.version;
40172
+ });
40173
+
40174
+ // src/tui/spinner.ts
40175
+ function edgeChar(dx, dy) {
40176
+ const a = Math.abs(dx), b = Math.abs(dy);
40177
+ if (b < a * 0.4)
40178
+ return "-";
40179
+ if (a < b * 0.4)
40180
+ return "|";
40181
+ return dx > 0 === dy > 0 ? "\\" : "/";
40182
+ }
40183
+ function drawLine(grid, x0, y0, x1, y1) {
40184
+ const dx = x1 - x0, dy = y1 - y0;
40185
+ const steps = Math.max(Math.abs(dx), Math.abs(dy));
40186
+ for (let s = 1;s < steps; s++) {
40187
+ const x = Math.round(x0 + dx * s / steps);
40188
+ const y = Math.round(y0 + dy * s / steps);
40189
+ if (y >= 0 && y < H && x >= 0 && x < W) {
40190
+ const c = grid[y][x];
40191
+ if (c === " ")
40192
+ grid[y][x] = edgeChar(dx, dy);
40193
+ else if (c !== edgeChar(dx, dy) && c !== "●")
40194
+ grid[y][x] = "+";
40195
+ }
40196
+ }
40197
+ }
40198
+ function buildFrame(i) {
40199
+ const grid = Array.from({ length: H }, () => Array(W).fill(" "));
40200
+ const base = i / TOTAL * Math.PI * 2;
40201
+ const nodes = [0, 1, 2, 3].map((n) => {
40202
+ const a = base + n * Math.PI / 2 - Math.PI / 2;
40203
+ return { x: Math.round(CX + RX * Math.cos(a)), y: Math.round(CY + RY * Math.sin(a)) };
40204
+ });
40205
+ for (let a = 0;a < 4; a++)
40206
+ for (let b = a + 1;b < 4; b++)
40207
+ drawLine(grid, nodes[a].x, nodes[a].y, nodes[b].x, nodes[b].y);
40208
+ for (const { x, y } of nodes)
40209
+ if (y >= 0 && y < H && x >= 0 && x < W)
40210
+ grid[y][x] = "●";
40211
+ return grid.map((r) => r.join(""));
40212
+ }
40213
+ function colorize(line) {
40214
+ return line.replace(/●/g, boldOrange("●")).replace(/[-|/\\+]/g, (c) => dim(clay(c)));
40215
+ }
40216
+ function getFrame(index) {
40217
+ return RAW_FRAMES[index % RAW_FRAMES.length].map(colorize);
40218
+ }
40219
+ function createSpinner(opts) {
40220
+ let frame = 0;
40221
+ let timer = null;
40222
+ return {
40223
+ start() {
40224
+ if (timer)
40225
+ return;
40226
+ timer = setInterval(() => {
40227
+ opts.render(getFrame(frame++));
40228
+ }, opts.interval ?? 70);
40229
+ opts.render(getFrame(frame++));
40230
+ },
40231
+ stop() {
40232
+ if (timer) {
40233
+ clearInterval(timer);
40234
+ timer = null;
40235
+ }
40236
+ },
40237
+ get isRunning() {
40238
+ return timer !== null;
40239
+ }
40240
+ };
40241
+ }
40242
+ var W = 7, H = 5, CX = 3, CY = 2, RX = 3, RY = 2, TOTAL = 12, seen, RAW_FRAMES, FRAME_COUNT, FRAME_HEIGHT;
40243
+ var init_spinner = __esm(() => {
40244
+ init_colors();
40245
+ seen = new Set;
40246
+ RAW_FRAMES = [];
40247
+ for (let i = 0;i < TOTAL; i++) {
40248
+ const f = buildFrame(i);
40249
+ const key = f.join(`
40250
+ `);
40251
+ if (!seen.has(key)) {
40252
+ seen.add(key);
40253
+ RAW_FRAMES.push(f);
40254
+ }
40255
+ }
40256
+ FRAME_COUNT = RAW_FRAMES.length;
40257
+ FRAME_HEIGHT = H;
40258
+ });
40259
+
40050
40260
  // ../../node_modules/qrcode-terminal/vendor/QRCode/QRMode.js
40051
40261
  var require_QRMode = __commonJS((exports, module) => {
40052
40262
  module.exports = {
@@ -53713,6 +53923,86 @@ function generatePairingCode() {
53713
53923
  return Array.from(bytes, (b) => CHARS[b % CHARS.length]).join("");
53714
53924
  }
53715
53925
  // src/commands/launch.ts
53926
+ init_colors();
53927
+
53928
+ // src/tui/screen.ts
53929
+ init_version();
53930
+ init_colors();
53931
+ function termSize() {
53932
+ return {
53933
+ cols: process.stdout.columns || 80,
53934
+ rows: process.stdout.rows || 24
53935
+ };
53936
+ }
53937
+ function center(s) {
53938
+ const { cols } = termSize();
53939
+ const vis = visibleLength(s);
53940
+ const pad = Math.max(0, Math.floor((cols - vis) / 2));
53941
+ return " ".repeat(pad) + s;
53942
+ }
53943
+ function writeCentered(row, s) {
53944
+ process.stdout.write(moveTo(row, 1) + center(s) + CLEAR_LINE);
53945
+ }
53946
+ function drawTopBar() {
53947
+ const { cols } = termSize();
53948
+ const left = orange(`claudemesh v${VERSION}`);
53949
+ const right = dim("claudemesh.com");
53950
+ const leftVis = visibleLength(left);
53951
+ const rightVis = visibleLength(right);
53952
+ const gap = Math.max(1, cols - leftVis - rightVis);
53953
+ process.stdout.write(moveTo(1, 1) + left + " ".repeat(gap) + right + CLEAR_LINE);
53954
+ }
53955
+ function enterFullScreen() {
53956
+ process.stdout.write(HIDE_CURSOR + CLEAR_SCREEN);
53957
+ drawTopBar();
53958
+ }
53959
+ function exitFullScreen() {
53960
+ process.stdout.write(SHOW_CURSOR + CLEAR_SCREEN);
53961
+ }
53962
+ async function menuSelect(opts) {
53963
+ const { items, title, row } = opts;
53964
+ let selected = opts.defaultIndex ?? 0;
53965
+ writeCentered(row, bold2(orange(title)));
53966
+ const renderItems = () => {
53967
+ for (let i = 0;i < items.length; i++) {
53968
+ const prefix = i === selected ? boldOrange("▸ ") : " ";
53969
+ const text2 = i === selected ? bold2(items[i]) : dim(items[i]);
53970
+ writeCentered(row + 1 + i, prefix + text2 + CLEAR_LINE);
53971
+ }
53972
+ };
53973
+ renderItems();
53974
+ return new Promise((resolve2) => {
53975
+ const stdin = process.stdin;
53976
+ const wasRaw = stdin.isRaw;
53977
+ stdin.setRawMode(true);
53978
+ stdin.resume();
53979
+ stdin.setEncoding("utf8");
53980
+ const onData = (key) => {
53981
+ if (key === "\x1B[A" || key === "k") {
53982
+ selected = (selected - 1 + items.length) % items.length;
53983
+ renderItems();
53984
+ } else if (key === "\x1B[B" || key === "j") {
53985
+ selected = (selected + 1) % items.length;
53986
+ renderItems();
53987
+ } else if (key === "\r" || key === `
53988
+ `) {
53989
+ stdin.removeListener("data", onData);
53990
+ stdin.setRawMode(wasRaw ?? false);
53991
+ stdin.pause();
53992
+ resolve2(selected);
53993
+ } else if (key === "\x03") {
53994
+ stdin.removeListener("data", onData);
53995
+ stdin.setRawMode(wasRaw ?? false);
53996
+ exitFullScreen();
53997
+ process.exit(0);
53998
+ }
53999
+ };
54000
+ stdin.on("data", onData);
54001
+ });
54002
+ }
54003
+
54004
+ // src/commands/launch.ts
54005
+ init_spinner();
53716
54006
  async function pickMesh(meshes) {
53717
54007
  if (meshes.length === 1)
53718
54008
  return meshes[0];
@@ -53755,21 +54045,21 @@ function askLine(prompt) {
53755
54045
  }
53756
54046
  async function confirmPermissions() {
53757
54047
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
53758
- const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
53759
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
53760
- const yellow = (s) => useColor ? `\x1B[33m${s}\x1B[39m` : s;
53761
- console.log(yellow(bold2(" Autonomous mode")));
54048
+ const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
54049
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54050
+ const yellow2 = (s) => useColor ? `\x1B[33m${s}\x1B[39m` : s;
54051
+ console.log(yellow2(bold3(" Autonomous mode")));
53762
54052
  console.log("");
53763
54053
  console.log(" Claude will run with --dangerously-skip-permissions, bypassing");
53764
54054
  console.log(" ALL permission prompts — not just claudemesh tools.");
53765
54055
  console.log(" Peers exchange text only — no file access, no tool calls.");
53766
54056
  console.log("");
53767
- console.log(dim(" Without -y: only claudemesh tools are pre-approved (via allowedTools)."));
53768
- console.log(dim(" Use -y for autonomous agents. Omit it for shared/multi-person meshes."));
54057
+ console.log(dim2(" Without -y: only claudemesh tools are pre-approved (via allowedTools)."));
54058
+ console.log(dim2(" Use -y for autonomous agents. Omit it for shared/multi-person meshes."));
53769
54059
  console.log("");
53770
54060
  const rl = createInterface({ input: process.stdin, output: process.stdout });
53771
54061
  return new Promise((resolve2, reject) => {
53772
- rl.question(` ${bold2("Continue?")} [Y/n] `, (answer) => {
54062
+ rl.question(` ${bold3("Continue?")} [Y/n] `, (answer) => {
53773
54063
  rl.close();
53774
54064
  const a = answer.trim().toLowerCase();
53775
54065
  if (a === "" || a === "y" || a === "yes") {
@@ -53786,12 +54076,12 @@ async function confirmPermissions() {
53786
54076
  }
53787
54077
  function printBanner(name, meshSlug, role, groups, messageMode) {
53788
54078
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
53789
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
53790
- const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
54079
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54080
+ const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
53791
54081
  const roleSuffix = role ? ` (${role})` : "";
53792
54082
  const groupTags = groups.length ? " [" + groups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`).join(", ") + "]" : "";
53793
54083
  const rule = "─".repeat(60);
53794
- console.log(bold2(`claudemesh launch`) + dim(` — as ${name}${roleSuffix} on ${meshSlug}${groupTags} [${messageMode}]`));
54084
+ console.log(bold3(`claudemesh launch`) + dim2(` — as ${name}${roleSuffix} on ${meshSlug}${groupTags} [${messageMode}]`));
53795
54085
  console.log(rule);
53796
54086
  if (messageMode === "push") {
53797
54087
  console.log("Peer messages arrive as <channel> reminders in real-time.");
@@ -53801,10 +54091,48 @@ function printBanner(name, meshSlug, role, groups, messageMode) {
53801
54091
  console.log("Messages off. Use check_messages to poll manually.");
53802
54092
  }
53803
54093
  console.log("Peers send text only — they cannot call tools or read files.");
53804
- console.log(dim(`Config: ${getConfigPath()}`));
54094
+ console.log(dim2(`Config: ${getConfigPath()}`));
53805
54095
  console.log(rule);
53806
54096
  console.log("");
53807
54097
  }
54098
+ async function showLaunchSplash(name, meshSlug, role, groups, messageMode) {
54099
+ if (!process.stdout.isTTY)
54100
+ return;
54101
+ const { rows } = termSize();
54102
+ enterFullScreen();
54103
+ drawTopBar();
54104
+ const logoTop = Math.floor((rows - FRAME_HEIGHT - 10) / 2);
54105
+ const brandRow = logoTop + FRAME_HEIGHT + 1;
54106
+ const subtitleRow = brandRow + 1;
54107
+ const infoRow = subtitleRow + 2;
54108
+ writeCentered(brandRow, boldOrange("claudemesh"));
54109
+ writeCentered(subtitleRow, dim("peer mesh for Claude Code"));
54110
+ const spinner = createSpinner({
54111
+ render(lines) {
54112
+ for (let i = 0;i < lines.length; i++) {
54113
+ writeCentered(logoTop + i, lines[i]);
54114
+ }
54115
+ },
54116
+ interval: 70
54117
+ });
54118
+ spinner.start();
54119
+ const roleSuffix = role ? ` (${role})` : "";
54120
+ const groupStr = groups.length ? " " + groups.map((g) => dim(`@${g.name}`)).join(", ") : "";
54121
+ const steps = [
54122
+ { label: `Identity`, value: `${name}${roleSuffix}` },
54123
+ { label: `Mesh`, value: meshSlug },
54124
+ { label: `Messages`, value: messageMode }
54125
+ ];
54126
+ for (let i = 0;i < steps.length; i++) {
54127
+ await new Promise((r) => setTimeout(r, 300));
54128
+ writeCentered(infoRow + i, `${steps[i].label} ${green("✓")} ${steps[i].value}${i === 0 ? groupStr : ""}`);
54129
+ }
54130
+ await new Promise((r) => setTimeout(r, 400));
54131
+ writeCentered(infoRow + steps.length + 1, dim("Launching Claude Code..."));
54132
+ await new Promise((r) => setTimeout(r, 600));
54133
+ spinner.stop();
54134
+ exitFullScreen();
54135
+ }
53808
54136
  async function runLaunch(flags, rawArgs) {
53809
54137
  const dashIdx = rawArgs.indexOf("--");
53810
54138
  const claudePassthrough = dashIdx >= 0 ? rawArgs.slice(dashIdx + 1) : [];
@@ -53854,22 +54182,22 @@ async function runLaunch(flags, rawArgs) {
53854
54182
  let justSynced = false;
53855
54183
  if (config2.meshes.length === 0 && !args.joinLink) {
53856
54184
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
53857
- const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
53858
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
53859
- const green = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
54185
+ const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
54186
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54187
+ const green2 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
53860
54188
  const code = generatePairingCode();
53861
54189
  const listener = await startCallbackListener();
53862
54190
  const url = `https://claudemesh.com/cli-auth?port=${listener.port}&code=${code}&action=sync`;
53863
54191
  console.log(`
53864
- ${bold2("Welcome to claudemesh!")} No meshes found.`);
54192
+ ${bold3("Welcome to claudemesh!")} No meshes found.`);
53865
54193
  console.log(` Opening browser to sign in...
53866
54194
  `);
53867
54195
  const opened = await openBrowser(url);
53868
54196
  if (!opened) {
53869
54197
  console.log(` Couldn't open browser automatically.`);
53870
54198
  }
53871
- console.log(` ${dim(`Visit: ${url}`)}`);
53872
- console.log(` ${dim(`Or join with invite: claudemesh launch --join <url>`)}
54199
+ console.log(` ${dim2(`Visit: ${url}`)}`);
54200
+ console.log(` ${dim2(`Or join with invite: claudemesh launch --join <url>`)}
53873
54201
  `);
53874
54202
  const manualPromise = new Promise((resolve2) => {
53875
54203
  const rl = createInterface({ input: process.stdin, output: process.stdout });
@@ -53915,7 +54243,7 @@ async function runLaunch(flags, rawArgs) {
53915
54243
  saveConfig2(config2);
53916
54244
  justSynced = true;
53917
54245
  console.log(`
53918
- ${green("✓")} Synced ${result.meshes.length} mesh(es): ${result.meshes.map((m) => m.slug).join(", ")}
54246
+ ${green2("✓")} Synced ${result.meshes.length} mesh(es): ${result.meshes.map((m) => m.slug).join(", ")}
53919
54247
  `);
53920
54248
  }
53921
54249
  if (config2.meshes.length === 0) {
@@ -54028,9 +54356,11 @@ async function runLaunch(flags, rawArgs) {
54028
54356
  writeFileSync4(join4(tmpDir, "config.json"), JSON.stringify(sessionConfig, null, 2) + `
54029
54357
  `, "utf-8");
54030
54358
  if (!args.quiet) {
54359
+ await showLaunchSplash(displayName, mesh.slug, role, parsedGroups, messageMode);
54031
54360
  printBanner(displayName, mesh.slug, role, parsedGroups, messageMode);
54032
54361
  if (!args.skipPermConfirm) {
54033
54362
  await confirmPermissions();
54363
+ args.skipPermConfirm = true;
54034
54364
  }
54035
54365
  }
54036
54366
  const meshMcpEntries = [];
@@ -54174,79 +54504,7 @@ async function runLaunch(flags, rawArgs) {
54174
54504
  // src/commands/status.ts
54175
54505
  import { statSync as statSync2, existsSync as existsSync4 } from "node:fs";
54176
54506
  init_config();
54177
- // package.json
54178
- var package_default = {
54179
- name: "claudemesh-cli",
54180
- version: "0.9.3",
54181
- description: "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
54182
- keywords: [
54183
- "claude-code",
54184
- "mcp",
54185
- "model-context-protocol",
54186
- "claudemesh",
54187
- "peer-messaging",
54188
- "multi-agent"
54189
- ],
54190
- author: "Alejandro Gutiérrez",
54191
- license: "MIT",
54192
- homepage: "https://claudemesh.com",
54193
- repository: {
54194
- type: "git",
54195
- url: "https://github.com/alezmad/claudemesh.git",
54196
- directory: "apps/cli"
54197
- },
54198
- type: "module",
54199
- bin: {
54200
- claudemesh: "./dist/index.js"
54201
- },
54202
- files: [
54203
- "dist",
54204
- "README.md",
54205
- "LICENSE"
54206
- ],
54207
- publishConfig: {
54208
- access: "public"
54209
- },
54210
- scripts: {
54211
- build: 'bun build src/index.ts --target=node --outfile dist/index.js --banner "#!/usr/bin/env node" && chmod +x dist/index.js',
54212
- clean: "git clean -xdf .cache .turbo dist node_modules",
54213
- dev: "bun --hot src/index.ts",
54214
- start: "bun src/index.ts",
54215
- format: "prettier --check . --ignore-path ../../.gitignore",
54216
- lint: "eslint",
54217
- prepublishOnly: "bun run build",
54218
- test: "vitest run",
54219
- typecheck: "tsc --noEmit"
54220
- },
54221
- prettier: "@turbostarter/prettier-config",
54222
- engines: {
54223
- node: ">=20"
54224
- },
54225
- dependencies: {
54226
- "@modelcontextprotocol/sdk": "1.27.1",
54227
- citty: "0.2.2",
54228
- "libsodium-wrappers": "0.7.15",
54229
- ws: "8.20.0",
54230
- zod: "4.1.13"
54231
- },
54232
- devDependencies: {
54233
- "@turbostarter/eslint-config": "workspace:*",
54234
- "@turbostarter/prettier-config": "workspace:*",
54235
- "@turbostarter/tsconfig": "workspace:*",
54236
- "@turbostarter/vitest-config": "workspace:*",
54237
- "@types/libsodium-wrappers": "0.7.14",
54238
- "@types/ws": "8.5.13",
54239
- eslint: "catalog:",
54240
- prettier: "catalog:",
54241
- typescript: "catalog:",
54242
- vitest: "catalog:"
54243
- }
54244
- };
54245
-
54246
- // src/version.ts
54247
- var VERSION = package_default.version;
54248
-
54249
- // src/commands/status.ts
54507
+ init_version();
54250
54508
  async function probeBroker(url, timeoutMs = 4000) {
54251
54509
  return new Promise((resolve2) => {
54252
54510
  const ws = new wrapper_default(url);
@@ -54271,9 +54529,9 @@ async function probeBroker(url, timeoutMs = 4000) {
54271
54529
  }
54272
54530
  async function runStatus() {
54273
54531
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
54274
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54275
- const green = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
54276
- const red = (s) => useColor ? `\x1B[31m${s}\x1B[39m` : s;
54532
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54533
+ const green2 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
54534
+ const red2 = (s) => useColor ? `\x1B[31m${s}\x1B[39m` : s;
54277
54535
  console.log(`claudemesh status (v${VERSION})`);
54278
54536
  console.log("─".repeat(60));
54279
54537
  const configPath = getConfigPath();
@@ -54287,7 +54545,7 @@ async function runStatus() {
54287
54545
  const config2 = loadConfig();
54288
54546
  if (config2.meshes.length === 0) {
54289
54547
  console.log("");
54290
- console.log(dim("No meshes joined. Run `claudemesh join <invite-url>` to get started."));
54548
+ console.log(dim2("No meshes joined. Run `claudemesh join <invite-url>` to get started."));
54291
54549
  process.exit(0);
54292
54550
  }
54293
54551
  console.log("");
@@ -54304,29 +54562,30 @@ async function runStatus() {
54304
54562
  error: probe.error
54305
54563
  });
54306
54564
  if (probe.ok) {
54307
- console.log(green("reachable"));
54565
+ console.log(green2("reachable"));
54308
54566
  } else {
54309
- console.log(red(`unreachable (${probe.error})`));
54567
+ console.log(red2(`unreachable (${probe.error})`));
54310
54568
  }
54311
54569
  }
54312
54570
  console.log("");
54313
54571
  for (const r of results) {
54314
- console.log(dim(` ${r.slug}: pubkey ${r.pubkey.slice(0, 16)}…`));
54572
+ console.log(dim2(` ${r.slug}: pubkey ${r.pubkey.slice(0, 16)}…`));
54315
54573
  }
54316
54574
  const allOk = results.every((r) => r.reachable);
54317
54575
  console.log("");
54318
54576
  if (allOk) {
54319
- console.log(green("All meshes reachable."));
54577
+ console.log(green2("All meshes reachable."));
54320
54578
  process.exit(0);
54321
54579
  } else {
54322
54580
  const broken = results.filter((r) => !r.reachable).length;
54323
- console.log(red(`${broken} of ${results.length} mesh(es) unreachable.`));
54581
+ console.log(red2(`${broken} of ${results.length} mesh(es) unreachable.`));
54324
54582
  process.exit(1);
54325
54583
  }
54326
54584
  }
54327
54585
 
54328
54586
  // src/commands/doctor.ts
54329
54587
  init_config();
54588
+ init_version();
54330
54589
  import { existsSync as existsSync5, readFileSync as readFileSync4, statSync as statSync3 } from "node:fs";
54331
54590
  import { homedir as homedir5, platform as platform2 } from "node:os";
54332
54591
  import { join as join5 } from "node:path";
@@ -54475,9 +54734,9 @@ function checkKeypairs() {
54475
54734
  }
54476
54735
  async function runDoctor() {
54477
54736
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
54478
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54479
- const green = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
54480
- const red = (s) => useColor ? `\x1B[31m${s}\x1B[39m` : s;
54737
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54738
+ const green2 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
54739
+ const red2 = (s) => useColor ? `\x1B[31m${s}\x1B[39m` : s;
54481
54740
  console.log(`claudemesh doctor (v${VERSION})`);
54482
54741
  console.log("─".repeat(60));
54483
54742
  const checks3 = [
@@ -54489,20 +54748,20 @@ async function runDoctor() {
54489
54748
  checkKeypairs()
54490
54749
  ];
54491
54750
  for (const c of checks3) {
54492
- const mark = c.pass ? green("✓") : red("✗");
54493
- const detail = c.detail ? dim(` (${c.detail})`) : "";
54751
+ const mark = c.pass ? green2("✓") : red2("✗");
54752
+ const detail = c.detail ? dim2(` (${c.detail})`) : "";
54494
54753
  console.log(`${mark} ${c.name}${detail}`);
54495
54754
  if (!c.pass && c.fix) {
54496
- console.log(dim(` → ${c.fix}`));
54755
+ console.log(dim2(` → ${c.fix}`));
54497
54756
  }
54498
54757
  }
54499
54758
  const failing = checks3.filter((c) => !c.pass);
54500
54759
  console.log("");
54501
54760
  if (failing.length === 0) {
54502
- console.log(green("All checks passed."));
54761
+ console.log(green2("All checks passed."));
54503
54762
  process.exit(0);
54504
54763
  } else {
54505
- console.log(red(`${failing.length} check(s) failed.`));
54764
+ console.log(red2(`${failing.length} check(s) failed.`));
54506
54765
  process.exit(1);
54507
54766
  }
54508
54767
  }
@@ -54512,6 +54771,8 @@ init_config();
54512
54771
  import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
54513
54772
  import { homedir as homedir6 } from "node:os";
54514
54773
  import { join as join6 } from "node:path";
54774
+ init_colors();
54775
+ init_spinner();
54515
54776
  function detectState() {
54516
54777
  const claudeConfig = join6(homedir6(), ".claude.json");
54517
54778
  let mcpRegistered = false;
@@ -54530,56 +54791,154 @@ function detectState() {
54530
54791
  return "broken-config";
54531
54792
  }
54532
54793
  }
54533
- function runWelcome() {
54534
- const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
54535
- const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
54536
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54537
- const green = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
54538
- const yellow = (s) => useColor ? `\x1B[33m${s}\x1B[39m` : s;
54539
- console.log(bold2(`claudemesh v${VERSION}`) + dim(" — peer mesh for Claude Code"));
54794
+ async function runWelcome() {
54795
+ if (!process.stdout.isTTY) {
54796
+ return runWelcomePlain();
54797
+ }
54798
+ const state = detectState();
54799
+ const { rows } = termSize();
54800
+ enterFullScreen();
54801
+ drawTopBar();
54802
+ const logoTop = Math.floor((rows - FRAME_HEIGHT - 10) / 2);
54803
+ const brandRow = logoTop + FRAME_HEIGHT + 1;
54804
+ const subtitleRow = brandRow + 1;
54805
+ const contentRow = subtitleRow + 2;
54806
+ writeCentered(brandRow, boldOrange("claudemesh"));
54807
+ writeCentered(subtitleRow, dim("peer mesh for Claude Code"));
54808
+ const spinner = createSpinner({
54809
+ render(lines) {
54810
+ for (let i = 0;i < lines.length; i++) {
54811
+ writeCentered(logoTop + i, lines[i]);
54812
+ }
54813
+ },
54814
+ interval: 70
54815
+ });
54816
+ spinner.start();
54817
+ let menuRow = contentRow;
54818
+ switch (state) {
54819
+ case "no-install": {
54820
+ writeCentered(contentRow, "Welcome. Let's get you set up.");
54821
+ writeCentered(contentRow + 1, "");
54822
+ writeCentered(contentRow + 2, dim("MCP server ") + yellow("○") + dim(" not registered"));
54823
+ writeCentered(contentRow + 3, dim("Mesh ") + dim("○") + dim(" waiting"));
54824
+ menuRow = contentRow + 5;
54825
+ spinner.stop();
54826
+ const choice = await menuSelect({
54827
+ title: "Get started",
54828
+ items: ["Install MCP server", "Cancel"],
54829
+ row: menuRow
54830
+ });
54831
+ exitFullScreen();
54832
+ if (choice === 0) {
54833
+ console.log(green("$") + ` claudemesh install
54834
+ `);
54835
+ }
54836
+ break;
54837
+ }
54838
+ case "no-meshes": {
54839
+ writeCentered(contentRow, green("✓") + " MCP registered. Now join a mesh.");
54840
+ writeCentered(contentRow + 2, dim("MCP server ") + green("✓") + dim(" registered"));
54841
+ writeCentered(contentRow + 3, dim("Mesh ") + yellow("○") + dim(" none joined"));
54842
+ menuRow = contentRow + 5;
54843
+ spinner.stop();
54844
+ const choice = await menuSelect({
54845
+ title: "Next step",
54846
+ items: [
54847
+ "Join with invite URL",
54848
+ "Create a new mesh",
54849
+ "Cancel"
54850
+ ],
54851
+ row: menuRow
54852
+ });
54853
+ exitFullScreen();
54854
+ if (choice === 0) {
54855
+ console.log(green("$") + ` claudemesh join https://claudemesh.com/join/<token>
54856
+ `);
54857
+ console.log(dim(" Don't have an invite? Create one at ") + bold2("https://claudemesh.com") + dim(" or ask a mesh owner."));
54858
+ } else if (choice === 1) {
54859
+ console.log(green("$") + ` claudemesh create
54860
+ `);
54861
+ }
54862
+ break;
54863
+ }
54864
+ case "ready": {
54865
+ const cfg = loadConfig();
54866
+ const meshNames = cfg.meshes.map((m) => m.slug).join(", ");
54867
+ writeCentered(contentRow, green("✓") + " MCP registered");
54868
+ writeCentered(contentRow + 1, green("✓") + ` ${cfg.meshes.length} mesh(es): ${meshNames}`);
54869
+ writeCentered(contentRow + 2, "");
54870
+ writeCentered(contentRow + 3, bold2("Ready to launch."));
54871
+ menuRow = contentRow + 5;
54872
+ spinner.stop();
54873
+ const choice = await menuSelect({
54874
+ title: "What next?",
54875
+ items: [
54876
+ "Launch Claude Code session",
54877
+ "View peers",
54878
+ "Check status",
54879
+ "Run diagnostics",
54880
+ "Exit"
54881
+ ],
54882
+ row: menuRow
54883
+ });
54884
+ exitFullScreen();
54885
+ switch (choice) {
54886
+ case 0:
54887
+ console.log(green("$") + ` claudemesh launch
54888
+ `);
54889
+ break;
54890
+ case 1:
54891
+ console.log(green("$") + ` claudemesh peers
54892
+ `);
54893
+ break;
54894
+ case 2:
54895
+ console.log(green("$") + ` claudemesh status
54896
+ `);
54897
+ break;
54898
+ case 3:
54899
+ console.log(green("$") + ` claudemesh doctor
54900
+ `);
54901
+ break;
54902
+ }
54903
+ break;
54904
+ }
54905
+ case "broken-config": {
54906
+ writeCentered(contentRow, yellow("⚠") + " ~/.claudemesh/config.json is unreadable.");
54907
+ menuRow = contentRow + 2;
54908
+ spinner.stop();
54909
+ const choice = await menuSelect({
54910
+ title: "Recover",
54911
+ items: ["Run diagnostics", "Cancel"],
54912
+ row: menuRow
54913
+ });
54914
+ exitFullScreen();
54915
+ if (choice === 0) {
54916
+ console.log(green("$") + ` claudemesh doctor
54917
+ `);
54918
+ }
54919
+ break;
54920
+ }
54921
+ }
54922
+ }
54923
+ function runWelcomePlain() {
54924
+ const { VERSION: VERSION2 } = (init_version(), __toCommonJS(exports_version));
54925
+ console.log(`claudemesh v${VERSION2} — peer mesh for Claude Code`);
54540
54926
  console.log("─".repeat(60));
54541
54927
  const state = detectState();
54542
54928
  switch (state) {
54543
54929
  case "no-install":
54544
- console.log("Welcome. Let's get you set up.");
54545
- console.log("");
54546
- console.log(bold2("Step 1:") + " register the MCP server + status hooks");
54547
- console.log(` ${green("$")} claudemesh install`);
54548
- console.log("");
54549
- console.log(dim("Step 2 (after restart): claudemesh join <invite-url>"));
54550
- console.log(dim("Step 3: claudemesh launch"));
54930
+ console.log("MCP not registered. Run: claudemesh install");
54551
54931
  break;
54552
54932
  case "no-meshes":
54553
- console.log(green("✓") + " MCP registered. Now join a mesh.");
54554
- console.log("");
54555
- console.log(bold2("Step 2:") + " join a mesh");
54556
- console.log(` ${green("$")} claudemesh join https://claudemesh.com/join/<token>`);
54557
- console.log("");
54558
- console.log(dim(" Don't have an invite? Create one at ") + bold2("https://claudemesh.com") + dim(" or ask a mesh owner."));
54559
- console.log("");
54560
- console.log(dim("Step 3 (after joining): claudemesh launch"));
54933
+ console.log("No meshes joined. Run: claudemesh join <invite-url>");
54561
54934
  break;
54562
54935
  case "ready": {
54563
54936
  const cfg = loadConfig();
54564
- const meshNames = cfg.meshes.map((m) => m.slug).join(", ");
54565
- console.log(green("✓") + " MCP registered.");
54566
- console.log(green("✓") + ` ${cfg.meshes.length} mesh(es) joined: ${meshNames}`);
54567
- console.log("");
54568
- console.log(bold2("You're ready.") + " Launch Claude Code with real-time peer messages:");
54569
- console.log(` ${green("$")} claudemesh launch`);
54570
- console.log("");
54571
- console.log(dim(" (Plain `claude` works too — messages pull-only via check_messages.)"));
54572
- console.log("");
54573
- console.log(dim("Health check: claudemesh status"));
54574
- console.log(dim("Diagnostics: claudemesh doctor"));
54575
- console.log(dim("All commands: claudemesh --help"));
54937
+ console.log(`${cfg.meshes.length} mesh(es) joined. Run: claudemesh launch`);
54576
54938
  break;
54577
54939
  }
54578
54940
  case "broken-config":
54579
- console.log(yellow("⚠") + " Your ~/.claudemesh/config.json is unreadable.");
54580
- console.log("");
54581
- console.log("Run diagnostics to see what's wrong:");
54582
- console.log(` ${green("$")} claudemesh doctor`);
54941
+ console.log("Config unreadable. Run: claudemesh doctor");
54583
54942
  break;
54584
54943
  }
54585
54944
  console.log("");
@@ -54623,10 +54982,10 @@ Joined: ${config2.meshes.map((m) => m.slug).join(", ")}`);
54623
54982
  // src/commands/peers.ts
54624
54983
  async function runPeers(flags) {
54625
54984
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
54626
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54627
- const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
54628
- const green = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
54629
- const yellow = (s) => useColor ? `\x1B[33m${s}\x1B[39m` : s;
54985
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54986
+ const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
54987
+ const green2 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
54988
+ const yellow2 = (s) => useColor ? `\x1B[33m${s}\x1B[39m` : s;
54630
54989
  await withMesh({ meshSlug: flags.mesh ?? null }, async (client2, mesh) => {
54631
54990
  const peers = await client2.listPeers();
54632
54991
  if (flags.json) {
@@ -54634,15 +54993,15 @@ async function runPeers(flags) {
54634
54993
  return;
54635
54994
  }
54636
54995
  if (peers.length === 0) {
54637
- console.log(dim(`No peers connected on mesh "${mesh.slug}".`));
54996
+ console.log(dim2(`No peers connected on mesh "${mesh.slug}".`));
54638
54997
  return;
54639
54998
  }
54640
- console.log(bold2(`Peers on ${mesh.slug}`) + dim(` (${peers.length})`));
54999
+ console.log(bold3(`Peers on ${mesh.slug}`) + dim2(` (${peers.length})`));
54641
55000
  console.log("");
54642
55001
  for (const p of peers) {
54643
55002
  const groups = p.groups.length ? " [" + p.groups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`).join(", ") + "]" : "";
54644
- const statusIcon = p.status === "working" ? yellow("●") : green("●");
54645
- const name = bold2(p.displayName);
55003
+ const statusIcon = p.status === "working" ? yellow2("●") : green2("●");
55004
+ const name = bold3(p.displayName);
54646
55005
  const meta2 = [];
54647
55006
  if (p.peerType)
54648
55007
  meta2.push(p.peerType);
@@ -54650,9 +55009,9 @@ async function runPeers(flags) {
54650
55009
  meta2.push(p.channel);
54651
55010
  if (p.model)
54652
55011
  meta2.push(p.model);
54653
- const metaStr = meta2.length ? dim(` (${meta2.join(", ")})`) : "";
54654
- const cwdStr = p.cwd ? dim(` cwd: ${p.cwd}`) : "";
54655
- const summary = p.summary ? dim(` ${p.summary}`) : "";
55012
+ const metaStr = meta2.length ? dim2(` (${meta2.join(", ")})`) : "";
55013
+ const cwdStr = p.cwd ? dim2(` cwd: ${p.cwd}`) : "";
55014
+ const summary = p.summary ? dim2(` ${p.summary}`) : "";
54656
55015
  console.log(` ${statusIcon} ${name}${groups}${metaStr}${summary}`);
54657
55016
  if (cwdStr)
54658
55017
  console.log(` ${cwdStr}`);
@@ -54688,19 +55047,19 @@ async function runSend(flags, to, message) {
54688
55047
 
54689
55048
  // src/commands/inbox.ts
54690
55049
  function formatMessage(msg, useColor) {
54691
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54692
- const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
55050
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
55051
+ const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
54693
55052
  const text2 = msg.plaintext ?? `[encrypted: ${msg.ciphertext.slice(0, 32)}…]`;
54694
55053
  const from = msg.senderPubkey.slice(0, 8);
54695
55054
  const time3 = new Date(msg.createdAt).toLocaleTimeString();
54696
55055
  const kindTag = msg.kind === "direct" ? "→ direct" : msg.kind;
54697
- return ` ${bold2(from)} ${dim(`[${kindTag}] ${time3}`)}
55056
+ return ` ${bold3(from)} ${dim2(`[${kindTag}] ${time3}`)}
54698
55057
  ${text2}`;
54699
55058
  }
54700
55059
  async function runInbox(flags) {
54701
55060
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
54702
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54703
- const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
55061
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
55062
+ const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
54704
55063
  const waitMs = (flags.wait ?? 1) * 1000;
54705
55064
  await withMesh({ meshSlug: flags.mesh ?? null }, async (client2, mesh) => {
54706
55065
  await new Promise((resolve2) => setTimeout(resolve2, waitMs));
@@ -54710,10 +55069,10 @@ async function runInbox(flags) {
54710
55069
  return;
54711
55070
  }
54712
55071
  if (messages.length === 0) {
54713
- console.log(dim(`No messages on mesh "${mesh.slug}".`));
55072
+ console.log(dim2(`No messages on mesh "${mesh.slug}".`));
54714
55073
  return;
54715
55074
  }
54716
- console.log(bold2(`Inbox — ${mesh.slug}`) + dim(` (${messages.length} message${messages.length === 1 ? "" : "s"})`));
55075
+ console.log(bold3(`Inbox — ${mesh.slug}`) + dim2(` (${messages.length} message${messages.length === 1 ? "" : "s"})`));
54717
55076
  console.log("");
54718
55077
  for (const msg of messages) {
54719
55078
  console.log(formatMessage(msg, useColor));
@@ -54725,11 +55084,11 @@ async function runInbox(flags) {
54725
55084
  // src/commands/state.ts
54726
55085
  async function runStateGet(flags, key) {
54727
55086
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
54728
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
55087
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54729
55088
  await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
54730
55089
  const entry = await client2.getState(key);
54731
55090
  if (!entry) {
54732
- console.log(dim(`(not set)`));
55091
+ console.log(dim2(`(not set)`));
54733
55092
  return;
54734
55093
  }
54735
55094
  if (flags.json) {
@@ -54738,7 +55097,7 @@ async function runStateGet(flags, key) {
54738
55097
  }
54739
55098
  const val = typeof entry.value === "string" ? entry.value : JSON.stringify(entry.value);
54740
55099
  console.log(val);
54741
- console.log(dim(` set by ${entry.updatedBy} at ${new Date(entry.updatedAt).toLocaleString()}`));
55100
+ console.log(dim2(` set by ${entry.updatedBy} at ${new Date(entry.updatedAt).toLocaleString()}`));
54742
55101
  });
54743
55102
  }
54744
55103
  async function runStateSet(flags, key, value) {
@@ -54755,8 +55114,8 @@ async function runStateSet(flags, key, value) {
54755
55114
  }
54756
55115
  async function runStateList(flags) {
54757
55116
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
54758
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54759
- const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
55117
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
55118
+ const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
54760
55119
  await withMesh({ meshSlug: flags.mesh ?? null }, async (client2, mesh) => {
54761
55120
  const entries = await client2.listState();
54762
55121
  if (flags.json) {
@@ -54764,13 +55123,13 @@ async function runStateList(flags) {
54764
55123
  return;
54765
55124
  }
54766
55125
  if (entries.length === 0) {
54767
- console.log(dim(`No state on mesh "${mesh.slug}".`));
55126
+ console.log(dim2(`No state on mesh "${mesh.slug}".`));
54768
55127
  return;
54769
55128
  }
54770
55129
  for (const e of entries) {
54771
55130
  const val = typeof e.value === "string" ? e.value : JSON.stringify(e.value);
54772
- console.log(`${bold2(e.key)}: ${val}`);
54773
- console.log(dim(` ${e.updatedBy} · ${new Date(e.updatedAt).toLocaleString()}`));
55131
+ console.log(`${bold3(e.key)}: ${val}`);
55132
+ console.log(dim2(` ${e.updatedBy} · ${new Date(e.updatedAt).toLocaleString()}`));
54774
55133
  }
54775
55134
  });
54776
55135
  }
@@ -54794,8 +55153,8 @@ async function runRemember(flags, content) {
54794
55153
  }
54795
55154
  async function runRecall(flags, query) {
54796
55155
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
54797
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54798
- const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
55156
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
55157
+ const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
54799
55158
  await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
54800
55159
  const memories = await client2.recall(query);
54801
55160
  if (flags.json) {
@@ -54803,14 +55162,14 @@ async function runRecall(flags, query) {
54803
55162
  return;
54804
55163
  }
54805
55164
  if (memories.length === 0) {
54806
- console.log(dim("No memories found."));
55165
+ console.log(dim2("No memories found."));
54807
55166
  return;
54808
55167
  }
54809
55168
  for (const m of memories) {
54810
- const tags = m.tags.length ? dim(` [${m.tags.join(", ")}]`) : "";
54811
- console.log(`${bold2(m.id.slice(0, 8))}${tags}`);
55169
+ const tags = m.tags.length ? dim2(` [${m.tags.join(", ")}]`) : "";
55170
+ console.log(`${bold3(m.id.slice(0, 8))}${tags}`);
54812
55171
  console.log(` ${m.content}`);
54813
- console.log(dim(` ${m.rememberedBy} · ${new Date(m.rememberedAt).toLocaleString()}`));
55172
+ console.log(dim2(` ${m.rememberedBy} · ${new Date(m.rememberedAt).toLocaleString()}`));
54814
55173
  console.log("");
54815
55174
  }
54816
55175
  });
@@ -54820,8 +55179,8 @@ async function runRecall(flags, query) {
54820
55179
  init_config();
54821
55180
  async function runInfo(flags) {
54822
55181
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
54823
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54824
- const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
55182
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
55183
+ const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
54825
55184
  const config2 = loadConfig();
54826
55185
  await withMesh({ meshSlug: flags.mesh ?? null }, async (client2, mesh) => {
54827
55186
  const [brokerInfo, peers, state] = await Promise.all([
@@ -54843,16 +55202,16 @@ async function runInfo(flags) {
54843
55202
  console.log(JSON.stringify(output, null, 2));
54844
55203
  return;
54845
55204
  }
54846
- console.log(bold2(mesh.slug) + dim(` · ${mesh.brokerUrl}`));
54847
- console.log(dim(` mesh: ${mesh.meshId}`));
54848
- console.log(dim(` member: ${mesh.memberId}`));
55205
+ console.log(bold3(mesh.slug) + dim2(` · ${mesh.brokerUrl}`));
55206
+ console.log(dim2(` mesh: ${mesh.meshId}`));
55207
+ console.log(dim2(` member: ${mesh.memberId}`));
54849
55208
  console.log(` peers: ${peers.length} connected`);
54850
55209
  console.log(` state: ${state.length} keys`);
54851
55210
  if (brokerInfo && typeof brokerInfo === "object") {
54852
55211
  for (const [k, v] of Object.entries(brokerInfo)) {
54853
55212
  if (["slug", "meshId", "brokerUrl"].includes(k))
54854
55213
  continue;
54855
- console.log(dim(` ${k}: ${JSON.stringify(v)}`));
55214
+ console.log(dim2(` ${k}: ${JSON.stringify(v)}`));
54856
55215
  }
54857
55216
  }
54858
55217
  });
@@ -54897,8 +55256,8 @@ function parseDeliverAt(flags) {
54897
55256
  }
54898
55257
  async function runRemind(flags, positional) {
54899
55258
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
54900
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
54901
- const bold2 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
55259
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
55260
+ const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
54902
55261
  const action = positional[0];
54903
55262
  if (action === "list") {
54904
55263
  await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
@@ -54908,14 +55267,14 @@ async function runRemind(flags, positional) {
54908
55267
  return;
54909
55268
  }
54910
55269
  if (scheduled.length === 0) {
54911
- console.log(dim("No pending reminders."));
55270
+ console.log(dim2("No pending reminders."));
54912
55271
  return;
54913
55272
  }
54914
55273
  for (const m of scheduled) {
54915
55274
  const when = new Date(m.deliverAt).toLocaleString();
54916
- const to = m.to === client2.getSessionPubkey() ? dim("(self)") : m.to;
54917
- console.log(` ${bold2(m.id.slice(0, 8))} → ${to} at ${when}`);
54918
- console.log(` ${dim(m.message.slice(0, 80))}`);
55275
+ const to = m.to === client2.getSessionPubkey() ? dim2("(self)") : m.to;
55276
+ console.log(` ${bold3(m.id.slice(0, 8))} → ${to} at ${when}`);
55277
+ console.log(` ${dim2(m.message.slice(0, 80))}`);
54919
55278
  console.log("");
54920
55279
  }
54921
55280
  });
@@ -55128,14 +55487,14 @@ import { hostname as hostname4 } from "node:os";
55128
55487
  init_keypair();
55129
55488
  async function runSync(args) {
55130
55489
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
55131
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
55132
- const green = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
55490
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
55491
+ const green2 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
55133
55492
  const config2 = loadConfig();
55134
55493
  const code = generatePairingCode();
55135
55494
  const listener = await startCallbackListener();
55136
55495
  const url = `https://claudemesh.com/cli-auth?port=${listener.port}&code=${code}&action=sync`;
55137
55496
  console.log(`Opening browser to sync meshes...`);
55138
- console.log(dim(`Visit: ${url}`));
55497
+ console.log(dim2(`Visit: ${url}`));
55139
55498
  await openBrowser(url);
55140
55499
  const manualPromise = new Promise((resolve2) => {
55141
55500
  const rl = createInterface2({ input: process.stdin, output: process.stdout });
@@ -55180,7 +55539,7 @@ async function runSync(args) {
55180
55539
  config2.accountId = result.account_id;
55181
55540
  saveConfig(config2);
55182
55541
  if (added > 0) {
55183
- console.log(green(`✓ Added ${added} new mesh(es)`));
55542
+ console.log(green2(`✓ Added ${added} new mesh(es)`));
55184
55543
  } else {
55185
55544
  console.log(`Already up to date (${config2.meshes.length} meshes)`);
55186
55545
  }
@@ -55190,8 +55549,8 @@ async function runSync(args) {
55190
55549
  init_config();
55191
55550
  async function runProfile(flags) {
55192
55551
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
55193
- const dim = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
55194
- const green = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
55552
+ const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
55553
+ const green2 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
55195
55554
  const config2 = loadConfig();
55196
55555
  if (config2.meshes.length === 0) {
55197
55556
  console.error("No meshes joined. Run `claudemesh join <url>` first.");
@@ -55231,9 +55590,9 @@ async function runProfile(flags) {
55231
55590
  if (flags.json) {
55232
55591
  console.log(JSON.stringify(result, null, 2));
55233
55592
  } else if (result.ok) {
55234
- console.log(green("✓ Profile updated"));
55593
+ console.log(green2("✓ Profile updated"));
55235
55594
  const member = result.member;
55236
- printProfile(member, dim);
55595
+ printProfile(member, dim2);
55237
55596
  } else {
55238
55597
  console.error(`Error: ${result.error}`);
55239
55598
  process.exit(1);
@@ -55249,21 +55608,21 @@ async function runProfile(flags) {
55249
55608
  if (flags.json) {
55250
55609
  console.log(JSON.stringify(me ?? {}, null, 2));
55251
55610
  } else if (me) {
55252
- printProfile(me, dim);
55611
+ printProfile(me, dim2);
55253
55612
  } else {
55254
55613
  console.log("Member not found in mesh.");
55255
55614
  }
55256
55615
  }
55257
55616
  }
55258
- function printProfile(member, dim) {
55617
+ function printProfile(member, dim2) {
55259
55618
  const groups = member.groups;
55260
- const groupStr = groups?.length ? groups.map((g) => g.role ? `${g.name} (${g.role})` : g.name).join(", ") : dim("(none)");
55261
- console.log(` Name: ${member.displayName ?? dim("(not set)")}`);
55262
- console.log(` Role: ${member.roleTag ?? dim("(not set)")}`);
55619
+ const groupStr = groups?.length ? groups.map((g) => g.role ? `${g.name} (${g.role})` : g.name).join(", ") : dim2("(none)");
55620
+ console.log(` Name: ${member.displayName ?? dim2("(not set)")}`);
55621
+ console.log(` Role: ${member.roleTag ?? dim2("(not set)")}`);
55263
55622
  console.log(` Groups: ${groupStr}`);
55264
55623
  console.log(` Messages: ${member.messageMode ?? "push"}`);
55265
55624
  console.log(` Access: ${member.permission ?? "member"}`);
55266
- console.log(` Mesh: ${dim(String(member.id ?? ""))}`);
55625
+ console.log(` Mesh: ${dim2(String(member.id ?? ""))}`);
55267
55626
  }
55268
55627
 
55269
55628
  // src/commands/connect-telegram.ts
@@ -55323,6 +55682,7 @@ async function disconnectTelegram() {
55323
55682
  }
55324
55683
 
55325
55684
  // src/index.ts
55685
+ init_version();
55326
55686
  var launch = defineCommand({
55327
55687
  meta: {
55328
55688
  name: "launch",
@@ -55657,8 +56017,8 @@ var main = defineCommand({
55657
56017
  }
55658
56018
  })
55659
56019
  },
55660
- run() {
55661
- runWelcome();
56020
+ async run() {
56021
+ await runWelcome();
55662
56022
  }
55663
56023
  });
55664
56024
  runMain(main);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudemesh-cli",
3
- "version": "0.9.3",
3
+ "version": "0.9.4",
4
4
  "description": "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -48,8 +48,8 @@
48
48
  "prettier": "3.6.2",
49
49
  "typescript": "5.9.3",
50
50
  "vitest": "4.0.14",
51
- "@turbostarter/eslint-config": "0.1.0",
52
51
  "@turbostarter/prettier-config": "0.1.0",
52
+ "@turbostarter/eslint-config": "0.1.0",
53
53
  "@turbostarter/vitest-config": "0.1.0",
54
54
  "@turbostarter/tsconfig": "0.1.0"
55
55
  },