claudemesh-cli 0.9.3 → 0.9.5
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/index.js +730 -267
- package/package.json +4 -4
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, green2, 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
|
+
green2 = 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.5",
|
|
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,177 @@ 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(extra) {
|
|
53947
|
+
const { cols } = termSize();
|
|
53948
|
+
const bg = "\x1B[48;5;208m\x1B[30m";
|
|
53949
|
+
const reset = "\x1B[0m";
|
|
53950
|
+
const left = ` claudemesh v${VERSION}`;
|
|
53951
|
+
const right = `claudemesh.com `;
|
|
53952
|
+
const mid = extra ? ` ${extra}` : "";
|
|
53953
|
+
const gap = Math.max(1, cols - left.length - right.length - mid.length);
|
|
53954
|
+
process.stdout.write(moveTo(1, 1) + bg + left + mid + " ".repeat(gap) + right + reset);
|
|
53955
|
+
}
|
|
53956
|
+
function drawBottomBar(left, right) {
|
|
53957
|
+
const { cols, rows } = termSize();
|
|
53958
|
+
const bg = "\x1B[48;5;208m\x1B[30m";
|
|
53959
|
+
const reset = "\x1B[0m";
|
|
53960
|
+
const l = ` ${left}`;
|
|
53961
|
+
const r = right ? `${right} ` : "";
|
|
53962
|
+
const gap = Math.max(1, cols - l.length - r.length);
|
|
53963
|
+
process.stdout.write(moveTo(rows, 1) + bg + l + " ".repeat(gap) + r + reset);
|
|
53964
|
+
}
|
|
53965
|
+
function enterFullScreen() {
|
|
53966
|
+
process.stdout.write(HIDE_CURSOR + CLEAR_SCREEN);
|
|
53967
|
+
drawTopBar();
|
|
53968
|
+
}
|
|
53969
|
+
function exitFullScreen() {
|
|
53970
|
+
process.stdout.write(SHOW_CURSOR + CLEAR_SCREEN);
|
|
53971
|
+
}
|
|
53972
|
+
async function menuSelect(opts) {
|
|
53973
|
+
const { items, title, row } = opts;
|
|
53974
|
+
let selected = opts.defaultIndex ?? 0;
|
|
53975
|
+
writeCentered(row, bold2(orange(title)));
|
|
53976
|
+
const renderItems = () => {
|
|
53977
|
+
for (let i = 0;i < items.length; i++) {
|
|
53978
|
+
const prefix = i === selected ? boldOrange("▸ ") : " ";
|
|
53979
|
+
const text2 = i === selected ? bold2(items[i]) : dim(items[i]);
|
|
53980
|
+
writeCentered(row + 1 + i, prefix + text2 + CLEAR_LINE);
|
|
53981
|
+
}
|
|
53982
|
+
};
|
|
53983
|
+
renderItems();
|
|
53984
|
+
return new Promise((resolve2) => {
|
|
53985
|
+
const stdin = process.stdin;
|
|
53986
|
+
const wasRaw = stdin.isRaw;
|
|
53987
|
+
stdin.setRawMode(true);
|
|
53988
|
+
stdin.resume();
|
|
53989
|
+
stdin.setEncoding("utf8");
|
|
53990
|
+
const onData = (key) => {
|
|
53991
|
+
if (key === "\x1B[A" || key === "k") {
|
|
53992
|
+
selected = (selected - 1 + items.length) % items.length;
|
|
53993
|
+
renderItems();
|
|
53994
|
+
} else if (key === "\x1B[B" || key === "j") {
|
|
53995
|
+
selected = (selected + 1) % items.length;
|
|
53996
|
+
renderItems();
|
|
53997
|
+
} else if (key === "\r" || key === `
|
|
53998
|
+
`) {
|
|
53999
|
+
stdin.removeListener("data", onData);
|
|
54000
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
54001
|
+
stdin.pause();
|
|
54002
|
+
resolve2(selected);
|
|
54003
|
+
} else if (key === "\x03") {
|
|
54004
|
+
stdin.removeListener("data", onData);
|
|
54005
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
54006
|
+
exitFullScreen();
|
|
54007
|
+
process.exit(0);
|
|
54008
|
+
}
|
|
54009
|
+
};
|
|
54010
|
+
stdin.on("data", onData);
|
|
54011
|
+
});
|
|
54012
|
+
}
|
|
54013
|
+
async function textInput(opts) {
|
|
54014
|
+
const { label, row, placeholder } = opts;
|
|
54015
|
+
let value = "";
|
|
54016
|
+
const render = () => {
|
|
54017
|
+
const display = value || dim(placeholder ?? "");
|
|
54018
|
+
const cursor = SHOW_CURSOR;
|
|
54019
|
+
writeCentered(row, `${bold2(label)} ${display}${CLEAR_LINE}`);
|
|
54020
|
+
const fullText = `${label.replace(/\x1b\[[^m]*m/g, "")} ${value}`;
|
|
54021
|
+
const { cols } = termSize();
|
|
54022
|
+
const leftPad = Math.max(0, Math.floor((cols - fullText.length) / 2));
|
|
54023
|
+
process.stdout.write(moveTo(row, leftPad + fullText.length + 1) + cursor);
|
|
54024
|
+
};
|
|
54025
|
+
process.stdout.write(SHOW_CURSOR);
|
|
54026
|
+
render();
|
|
54027
|
+
return new Promise((resolve2) => {
|
|
54028
|
+
const stdin = process.stdin;
|
|
54029
|
+
const wasRaw = stdin.isRaw;
|
|
54030
|
+
stdin.setRawMode(true);
|
|
54031
|
+
stdin.resume();
|
|
54032
|
+
stdin.setEncoding("utf8");
|
|
54033
|
+
const onData = (key) => {
|
|
54034
|
+
if (key === "\r" || key === `
|
|
54035
|
+
`) {
|
|
54036
|
+
stdin.removeListener("data", onData);
|
|
54037
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
54038
|
+
stdin.pause();
|
|
54039
|
+
process.stdout.write(HIDE_CURSOR);
|
|
54040
|
+
const final = value || dim("skipped");
|
|
54041
|
+
writeCentered(row, `${label} ${green("✓")} ${final}${CLEAR_LINE}`);
|
|
54042
|
+
resolve2(value);
|
|
54043
|
+
} else if (key === "" || key === "\b") {
|
|
54044
|
+
value = value.slice(0, -1);
|
|
54045
|
+
render();
|
|
54046
|
+
} else if (key === "\x03") {
|
|
54047
|
+
stdin.removeListener("data", onData);
|
|
54048
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
54049
|
+
exitFullScreen();
|
|
54050
|
+
process.exit(0);
|
|
54051
|
+
} else if (key === "\x1B") {
|
|
54052
|
+
stdin.removeListener("data", onData);
|
|
54053
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
54054
|
+
stdin.pause();
|
|
54055
|
+
process.stdout.write(HIDE_CURSOR);
|
|
54056
|
+
writeCentered(row, `${label} ${dim("skipped")}${CLEAR_LINE}`);
|
|
54057
|
+
resolve2("");
|
|
54058
|
+
} else if (key >= " " && key <= "~") {
|
|
54059
|
+
value += key;
|
|
54060
|
+
render();
|
|
54061
|
+
}
|
|
54062
|
+
};
|
|
54063
|
+
stdin.on("data", onData);
|
|
54064
|
+
});
|
|
54065
|
+
}
|
|
54066
|
+
async function confirmPrompt(opts) {
|
|
54067
|
+
const { message, row } = opts;
|
|
54068
|
+
const defaultYes = opts.defaultYes ?? true;
|
|
54069
|
+
const hint = defaultYes ? `${bold2("Y")}/${dim("n")}` : `${dim("y")}/${bold2("N")}`;
|
|
54070
|
+
writeCentered(row, `${message} [${hint}]`);
|
|
54071
|
+
process.stdout.write(SHOW_CURSOR);
|
|
54072
|
+
return new Promise((resolve2) => {
|
|
54073
|
+
const stdin = process.stdin;
|
|
54074
|
+
const wasRaw = stdin.isRaw;
|
|
54075
|
+
stdin.setRawMode(true);
|
|
54076
|
+
stdin.resume();
|
|
54077
|
+
stdin.setEncoding("utf8");
|
|
54078
|
+
const onData = (key) => {
|
|
54079
|
+
stdin.removeListener("data", onData);
|
|
54080
|
+
stdin.setRawMode(wasRaw ?? false);
|
|
54081
|
+
stdin.pause();
|
|
54082
|
+
process.stdout.write(HIDE_CURSOR);
|
|
54083
|
+
if (key === "\x03") {
|
|
54084
|
+
exitFullScreen();
|
|
54085
|
+
process.exit(0);
|
|
54086
|
+
}
|
|
54087
|
+
const yes = key === "y" || key === "Y" || key === "\r" && defaultYes;
|
|
54088
|
+
writeCentered(row, `${message} ${yes ? green("✓ yes") : dim("✗ no")}${CLEAR_LINE}`);
|
|
54089
|
+
resolve2(yes);
|
|
54090
|
+
};
|
|
54091
|
+
stdin.on("data", onData);
|
|
54092
|
+
});
|
|
54093
|
+
}
|
|
54094
|
+
|
|
54095
|
+
// src/commands/launch.ts
|
|
54096
|
+
init_spinner();
|
|
53716
54097
|
async function pickMesh(meshes) {
|
|
53717
54098
|
if (meshes.length === 1)
|
|
53718
54099
|
return meshes[0];
|
|
@@ -53744,54 +54125,124 @@ function parseGroupsString(raw) {
|
|
|
53744
54125
|
return { name: token.slice(0, idx), role: token.slice(idx + 1) };
|
|
53745
54126
|
});
|
|
53746
54127
|
}
|
|
53747
|
-
function
|
|
53748
|
-
|
|
53749
|
-
|
|
53750
|
-
|
|
53751
|
-
|
|
53752
|
-
|
|
53753
|
-
|
|
53754
|
-
|
|
53755
|
-
}
|
|
53756
|
-
|
|
53757
|
-
|
|
53758
|
-
|
|
53759
|
-
|
|
53760
|
-
const
|
|
53761
|
-
|
|
53762
|
-
|
|
53763
|
-
|
|
53764
|
-
|
|
53765
|
-
|
|
53766
|
-
|
|
53767
|
-
|
|
53768
|
-
|
|
53769
|
-
|
|
53770
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
53771
|
-
return new Promise((resolve2, reject) => {
|
|
53772
|
-
rl.question(` ${bold2("Continue?")} [Y/n] `, (answer) => {
|
|
53773
|
-
rl.close();
|
|
53774
|
-
const a = answer.trim().toLowerCase();
|
|
53775
|
-
if (a === "" || a === "y" || a === "yes") {
|
|
53776
|
-
resolve2();
|
|
53777
|
-
} else {
|
|
53778
|
-
console.log(`
|
|
53779
|
-
Aborted. Run without autonomous mode:`);
|
|
53780
|
-
console.log(` claude --dangerously-load-development-channels server:claudemesh
|
|
53781
|
-
`);
|
|
53782
|
-
process.exit(0);
|
|
54128
|
+
async function runLaunchWizard(opts) {
|
|
54129
|
+
if (!process.stdout.isTTY) {
|
|
54130
|
+
return {
|
|
54131
|
+
role: opts.existingRole,
|
|
54132
|
+
groups: opts.existingGroups,
|
|
54133
|
+
messageMode: opts.existingMessageMode ?? "push",
|
|
54134
|
+
skipPermissions: opts.skipPermConfirm
|
|
54135
|
+
};
|
|
54136
|
+
}
|
|
54137
|
+
const { rows } = termSize();
|
|
54138
|
+
enterFullScreen();
|
|
54139
|
+
drawTopBar();
|
|
54140
|
+
drawBottomBar("↑↓ navigate ⏎ select esc skip ctrl-c quit", `mesh: ${opts.meshSlug}`);
|
|
54141
|
+
const logoTop = Math.floor((rows - FRAME_HEIGHT - 16) / 2);
|
|
54142
|
+
const brandRow = logoTop + FRAME_HEIGHT + 1;
|
|
54143
|
+
const subtitleRow = brandRow + 1;
|
|
54144
|
+
const formRow = subtitleRow + 2;
|
|
54145
|
+
writeCentered(brandRow, boldOrange("claudemesh"));
|
|
54146
|
+
writeCentered(subtitleRow, dim("peer mesh for Claude Code"));
|
|
54147
|
+
const spinner = createSpinner({
|
|
54148
|
+
render(lines) {
|
|
54149
|
+
for (let i = 0;i < lines.length; i++) {
|
|
54150
|
+
writeCentered(logoTop + i, lines[i]);
|
|
53783
54151
|
}
|
|
53784
|
-
}
|
|
54152
|
+
},
|
|
54153
|
+
interval: 70
|
|
53785
54154
|
});
|
|
54155
|
+
spinner.start();
|
|
54156
|
+
let row = formRow;
|
|
54157
|
+
writeCentered(row, `Directory ${green2("✓")} ${process.cwd()}`);
|
|
54158
|
+
row++;
|
|
54159
|
+
writeCentered(row, `Name ${green2("✓")} ${opts.displayName}`);
|
|
54160
|
+
row++;
|
|
54161
|
+
writeCentered(row, `Mesh ${green2("✓")} ${opts.meshSlug}`);
|
|
54162
|
+
row += 2;
|
|
54163
|
+
let role = opts.existingRole;
|
|
54164
|
+
let groups = opts.existingGroups;
|
|
54165
|
+
let messageMode = opts.existingMessageMode ?? "push";
|
|
54166
|
+
if (role === null) {
|
|
54167
|
+
spinner.stop();
|
|
54168
|
+
const answer = await textInput({ label: "Role", row, placeholder: "optional — press Enter to skip" });
|
|
54169
|
+
if (answer)
|
|
54170
|
+
role = answer;
|
|
54171
|
+
spinner.start();
|
|
54172
|
+
row++;
|
|
54173
|
+
} else {
|
|
54174
|
+
writeCentered(row, `Role ${green2("✓")} ${role}`);
|
|
54175
|
+
row++;
|
|
54176
|
+
}
|
|
54177
|
+
if (groups.length === 0) {
|
|
54178
|
+
spinner.stop();
|
|
54179
|
+
const answer = await textInput({ label: "Groups", row, placeholder: "comma-separated, optional" });
|
|
54180
|
+
if (answer)
|
|
54181
|
+
groups = parseGroupsString(answer);
|
|
54182
|
+
spinner.start();
|
|
54183
|
+
row++;
|
|
54184
|
+
} else {
|
|
54185
|
+
const tags = groups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`).join(", ");
|
|
54186
|
+
writeCentered(row, `Groups ${green2("✓")} ${tags}`);
|
|
54187
|
+
row++;
|
|
54188
|
+
}
|
|
54189
|
+
if (opts.existingMessageMode === null) {
|
|
54190
|
+
row++;
|
|
54191
|
+
spinner.stop();
|
|
54192
|
+
const choice = await menuSelect({
|
|
54193
|
+
title: "Message mode",
|
|
54194
|
+
items: [
|
|
54195
|
+
"Push (real-time, peers can interrupt)",
|
|
54196
|
+
"Inbox (held until you check)",
|
|
54197
|
+
"Off (tools only, no messages)"
|
|
54198
|
+
],
|
|
54199
|
+
row
|
|
54200
|
+
});
|
|
54201
|
+
messageMode = ["push", "inbox", "off"][choice];
|
|
54202
|
+
spinner.start();
|
|
54203
|
+
row += 5;
|
|
54204
|
+
} else {
|
|
54205
|
+
writeCentered(row, `Messages ${green2("✓")} ${messageMode}`);
|
|
54206
|
+
row++;
|
|
54207
|
+
}
|
|
54208
|
+
let skipPermissions = opts.skipPermConfirm;
|
|
54209
|
+
if (!skipPermissions) {
|
|
54210
|
+
row++;
|
|
54211
|
+
spinner.stop();
|
|
54212
|
+
writeCentered(row, dim("Claude will run with --dangerously-skip-permissions,"));
|
|
54213
|
+
writeCentered(row + 1, dim("bypassing ALL permission prompts — not just claudemesh."));
|
|
54214
|
+
row += 3;
|
|
54215
|
+
const confirmed = await confirmPrompt({
|
|
54216
|
+
message: boldOrange("Autonomous mode?"),
|
|
54217
|
+
row,
|
|
54218
|
+
defaultYes: true
|
|
54219
|
+
});
|
|
54220
|
+
if (!confirmed) {
|
|
54221
|
+
exitFullScreen();
|
|
54222
|
+
console.log(" Run without autonomous mode:");
|
|
54223
|
+
console.log(` claude --dangerously-load-development-channels server:claudemesh
|
|
54224
|
+
`);
|
|
54225
|
+
process.exit(0);
|
|
54226
|
+
}
|
|
54227
|
+
skipPermissions = true;
|
|
54228
|
+
spinner.start();
|
|
54229
|
+
}
|
|
54230
|
+
row += 2;
|
|
54231
|
+
writeCentered(row, dim("Launching Claude Code..."));
|
|
54232
|
+
drawBottomBar(`${opts.displayName} on ${opts.meshSlug}`, `mode: ${messageMode}`);
|
|
54233
|
+
await new Promise((r) => setTimeout(r, 800));
|
|
54234
|
+
spinner.stop();
|
|
54235
|
+
exitFullScreen();
|
|
54236
|
+
return { role, groups, messageMode, skipPermissions };
|
|
53786
54237
|
}
|
|
53787
54238
|
function printBanner(name, meshSlug, role, groups, messageMode) {
|
|
53788
54239
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
53789
|
-
const
|
|
53790
|
-
const
|
|
54240
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
54241
|
+
const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
53791
54242
|
const roleSuffix = role ? ` (${role})` : "";
|
|
53792
54243
|
const groupTags = groups.length ? " [" + groups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`).join(", ") + "]" : "";
|
|
53793
54244
|
const rule = "─".repeat(60);
|
|
53794
|
-
console.log(
|
|
54245
|
+
console.log(bold3(`claudemesh launch`) + dim2(` — as ${name}${roleSuffix} on ${meshSlug}${groupTags} [${messageMode}]`));
|
|
53795
54246
|
console.log(rule);
|
|
53796
54247
|
if (messageMode === "push") {
|
|
53797
54248
|
console.log("Peer messages arrive as <channel> reminders in real-time.");
|
|
@@ -53801,7 +54252,7 @@ function printBanner(name, meshSlug, role, groups, messageMode) {
|
|
|
53801
54252
|
console.log("Messages off. Use check_messages to poll manually.");
|
|
53802
54253
|
}
|
|
53803
54254
|
console.log("Peers send text only — they cannot call tools or read files.");
|
|
53804
|
-
console.log(
|
|
54255
|
+
console.log(dim2(`Config: ${getConfigPath()}`));
|
|
53805
54256
|
console.log(rule);
|
|
53806
54257
|
console.log("");
|
|
53807
54258
|
}
|
|
@@ -53854,22 +54305,22 @@ async function runLaunch(flags, rawArgs) {
|
|
|
53854
54305
|
let justSynced = false;
|
|
53855
54306
|
if (config2.meshes.length === 0 && !args.joinLink) {
|
|
53856
54307
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
53857
|
-
const
|
|
53858
|
-
const
|
|
53859
|
-
const
|
|
54308
|
+
const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
54309
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
54310
|
+
const green3 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
|
|
53860
54311
|
const code = generatePairingCode();
|
|
53861
54312
|
const listener = await startCallbackListener();
|
|
53862
54313
|
const url = `https://claudemesh.com/cli-auth?port=${listener.port}&code=${code}&action=sync`;
|
|
53863
54314
|
console.log(`
|
|
53864
|
-
${
|
|
54315
|
+
${bold3("Welcome to claudemesh!")} No meshes found.`);
|
|
53865
54316
|
console.log(` Opening browser to sign in...
|
|
53866
54317
|
`);
|
|
53867
54318
|
const opened = await openBrowser(url);
|
|
53868
54319
|
if (!opened) {
|
|
53869
54320
|
console.log(` Couldn't open browser automatically.`);
|
|
53870
54321
|
}
|
|
53871
|
-
console.log(` ${
|
|
53872
|
-
console.log(` ${
|
|
54322
|
+
console.log(` ${dim2(`Visit: ${url}`)}`);
|
|
54323
|
+
console.log(` ${dim2(`Or join with invite: claudemesh launch --join <url>`)}
|
|
53873
54324
|
`);
|
|
53874
54325
|
const manualPromise = new Promise((resolve2) => {
|
|
53875
54326
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -53915,7 +54366,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
53915
54366
|
saveConfig2(config2);
|
|
53916
54367
|
justSynced = true;
|
|
53917
54368
|
console.log(`
|
|
53918
|
-
${
|
|
54369
|
+
${green3("✓")} Synced ${result.meshes.length} mesh(es): ${result.meshes.map((m) => m.slug).join(", ")}
|
|
53919
54370
|
`);
|
|
53920
54371
|
}
|
|
53921
54372
|
if (config2.meshes.length === 0) {
|
|
@@ -53938,34 +54389,18 @@ async function runLaunch(flags, rawArgs) {
|
|
|
53938
54389
|
let parsedGroups = args.groups ? parseGroupsString(args.groups) : [];
|
|
53939
54390
|
let messageMode = args.messageMode ?? "push";
|
|
53940
54391
|
if (!args.quiet && !justSynced) {
|
|
53941
|
-
|
|
53942
|
-
|
|
53943
|
-
|
|
53944
|
-
|
|
53945
|
-
|
|
53946
|
-
|
|
53947
|
-
|
|
53948
|
-
|
|
53949
|
-
|
|
53950
|
-
|
|
53951
|
-
|
|
53952
|
-
|
|
53953
|
-
Message mode:`);
|
|
53954
|
-
console.log(" 1) Push (real-time, peers can interrupt your work)");
|
|
53955
|
-
console.log(" 2) Inbox (held until you check, notification only)");
|
|
53956
|
-
console.log(" 3) Off (tools only, no messages)");
|
|
53957
|
-
console.log("");
|
|
53958
|
-
const answer = await askLine(" Choice [1]: ");
|
|
53959
|
-
const choice = parseInt(answer || "1", 10);
|
|
53960
|
-
if (choice === 2)
|
|
53961
|
-
messageMode = "inbox";
|
|
53962
|
-
else if (choice === 3)
|
|
53963
|
-
messageMode = "off";
|
|
53964
|
-
else
|
|
53965
|
-
messageMode = "push";
|
|
53966
|
-
}
|
|
53967
|
-
if (role || parsedGroups.length)
|
|
53968
|
-
console.log("");
|
|
54392
|
+
const wizardResult = await runLaunchWizard({
|
|
54393
|
+
displayName,
|
|
54394
|
+
meshSlug: mesh.slug,
|
|
54395
|
+
existingRole: args.role,
|
|
54396
|
+
existingGroups: parsedGroups,
|
|
54397
|
+
existingMessageMode: args.messageMode ?? null,
|
|
54398
|
+
skipPermConfirm: args.skipPermConfirm
|
|
54399
|
+
});
|
|
54400
|
+
role = wizardResult.role;
|
|
54401
|
+
parsedGroups = wizardResult.groups;
|
|
54402
|
+
messageMode = wizardResult.messageMode;
|
|
54403
|
+
args.skipPermConfirm = wizardResult.skipPermissions;
|
|
53969
54404
|
}
|
|
53970
54405
|
const tmpBase = tmpdir();
|
|
53971
54406
|
try {
|
|
@@ -54029,9 +54464,6 @@ async function runLaunch(flags, rawArgs) {
|
|
|
54029
54464
|
`, "utf-8");
|
|
54030
54465
|
if (!args.quiet) {
|
|
54031
54466
|
printBanner(displayName, mesh.slug, role, parsedGroups, messageMode);
|
|
54032
|
-
if (!args.skipPermConfirm) {
|
|
54033
|
-
await confirmPermissions();
|
|
54034
|
-
}
|
|
54035
54467
|
}
|
|
54036
54468
|
const meshMcpEntries = [];
|
|
54037
54469
|
if (serviceCatalog.length > 0) {
|
|
@@ -54174,79 +54606,7 @@ async function runLaunch(flags, rawArgs) {
|
|
|
54174
54606
|
// src/commands/status.ts
|
|
54175
54607
|
import { statSync as statSync2, existsSync as existsSync4 } from "node:fs";
|
|
54176
54608
|
init_config();
|
|
54177
|
-
|
|
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
|
|
54609
|
+
init_version();
|
|
54250
54610
|
async function probeBroker(url, timeoutMs = 4000) {
|
|
54251
54611
|
return new Promise((resolve2) => {
|
|
54252
54612
|
const ws = new wrapper_default(url);
|
|
@@ -54271,9 +54631,9 @@ async function probeBroker(url, timeoutMs = 4000) {
|
|
|
54271
54631
|
}
|
|
54272
54632
|
async function runStatus() {
|
|
54273
54633
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
54274
|
-
const
|
|
54275
|
-
const
|
|
54276
|
-
const
|
|
54634
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
54635
|
+
const green3 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
|
|
54636
|
+
const red2 = (s) => useColor ? `\x1B[31m${s}\x1B[39m` : s;
|
|
54277
54637
|
console.log(`claudemesh status (v${VERSION})`);
|
|
54278
54638
|
console.log("─".repeat(60));
|
|
54279
54639
|
const configPath = getConfigPath();
|
|
@@ -54287,7 +54647,7 @@ async function runStatus() {
|
|
|
54287
54647
|
const config2 = loadConfig();
|
|
54288
54648
|
if (config2.meshes.length === 0) {
|
|
54289
54649
|
console.log("");
|
|
54290
|
-
console.log(
|
|
54650
|
+
console.log(dim2("No meshes joined. Run `claudemesh join <invite-url>` to get started."));
|
|
54291
54651
|
process.exit(0);
|
|
54292
54652
|
}
|
|
54293
54653
|
console.log("");
|
|
@@ -54304,29 +54664,30 @@ async function runStatus() {
|
|
|
54304
54664
|
error: probe.error
|
|
54305
54665
|
});
|
|
54306
54666
|
if (probe.ok) {
|
|
54307
|
-
console.log(
|
|
54667
|
+
console.log(green3("reachable"));
|
|
54308
54668
|
} else {
|
|
54309
|
-
console.log(
|
|
54669
|
+
console.log(red2(`unreachable (${probe.error})`));
|
|
54310
54670
|
}
|
|
54311
54671
|
}
|
|
54312
54672
|
console.log("");
|
|
54313
54673
|
for (const r of results) {
|
|
54314
|
-
console.log(
|
|
54674
|
+
console.log(dim2(` ${r.slug}: pubkey ${r.pubkey.slice(0, 16)}…`));
|
|
54315
54675
|
}
|
|
54316
54676
|
const allOk = results.every((r) => r.reachable);
|
|
54317
54677
|
console.log("");
|
|
54318
54678
|
if (allOk) {
|
|
54319
|
-
console.log(
|
|
54679
|
+
console.log(green3("All meshes reachable."));
|
|
54320
54680
|
process.exit(0);
|
|
54321
54681
|
} else {
|
|
54322
54682
|
const broken = results.filter((r) => !r.reachable).length;
|
|
54323
|
-
console.log(
|
|
54683
|
+
console.log(red2(`${broken} of ${results.length} mesh(es) unreachable.`));
|
|
54324
54684
|
process.exit(1);
|
|
54325
54685
|
}
|
|
54326
54686
|
}
|
|
54327
54687
|
|
|
54328
54688
|
// src/commands/doctor.ts
|
|
54329
54689
|
init_config();
|
|
54690
|
+
init_version();
|
|
54330
54691
|
import { existsSync as existsSync5, readFileSync as readFileSync4, statSync as statSync3 } from "node:fs";
|
|
54331
54692
|
import { homedir as homedir5, platform as platform2 } from "node:os";
|
|
54332
54693
|
import { join as join5 } from "node:path";
|
|
@@ -54475,9 +54836,9 @@ function checkKeypairs() {
|
|
|
54475
54836
|
}
|
|
54476
54837
|
async function runDoctor() {
|
|
54477
54838
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
54478
|
-
const
|
|
54479
|
-
const
|
|
54480
|
-
const
|
|
54839
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
54840
|
+
const green3 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
|
|
54841
|
+
const red2 = (s) => useColor ? `\x1B[31m${s}\x1B[39m` : s;
|
|
54481
54842
|
console.log(`claudemesh doctor (v${VERSION})`);
|
|
54482
54843
|
console.log("─".repeat(60));
|
|
54483
54844
|
const checks3 = [
|
|
@@ -54489,20 +54850,20 @@ async function runDoctor() {
|
|
|
54489
54850
|
checkKeypairs()
|
|
54490
54851
|
];
|
|
54491
54852
|
for (const c of checks3) {
|
|
54492
|
-
const mark = c.pass ?
|
|
54493
|
-
const detail = c.detail ?
|
|
54853
|
+
const mark = c.pass ? green3("✓") : red2("✗");
|
|
54854
|
+
const detail = c.detail ? dim2(` (${c.detail})`) : "";
|
|
54494
54855
|
console.log(`${mark} ${c.name}${detail}`);
|
|
54495
54856
|
if (!c.pass && c.fix) {
|
|
54496
|
-
console.log(
|
|
54857
|
+
console.log(dim2(` → ${c.fix}`));
|
|
54497
54858
|
}
|
|
54498
54859
|
}
|
|
54499
54860
|
const failing = checks3.filter((c) => !c.pass);
|
|
54500
54861
|
console.log("");
|
|
54501
54862
|
if (failing.length === 0) {
|
|
54502
|
-
console.log(
|
|
54863
|
+
console.log(green3("All checks passed."));
|
|
54503
54864
|
process.exit(0);
|
|
54504
54865
|
} else {
|
|
54505
|
-
console.log(
|
|
54866
|
+
console.log(red2(`${failing.length} check(s) failed.`));
|
|
54506
54867
|
process.exit(1);
|
|
54507
54868
|
}
|
|
54508
54869
|
}
|
|
@@ -54512,6 +54873,8 @@ init_config();
|
|
|
54512
54873
|
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
|
|
54513
54874
|
import { homedir as homedir6 } from "node:os";
|
|
54514
54875
|
import { join as join6 } from "node:path";
|
|
54876
|
+
init_colors();
|
|
54877
|
+
init_spinner();
|
|
54515
54878
|
function detectState() {
|
|
54516
54879
|
const claudeConfig = join6(homedir6(), ".claude.json");
|
|
54517
54880
|
let mcpRegistered = false;
|
|
@@ -54530,56 +54893,155 @@ function detectState() {
|
|
|
54530
54893
|
return "broken-config";
|
|
54531
54894
|
}
|
|
54532
54895
|
}
|
|
54533
|
-
function runWelcome() {
|
|
54534
|
-
|
|
54535
|
-
|
|
54536
|
-
|
|
54537
|
-
const
|
|
54538
|
-
const
|
|
54539
|
-
|
|
54896
|
+
async function runWelcome() {
|
|
54897
|
+
if (!process.stdout.isTTY) {
|
|
54898
|
+
return runWelcomePlain();
|
|
54899
|
+
}
|
|
54900
|
+
const state = detectState();
|
|
54901
|
+
const { rows } = termSize();
|
|
54902
|
+
enterFullScreen();
|
|
54903
|
+
drawTopBar();
|
|
54904
|
+
drawBottomBar("↑↓ navigate ⏎ select ctrl-c quit", "claudemesh.com");
|
|
54905
|
+
const logoTop = Math.floor((rows - FRAME_HEIGHT - 10) / 2);
|
|
54906
|
+
const brandRow = logoTop + FRAME_HEIGHT + 1;
|
|
54907
|
+
const subtitleRow = brandRow + 1;
|
|
54908
|
+
const contentRow = subtitleRow + 2;
|
|
54909
|
+
writeCentered(brandRow, boldOrange("claudemesh"));
|
|
54910
|
+
writeCentered(subtitleRow, dim("peer mesh for Claude Code"));
|
|
54911
|
+
const spinner = createSpinner({
|
|
54912
|
+
render(lines) {
|
|
54913
|
+
for (let i = 0;i < lines.length; i++) {
|
|
54914
|
+
writeCentered(logoTop + i, lines[i]);
|
|
54915
|
+
}
|
|
54916
|
+
},
|
|
54917
|
+
interval: 70
|
|
54918
|
+
});
|
|
54919
|
+
spinner.start();
|
|
54920
|
+
let menuRow = contentRow;
|
|
54921
|
+
switch (state) {
|
|
54922
|
+
case "no-install": {
|
|
54923
|
+
writeCentered(contentRow, "Welcome. Let's get you set up.");
|
|
54924
|
+
writeCentered(contentRow + 1, "");
|
|
54925
|
+
writeCentered(contentRow + 2, dim("MCP server ") + yellow("○") + dim(" not registered"));
|
|
54926
|
+
writeCentered(contentRow + 3, dim("Mesh ") + dim("○") + dim(" waiting"));
|
|
54927
|
+
menuRow = contentRow + 5;
|
|
54928
|
+
spinner.stop();
|
|
54929
|
+
const choice = await menuSelect({
|
|
54930
|
+
title: "Get started",
|
|
54931
|
+
items: ["Install MCP server", "Cancel"],
|
|
54932
|
+
row: menuRow
|
|
54933
|
+
});
|
|
54934
|
+
exitFullScreen();
|
|
54935
|
+
if (choice === 0) {
|
|
54936
|
+
console.log(green2("$") + ` claudemesh install
|
|
54937
|
+
`);
|
|
54938
|
+
}
|
|
54939
|
+
break;
|
|
54940
|
+
}
|
|
54941
|
+
case "no-meshes": {
|
|
54942
|
+
writeCentered(contentRow, green2("✓") + " MCP registered. Now join a mesh.");
|
|
54943
|
+
writeCentered(contentRow + 2, dim("MCP server ") + green2("✓") + dim(" registered"));
|
|
54944
|
+
writeCentered(contentRow + 3, dim("Mesh ") + yellow("○") + dim(" none joined"));
|
|
54945
|
+
menuRow = contentRow + 5;
|
|
54946
|
+
spinner.stop();
|
|
54947
|
+
const choice = await menuSelect({
|
|
54948
|
+
title: "Next step",
|
|
54949
|
+
items: [
|
|
54950
|
+
"Join with invite URL",
|
|
54951
|
+
"Create a new mesh",
|
|
54952
|
+
"Cancel"
|
|
54953
|
+
],
|
|
54954
|
+
row: menuRow
|
|
54955
|
+
});
|
|
54956
|
+
exitFullScreen();
|
|
54957
|
+
if (choice === 0) {
|
|
54958
|
+
console.log(green2("$") + ` claudemesh join https://claudemesh.com/join/<token>
|
|
54959
|
+
`);
|
|
54960
|
+
console.log(dim(" Don't have an invite? Create one at ") + bold2("https://claudemesh.com") + dim(" or ask a mesh owner."));
|
|
54961
|
+
} else if (choice === 1) {
|
|
54962
|
+
console.log(green2("$") + ` claudemesh create
|
|
54963
|
+
`);
|
|
54964
|
+
}
|
|
54965
|
+
break;
|
|
54966
|
+
}
|
|
54967
|
+
case "ready": {
|
|
54968
|
+
const cfg = loadConfig();
|
|
54969
|
+
const meshNames = cfg.meshes.map((m) => m.slug).join(", ");
|
|
54970
|
+
writeCentered(contentRow, green2("✓") + " MCP registered");
|
|
54971
|
+
writeCentered(contentRow + 1, green2("✓") + ` ${cfg.meshes.length} mesh(es): ${meshNames}`);
|
|
54972
|
+
writeCentered(contentRow + 2, "");
|
|
54973
|
+
writeCentered(contentRow + 3, bold2("Ready to launch."));
|
|
54974
|
+
menuRow = contentRow + 5;
|
|
54975
|
+
spinner.stop();
|
|
54976
|
+
const choice = await menuSelect({
|
|
54977
|
+
title: "What next?",
|
|
54978
|
+
items: [
|
|
54979
|
+
"Launch Claude Code session",
|
|
54980
|
+
"View peers",
|
|
54981
|
+
"Check status",
|
|
54982
|
+
"Run diagnostics",
|
|
54983
|
+
"Exit"
|
|
54984
|
+
],
|
|
54985
|
+
row: menuRow
|
|
54986
|
+
});
|
|
54987
|
+
exitFullScreen();
|
|
54988
|
+
switch (choice) {
|
|
54989
|
+
case 0:
|
|
54990
|
+
console.log(green2("$") + ` claudemesh launch
|
|
54991
|
+
`);
|
|
54992
|
+
break;
|
|
54993
|
+
case 1:
|
|
54994
|
+
console.log(green2("$") + ` claudemesh peers
|
|
54995
|
+
`);
|
|
54996
|
+
break;
|
|
54997
|
+
case 2:
|
|
54998
|
+
console.log(green2("$") + ` claudemesh status
|
|
54999
|
+
`);
|
|
55000
|
+
break;
|
|
55001
|
+
case 3:
|
|
55002
|
+
console.log(green2("$") + ` claudemesh doctor
|
|
55003
|
+
`);
|
|
55004
|
+
break;
|
|
55005
|
+
}
|
|
55006
|
+
break;
|
|
55007
|
+
}
|
|
55008
|
+
case "broken-config": {
|
|
55009
|
+
writeCentered(contentRow, yellow("⚠") + " ~/.claudemesh/config.json is unreadable.");
|
|
55010
|
+
menuRow = contentRow + 2;
|
|
55011
|
+
spinner.stop();
|
|
55012
|
+
const choice = await menuSelect({
|
|
55013
|
+
title: "Recover",
|
|
55014
|
+
items: ["Run diagnostics", "Cancel"],
|
|
55015
|
+
row: menuRow
|
|
55016
|
+
});
|
|
55017
|
+
exitFullScreen();
|
|
55018
|
+
if (choice === 0) {
|
|
55019
|
+
console.log(green2("$") + ` claudemesh doctor
|
|
55020
|
+
`);
|
|
55021
|
+
}
|
|
55022
|
+
break;
|
|
55023
|
+
}
|
|
55024
|
+
}
|
|
55025
|
+
}
|
|
55026
|
+
function runWelcomePlain() {
|
|
55027
|
+
const { VERSION: VERSION2 } = (init_version(), __toCommonJS(exports_version));
|
|
55028
|
+
console.log(`claudemesh v${VERSION2} — peer mesh for Claude Code`);
|
|
54540
55029
|
console.log("─".repeat(60));
|
|
54541
55030
|
const state = detectState();
|
|
54542
55031
|
switch (state) {
|
|
54543
55032
|
case "no-install":
|
|
54544
|
-
console.log("
|
|
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"));
|
|
55033
|
+
console.log("MCP not registered. Run: claudemesh install");
|
|
54551
55034
|
break;
|
|
54552
55035
|
case "no-meshes":
|
|
54553
|
-
console.log(
|
|
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"));
|
|
55036
|
+
console.log("No meshes joined. Run: claudemesh join <invite-url>");
|
|
54561
55037
|
break;
|
|
54562
55038
|
case "ready": {
|
|
54563
55039
|
const cfg = loadConfig();
|
|
54564
|
-
|
|
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"));
|
|
55040
|
+
console.log(`${cfg.meshes.length} mesh(es) joined. Run: claudemesh launch`);
|
|
54576
55041
|
break;
|
|
54577
55042
|
}
|
|
54578
55043
|
case "broken-config":
|
|
54579
|
-
console.log(
|
|
54580
|
-
console.log("");
|
|
54581
|
-
console.log("Run diagnostics to see what's wrong:");
|
|
54582
|
-
console.log(` ${green("$")} claudemesh doctor`);
|
|
55044
|
+
console.log("Config unreadable. Run: claudemesh doctor");
|
|
54583
55045
|
break;
|
|
54584
55046
|
}
|
|
54585
55047
|
console.log("");
|
|
@@ -54623,10 +55085,10 @@ Joined: ${config2.meshes.map((m) => m.slug).join(", ")}`);
|
|
|
54623
55085
|
// src/commands/peers.ts
|
|
54624
55086
|
async function runPeers(flags) {
|
|
54625
55087
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
54626
|
-
const
|
|
54627
|
-
const
|
|
54628
|
-
const
|
|
54629
|
-
const
|
|
55088
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
55089
|
+
const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
55090
|
+
const green3 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
|
|
55091
|
+
const yellow2 = (s) => useColor ? `\x1B[33m${s}\x1B[39m` : s;
|
|
54630
55092
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client2, mesh) => {
|
|
54631
55093
|
const peers = await client2.listPeers();
|
|
54632
55094
|
if (flags.json) {
|
|
@@ -54634,15 +55096,15 @@ async function runPeers(flags) {
|
|
|
54634
55096
|
return;
|
|
54635
55097
|
}
|
|
54636
55098
|
if (peers.length === 0) {
|
|
54637
|
-
console.log(
|
|
55099
|
+
console.log(dim2(`No peers connected on mesh "${mesh.slug}".`));
|
|
54638
55100
|
return;
|
|
54639
55101
|
}
|
|
54640
|
-
console.log(
|
|
55102
|
+
console.log(bold3(`Peers on ${mesh.slug}`) + dim2(` (${peers.length})`));
|
|
54641
55103
|
console.log("");
|
|
54642
55104
|
for (const p of peers) {
|
|
54643
55105
|
const groups = p.groups.length ? " [" + p.groups.map((g) => `@${g.name}${g.role ? `:${g.role}` : ""}`).join(", ") + "]" : "";
|
|
54644
|
-
const statusIcon = p.status === "working" ?
|
|
54645
|
-
const name =
|
|
55106
|
+
const statusIcon = p.status === "working" ? yellow2("●") : green3("●");
|
|
55107
|
+
const name = bold3(p.displayName);
|
|
54646
55108
|
const meta2 = [];
|
|
54647
55109
|
if (p.peerType)
|
|
54648
55110
|
meta2.push(p.peerType);
|
|
@@ -54650,9 +55112,9 @@ async function runPeers(flags) {
|
|
|
54650
55112
|
meta2.push(p.channel);
|
|
54651
55113
|
if (p.model)
|
|
54652
55114
|
meta2.push(p.model);
|
|
54653
|
-
const metaStr = meta2.length ?
|
|
54654
|
-
const cwdStr = p.cwd ?
|
|
54655
|
-
const summary = p.summary ?
|
|
55115
|
+
const metaStr = meta2.length ? dim2(` (${meta2.join(", ")})`) : "";
|
|
55116
|
+
const cwdStr = p.cwd ? dim2(` cwd: ${p.cwd}`) : "";
|
|
55117
|
+
const summary = p.summary ? dim2(` ${p.summary}`) : "";
|
|
54656
55118
|
console.log(` ${statusIcon} ${name}${groups}${metaStr}${summary}`);
|
|
54657
55119
|
if (cwdStr)
|
|
54658
55120
|
console.log(` ${cwdStr}`);
|
|
@@ -54688,19 +55150,19 @@ async function runSend(flags, to, message) {
|
|
|
54688
55150
|
|
|
54689
55151
|
// src/commands/inbox.ts
|
|
54690
55152
|
function formatMessage(msg, useColor) {
|
|
54691
|
-
const
|
|
54692
|
-
const
|
|
55153
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
55154
|
+
const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
54693
55155
|
const text2 = msg.plaintext ?? `[encrypted: ${msg.ciphertext.slice(0, 32)}…]`;
|
|
54694
55156
|
const from = msg.senderPubkey.slice(0, 8);
|
|
54695
55157
|
const time3 = new Date(msg.createdAt).toLocaleTimeString();
|
|
54696
55158
|
const kindTag = msg.kind === "direct" ? "→ direct" : msg.kind;
|
|
54697
|
-
return ` ${
|
|
55159
|
+
return ` ${bold3(from)} ${dim2(`[${kindTag}] ${time3}`)}
|
|
54698
55160
|
${text2}`;
|
|
54699
55161
|
}
|
|
54700
55162
|
async function runInbox(flags) {
|
|
54701
55163
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
54702
|
-
const
|
|
54703
|
-
const
|
|
55164
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
55165
|
+
const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
54704
55166
|
const waitMs = (flags.wait ?? 1) * 1000;
|
|
54705
55167
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client2, mesh) => {
|
|
54706
55168
|
await new Promise((resolve2) => setTimeout(resolve2, waitMs));
|
|
@@ -54710,10 +55172,10 @@ async function runInbox(flags) {
|
|
|
54710
55172
|
return;
|
|
54711
55173
|
}
|
|
54712
55174
|
if (messages.length === 0) {
|
|
54713
|
-
console.log(
|
|
55175
|
+
console.log(dim2(`No messages on mesh "${mesh.slug}".`));
|
|
54714
55176
|
return;
|
|
54715
55177
|
}
|
|
54716
|
-
console.log(
|
|
55178
|
+
console.log(bold3(`Inbox — ${mesh.slug}`) + dim2(` (${messages.length} message${messages.length === 1 ? "" : "s"})`));
|
|
54717
55179
|
console.log("");
|
|
54718
55180
|
for (const msg of messages) {
|
|
54719
55181
|
console.log(formatMessage(msg, useColor));
|
|
@@ -54725,11 +55187,11 @@ async function runInbox(flags) {
|
|
|
54725
55187
|
// src/commands/state.ts
|
|
54726
55188
|
async function runStateGet(flags, key) {
|
|
54727
55189
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
54728
|
-
const
|
|
55190
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
54729
55191
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
|
|
54730
55192
|
const entry = await client2.getState(key);
|
|
54731
55193
|
if (!entry) {
|
|
54732
|
-
console.log(
|
|
55194
|
+
console.log(dim2(`(not set)`));
|
|
54733
55195
|
return;
|
|
54734
55196
|
}
|
|
54735
55197
|
if (flags.json) {
|
|
@@ -54738,7 +55200,7 @@ async function runStateGet(flags, key) {
|
|
|
54738
55200
|
}
|
|
54739
55201
|
const val = typeof entry.value === "string" ? entry.value : JSON.stringify(entry.value);
|
|
54740
55202
|
console.log(val);
|
|
54741
|
-
console.log(
|
|
55203
|
+
console.log(dim2(` set by ${entry.updatedBy} at ${new Date(entry.updatedAt).toLocaleString()}`));
|
|
54742
55204
|
});
|
|
54743
55205
|
}
|
|
54744
55206
|
async function runStateSet(flags, key, value) {
|
|
@@ -54755,8 +55217,8 @@ async function runStateSet(flags, key, value) {
|
|
|
54755
55217
|
}
|
|
54756
55218
|
async function runStateList(flags) {
|
|
54757
55219
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
54758
|
-
const
|
|
54759
|
-
const
|
|
55220
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
55221
|
+
const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
54760
55222
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client2, mesh) => {
|
|
54761
55223
|
const entries = await client2.listState();
|
|
54762
55224
|
if (flags.json) {
|
|
@@ -54764,13 +55226,13 @@ async function runStateList(flags) {
|
|
|
54764
55226
|
return;
|
|
54765
55227
|
}
|
|
54766
55228
|
if (entries.length === 0) {
|
|
54767
|
-
console.log(
|
|
55229
|
+
console.log(dim2(`No state on mesh "${mesh.slug}".`));
|
|
54768
55230
|
return;
|
|
54769
55231
|
}
|
|
54770
55232
|
for (const e of entries) {
|
|
54771
55233
|
const val = typeof e.value === "string" ? e.value : JSON.stringify(e.value);
|
|
54772
|
-
console.log(`${
|
|
54773
|
-
console.log(
|
|
55234
|
+
console.log(`${bold3(e.key)}: ${val}`);
|
|
55235
|
+
console.log(dim2(` ${e.updatedBy} · ${new Date(e.updatedAt).toLocaleString()}`));
|
|
54774
55236
|
}
|
|
54775
55237
|
});
|
|
54776
55238
|
}
|
|
@@ -54794,8 +55256,8 @@ async function runRemember(flags, content) {
|
|
|
54794
55256
|
}
|
|
54795
55257
|
async function runRecall(flags, query) {
|
|
54796
55258
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
54797
|
-
const
|
|
54798
|
-
const
|
|
55259
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
55260
|
+
const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
54799
55261
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
|
|
54800
55262
|
const memories = await client2.recall(query);
|
|
54801
55263
|
if (flags.json) {
|
|
@@ -54803,14 +55265,14 @@ async function runRecall(flags, query) {
|
|
|
54803
55265
|
return;
|
|
54804
55266
|
}
|
|
54805
55267
|
if (memories.length === 0) {
|
|
54806
|
-
console.log(
|
|
55268
|
+
console.log(dim2("No memories found."));
|
|
54807
55269
|
return;
|
|
54808
55270
|
}
|
|
54809
55271
|
for (const m of memories) {
|
|
54810
|
-
const tags = m.tags.length ?
|
|
54811
|
-
console.log(`${
|
|
55272
|
+
const tags = m.tags.length ? dim2(` [${m.tags.join(", ")}]`) : "";
|
|
55273
|
+
console.log(`${bold3(m.id.slice(0, 8))}${tags}`);
|
|
54812
55274
|
console.log(` ${m.content}`);
|
|
54813
|
-
console.log(
|
|
55275
|
+
console.log(dim2(` ${m.rememberedBy} · ${new Date(m.rememberedAt).toLocaleString()}`));
|
|
54814
55276
|
console.log("");
|
|
54815
55277
|
}
|
|
54816
55278
|
});
|
|
@@ -54820,8 +55282,8 @@ async function runRecall(flags, query) {
|
|
|
54820
55282
|
init_config();
|
|
54821
55283
|
async function runInfo(flags) {
|
|
54822
55284
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
54823
|
-
const
|
|
54824
|
-
const
|
|
55285
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
55286
|
+
const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
54825
55287
|
const config2 = loadConfig();
|
|
54826
55288
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client2, mesh) => {
|
|
54827
55289
|
const [brokerInfo, peers, state] = await Promise.all([
|
|
@@ -54843,16 +55305,16 @@ async function runInfo(flags) {
|
|
|
54843
55305
|
console.log(JSON.stringify(output, null, 2));
|
|
54844
55306
|
return;
|
|
54845
55307
|
}
|
|
54846
|
-
console.log(
|
|
54847
|
-
console.log(
|
|
54848
|
-
console.log(
|
|
55308
|
+
console.log(bold3(mesh.slug) + dim2(` · ${mesh.brokerUrl}`));
|
|
55309
|
+
console.log(dim2(` mesh: ${mesh.meshId}`));
|
|
55310
|
+
console.log(dim2(` member: ${mesh.memberId}`));
|
|
54849
55311
|
console.log(` peers: ${peers.length} connected`);
|
|
54850
55312
|
console.log(` state: ${state.length} keys`);
|
|
54851
55313
|
if (brokerInfo && typeof brokerInfo === "object") {
|
|
54852
55314
|
for (const [k, v] of Object.entries(brokerInfo)) {
|
|
54853
55315
|
if (["slug", "meshId", "brokerUrl"].includes(k))
|
|
54854
55316
|
continue;
|
|
54855
|
-
console.log(
|
|
55317
|
+
console.log(dim2(` ${k}: ${JSON.stringify(v)}`));
|
|
54856
55318
|
}
|
|
54857
55319
|
}
|
|
54858
55320
|
});
|
|
@@ -54897,8 +55359,8 @@ function parseDeliverAt(flags) {
|
|
|
54897
55359
|
}
|
|
54898
55360
|
async function runRemind(flags, positional) {
|
|
54899
55361
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
54900
|
-
const
|
|
54901
|
-
const
|
|
55362
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
55363
|
+
const bold3 = (s) => useColor ? `\x1B[1m${s}\x1B[22m` : s;
|
|
54902
55364
|
const action = positional[0];
|
|
54903
55365
|
if (action === "list") {
|
|
54904
55366
|
await withMesh({ meshSlug: flags.mesh ?? null }, async (client2) => {
|
|
@@ -54908,14 +55370,14 @@ async function runRemind(flags, positional) {
|
|
|
54908
55370
|
return;
|
|
54909
55371
|
}
|
|
54910
55372
|
if (scheduled.length === 0) {
|
|
54911
|
-
console.log(
|
|
55373
|
+
console.log(dim2("No pending reminders."));
|
|
54912
55374
|
return;
|
|
54913
55375
|
}
|
|
54914
55376
|
for (const m of scheduled) {
|
|
54915
55377
|
const when = new Date(m.deliverAt).toLocaleString();
|
|
54916
|
-
const to = m.to === client2.getSessionPubkey() ?
|
|
54917
|
-
console.log(` ${
|
|
54918
|
-
console.log(` ${
|
|
55378
|
+
const to = m.to === client2.getSessionPubkey() ? dim2("(self)") : m.to;
|
|
55379
|
+
console.log(` ${bold3(m.id.slice(0, 8))} → ${to} at ${when}`);
|
|
55380
|
+
console.log(` ${dim2(m.message.slice(0, 80))}`);
|
|
54919
55381
|
console.log("");
|
|
54920
55382
|
}
|
|
54921
55383
|
});
|
|
@@ -55128,14 +55590,14 @@ import { hostname as hostname4 } from "node:os";
|
|
|
55128
55590
|
init_keypair();
|
|
55129
55591
|
async function runSync(args) {
|
|
55130
55592
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
55131
|
-
const
|
|
55132
|
-
const
|
|
55593
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
55594
|
+
const green3 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
|
|
55133
55595
|
const config2 = loadConfig();
|
|
55134
55596
|
const code = generatePairingCode();
|
|
55135
55597
|
const listener = await startCallbackListener();
|
|
55136
55598
|
const url = `https://claudemesh.com/cli-auth?port=${listener.port}&code=${code}&action=sync`;
|
|
55137
55599
|
console.log(`Opening browser to sync meshes...`);
|
|
55138
|
-
console.log(
|
|
55600
|
+
console.log(dim2(`Visit: ${url}`));
|
|
55139
55601
|
await openBrowser(url);
|
|
55140
55602
|
const manualPromise = new Promise((resolve2) => {
|
|
55141
55603
|
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
@@ -55180,7 +55642,7 @@ async function runSync(args) {
|
|
|
55180
55642
|
config2.accountId = result.account_id;
|
|
55181
55643
|
saveConfig(config2);
|
|
55182
55644
|
if (added > 0) {
|
|
55183
|
-
console.log(
|
|
55645
|
+
console.log(green3(`✓ Added ${added} new mesh(es)`));
|
|
55184
55646
|
} else {
|
|
55185
55647
|
console.log(`Already up to date (${config2.meshes.length} meshes)`);
|
|
55186
55648
|
}
|
|
@@ -55190,8 +55652,8 @@ async function runSync(args) {
|
|
|
55190
55652
|
init_config();
|
|
55191
55653
|
async function runProfile(flags) {
|
|
55192
55654
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
55193
|
-
const
|
|
55194
|
-
const
|
|
55655
|
+
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
55656
|
+
const green3 = (s) => useColor ? `\x1B[32m${s}\x1B[39m` : s;
|
|
55195
55657
|
const config2 = loadConfig();
|
|
55196
55658
|
if (config2.meshes.length === 0) {
|
|
55197
55659
|
console.error("No meshes joined. Run `claudemesh join <url>` first.");
|
|
@@ -55231,9 +55693,9 @@ async function runProfile(flags) {
|
|
|
55231
55693
|
if (flags.json) {
|
|
55232
55694
|
console.log(JSON.stringify(result, null, 2));
|
|
55233
55695
|
} else if (result.ok) {
|
|
55234
|
-
console.log(
|
|
55696
|
+
console.log(green3("✓ Profile updated"));
|
|
55235
55697
|
const member = result.member;
|
|
55236
|
-
printProfile(member,
|
|
55698
|
+
printProfile(member, dim2);
|
|
55237
55699
|
} else {
|
|
55238
55700
|
console.error(`Error: ${result.error}`);
|
|
55239
55701
|
process.exit(1);
|
|
@@ -55249,21 +55711,21 @@ async function runProfile(flags) {
|
|
|
55249
55711
|
if (flags.json) {
|
|
55250
55712
|
console.log(JSON.stringify(me ?? {}, null, 2));
|
|
55251
55713
|
} else if (me) {
|
|
55252
|
-
printProfile(me,
|
|
55714
|
+
printProfile(me, dim2);
|
|
55253
55715
|
} else {
|
|
55254
55716
|
console.log("Member not found in mesh.");
|
|
55255
55717
|
}
|
|
55256
55718
|
}
|
|
55257
55719
|
}
|
|
55258
|
-
function printProfile(member,
|
|
55720
|
+
function printProfile(member, dim2) {
|
|
55259
55721
|
const groups = member.groups;
|
|
55260
|
-
const groupStr = groups?.length ? groups.map((g) => g.role ? `${g.name} (${g.role})` : g.name).join(", ") :
|
|
55261
|
-
console.log(` Name: ${member.displayName ??
|
|
55262
|
-
console.log(` Role: ${member.roleTag ??
|
|
55722
|
+
const groupStr = groups?.length ? groups.map((g) => g.role ? `${g.name} (${g.role})` : g.name).join(", ") : dim2("(none)");
|
|
55723
|
+
console.log(` Name: ${member.displayName ?? dim2("(not set)")}`);
|
|
55724
|
+
console.log(` Role: ${member.roleTag ?? dim2("(not set)")}`);
|
|
55263
55725
|
console.log(` Groups: ${groupStr}`);
|
|
55264
55726
|
console.log(` Messages: ${member.messageMode ?? "push"}`);
|
|
55265
55727
|
console.log(` Access: ${member.permission ?? "member"}`);
|
|
55266
|
-
console.log(` Mesh: ${
|
|
55728
|
+
console.log(` Mesh: ${dim2(String(member.id ?? ""))}`);
|
|
55267
55729
|
}
|
|
55268
55730
|
|
|
55269
55731
|
// src/commands/connect-telegram.ts
|
|
@@ -55323,6 +55785,7 @@ async function disconnectTelegram() {
|
|
|
55323
55785
|
}
|
|
55324
55786
|
|
|
55325
55787
|
// src/index.ts
|
|
55788
|
+
init_version();
|
|
55326
55789
|
var launch = defineCommand({
|
|
55327
55790
|
meta: {
|
|
55328
55791
|
name: "launch",
|
|
@@ -55657,8 +56120,8 @@ var main = defineCommand({
|
|
|
55657
56120
|
}
|
|
55658
56121
|
})
|
|
55659
56122
|
},
|
|
55660
|
-
run() {
|
|
55661
|
-
runWelcome();
|
|
56123
|
+
async run() {
|
|
56124
|
+
await runWelcome();
|
|
55662
56125
|
}
|
|
55663
56126
|
});
|
|
55664
56127
|
runMain(main);
|