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.
- package/dist/index.js +566 -206
- 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
|
|
53759
|
-
const
|
|
53760
|
-
const
|
|
53761
|
-
console.log(
|
|
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(
|
|
53768
|
-
console.log(
|
|
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(` ${
|
|
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
|
|
53790
|
-
const
|
|
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(
|
|
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(
|
|
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
|
|
53858
|
-
const
|
|
53859
|
-
const
|
|
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
|
-
${
|
|
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(` ${
|
|
53872
|
-
console.log(` ${
|
|
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
|
-
${
|
|
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
|
-
|
|
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
|
|
54275
|
-
const
|
|
54276
|
-
const
|
|
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(
|
|
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(
|
|
54565
|
+
console.log(green2("reachable"));
|
|
54308
54566
|
} else {
|
|
54309
|
-
console.log(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
54479
|
-
const
|
|
54480
|
-
const
|
|
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 ?
|
|
54493
|
-
const detail = 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(
|
|
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(
|
|
54761
|
+
console.log(green2("All checks passed."));
|
|
54503
54762
|
process.exit(0);
|
|
54504
54763
|
} else {
|
|
54505
|
-
console.log(
|
|
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
|
-
|
|
54535
|
-
|
|
54536
|
-
|
|
54537
|
-
const
|
|
54538
|
-
const
|
|
54539
|
-
|
|
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("
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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
|
|
54627
|
-
const
|
|
54628
|
-
const
|
|
54629
|
-
const
|
|
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(
|
|
54996
|
+
console.log(dim2(`No peers connected on mesh "${mesh.slug}".`));
|
|
54638
54997
|
return;
|
|
54639
54998
|
}
|
|
54640
|
-
console.log(
|
|
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" ?
|
|
54645
|
-
const name =
|
|
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 ?
|
|
54654
|
-
const cwdStr = p.cwd ?
|
|
54655
|
-
const summary = 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
|
|
54692
|
-
const
|
|
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 ` ${
|
|
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
|
|
54703
|
-
const
|
|
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(
|
|
55072
|
+
console.log(dim2(`No messages on mesh "${mesh.slug}".`));
|
|
54714
55073
|
return;
|
|
54715
55074
|
}
|
|
54716
|
-
console.log(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
54759
|
-
const
|
|
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(
|
|
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(`${
|
|
54773
|
-
console.log(
|
|
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
|
|
54798
|
-
const
|
|
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(
|
|
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 ?
|
|
54811
|
-
console.log(`${
|
|
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(
|
|
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
|
|
54824
|
-
const
|
|
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(
|
|
54847
|
-
console.log(
|
|
54848
|
-
console.log(
|
|
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(
|
|
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
|
|
54901
|
-
const
|
|
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(
|
|
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() ?
|
|
54917
|
-
console.log(` ${
|
|
54918
|
-
console.log(` ${
|
|
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
|
|
55132
|
-
const
|
|
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(
|
|
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(
|
|
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
|
|
55194
|
-
const
|
|
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(
|
|
55593
|
+
console.log(green2("✓ Profile updated"));
|
|
55235
55594
|
const member = result.member;
|
|
55236
|
-
printProfile(member,
|
|
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,
|
|
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,
|
|
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(", ") :
|
|
55261
|
-
console.log(` Name: ${member.displayName ??
|
|
55262
|
-
console.log(` Role: ${member.roleTag ??
|
|
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: ${
|
|
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
|
+
"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
|
},
|