claudemesh-cli 0.9.8 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +280 -180
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -40020,6 +40020,88 @@ var init_file_crypto = __esm(() => {
|
|
|
40020
40020
|
init_keypair();
|
|
40021
40021
|
});
|
|
40022
40022
|
|
|
40023
|
+
// src/auth/callback-listener.ts
|
|
40024
|
+
import { createServer } from "node:http";
|
|
40025
|
+
function startCallbackListener() {
|
|
40026
|
+
return new Promise((resolveStart) => {
|
|
40027
|
+
let resolveToken;
|
|
40028
|
+
const tokenPromise = new Promise((r) => {
|
|
40029
|
+
resolveToken = r;
|
|
40030
|
+
});
|
|
40031
|
+
const server = createServer((req, res) => {
|
|
40032
|
+
const url = new URL(req.url, "http://localhost");
|
|
40033
|
+
if (req.method === "OPTIONS") {
|
|
40034
|
+
res.writeHead(204, {
|
|
40035
|
+
"Access-Control-Allow-Origin": "https://claudemesh.com",
|
|
40036
|
+
"Access-Control-Allow-Methods": "GET",
|
|
40037
|
+
"Access-Control-Allow-Headers": "Content-Type"
|
|
40038
|
+
});
|
|
40039
|
+
res.end();
|
|
40040
|
+
return;
|
|
40041
|
+
}
|
|
40042
|
+
if (url.pathname === "/ping") {
|
|
40043
|
+
res.writeHead(200, {
|
|
40044
|
+
"Content-Type": "text/plain",
|
|
40045
|
+
"Access-Control-Allow-Origin": "https://claudemesh.com"
|
|
40046
|
+
});
|
|
40047
|
+
res.end("ok");
|
|
40048
|
+
return;
|
|
40049
|
+
}
|
|
40050
|
+
if (url.pathname === "/callback") {
|
|
40051
|
+
const token = url.searchParams.get("token");
|
|
40052
|
+
if (token) {
|
|
40053
|
+
res.writeHead(200, {
|
|
40054
|
+
"Content-Type": "text/html",
|
|
40055
|
+
"Access-Control-Allow-Origin": "https://claudemesh.com"
|
|
40056
|
+
});
|
|
40057
|
+
res.end("<html><body><h2>Done! You can close this tab.</h2><p>Launching claudemesh...</p></body></html>");
|
|
40058
|
+
resolveToken(token);
|
|
40059
|
+
setTimeout(() => server.close(), 500);
|
|
40060
|
+
} else {
|
|
40061
|
+
res.writeHead(400, { "Content-Type": "text/plain" });
|
|
40062
|
+
res.end("Missing token");
|
|
40063
|
+
}
|
|
40064
|
+
return;
|
|
40065
|
+
}
|
|
40066
|
+
res.writeHead(404);
|
|
40067
|
+
res.end();
|
|
40068
|
+
});
|
|
40069
|
+
server.listen(0, "127.0.0.1", () => {
|
|
40070
|
+
const addr = server.address();
|
|
40071
|
+
resolveStart({
|
|
40072
|
+
port: addr.port,
|
|
40073
|
+
token: tokenPromise,
|
|
40074
|
+
close: () => server.close()
|
|
40075
|
+
});
|
|
40076
|
+
});
|
|
40077
|
+
});
|
|
40078
|
+
}
|
|
40079
|
+
var init_callback_listener = () => {};
|
|
40080
|
+
|
|
40081
|
+
// src/auth/open-browser.ts
|
|
40082
|
+
import { exec } from "node:child_process";
|
|
40083
|
+
function openBrowser(url) {
|
|
40084
|
+
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
|
40085
|
+
return Promise.resolve(false);
|
|
40086
|
+
}
|
|
40087
|
+
const quoted = JSON.stringify(url);
|
|
40088
|
+
const browserCmd = process.env.BROWSER;
|
|
40089
|
+
const cmd = browserCmd ? `${browserCmd} ${quoted}` : process.platform === "darwin" ? `open ${quoted}` : process.platform === "win32" ? `rundll32 url.dll,FileProtocolHandler ${quoted}` : `xdg-open ${quoted}`;
|
|
40090
|
+
return new Promise((resolve2) => {
|
|
40091
|
+
exec(cmd, (err) => resolve2(!err));
|
|
40092
|
+
});
|
|
40093
|
+
}
|
|
40094
|
+
var init_open_browser = () => {};
|
|
40095
|
+
|
|
40096
|
+
// src/auth/pairing-code.ts
|
|
40097
|
+
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
40098
|
+
function generatePairingCode() {
|
|
40099
|
+
const bytes = randomBytes2(4);
|
|
40100
|
+
return Array.from(bytes, (b) => CHARS[b % CHARS.length]).join("");
|
|
40101
|
+
}
|
|
40102
|
+
var CHARS = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";
|
|
40103
|
+
var init_pairing_code = () => {};
|
|
40104
|
+
|
|
40023
40105
|
// src/auth/sync-with-broker.ts
|
|
40024
40106
|
var exports_sync_with_broker = {};
|
|
40025
40107
|
__export(exports_sync_with_broker, {
|
|
@@ -40062,6 +40144,20 @@ function deriveHttpUrl(wssUrl) {
|
|
|
40062
40144
|
return url.toString().replace(/\/$/, "");
|
|
40063
40145
|
}
|
|
40064
40146
|
|
|
40147
|
+
// src/auth/index.ts
|
|
40148
|
+
var exports_auth = {};
|
|
40149
|
+
__export(exports_auth, {
|
|
40150
|
+
syncWithBroker: () => syncWithBroker,
|
|
40151
|
+
startCallbackListener: () => startCallbackListener,
|
|
40152
|
+
openBrowser: () => openBrowser,
|
|
40153
|
+
generatePairingCode: () => generatePairingCode
|
|
40154
|
+
});
|
|
40155
|
+
var init_auth = __esm(() => {
|
|
40156
|
+
init_callback_listener();
|
|
40157
|
+
init_open_browser();
|
|
40158
|
+
init_pairing_code();
|
|
40159
|
+
});
|
|
40160
|
+
|
|
40065
40161
|
// src/tui/colors.ts
|
|
40066
40162
|
function moveTo(row, col) {
|
|
40067
40163
|
return isTTY ? `\x1B[${row};${col}H` : "";
|
|
@@ -40093,7 +40189,7 @@ var package_default;
|
|
|
40093
40189
|
var init_package = __esm(() => {
|
|
40094
40190
|
package_default = {
|
|
40095
40191
|
name: "claudemesh-cli",
|
|
40096
|
-
version: "0.
|
|
40192
|
+
version: "0.10.0",
|
|
40097
40193
|
description: "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
|
|
40098
40194
|
keywords: [
|
|
40099
40195
|
"claude-code",
|
|
@@ -53839,90 +53935,13 @@ async function runHook(args) {
|
|
|
53839
53935
|
|
|
53840
53936
|
// src/commands/launch.ts
|
|
53841
53937
|
init_config();
|
|
53938
|
+
init_auth();
|
|
53842
53939
|
import { spawn } from "node:child_process";
|
|
53843
53940
|
import { randomUUID } from "node:crypto";
|
|
53844
53941
|
import { mkdtempSync, writeFileSync as writeFileSync4, rmSync, readdirSync, statSync, existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
|
|
53845
53942
|
import { tmpdir, hostname as hostname2, homedir as homedir4 } from "node:os";
|
|
53846
53943
|
import { join as join4 } from "node:path";
|
|
53847
53944
|
import { createInterface } from "node:readline";
|
|
53848
|
-
|
|
53849
|
-
// src/auth/callback-listener.ts
|
|
53850
|
-
import { createServer } from "node:http";
|
|
53851
|
-
function startCallbackListener() {
|
|
53852
|
-
return new Promise((resolveStart) => {
|
|
53853
|
-
let resolveToken;
|
|
53854
|
-
const tokenPromise = new Promise((r) => {
|
|
53855
|
-
resolveToken = r;
|
|
53856
|
-
});
|
|
53857
|
-
const server = createServer((req, res) => {
|
|
53858
|
-
const url = new URL(req.url, "http://localhost");
|
|
53859
|
-
if (req.method === "OPTIONS") {
|
|
53860
|
-
res.writeHead(204, {
|
|
53861
|
-
"Access-Control-Allow-Origin": "https://claudemesh.com",
|
|
53862
|
-
"Access-Control-Allow-Methods": "GET",
|
|
53863
|
-
"Access-Control-Allow-Headers": "Content-Type"
|
|
53864
|
-
});
|
|
53865
|
-
res.end();
|
|
53866
|
-
return;
|
|
53867
|
-
}
|
|
53868
|
-
if (url.pathname === "/ping") {
|
|
53869
|
-
res.writeHead(200, {
|
|
53870
|
-
"Content-Type": "text/plain",
|
|
53871
|
-
"Access-Control-Allow-Origin": "https://claudemesh.com"
|
|
53872
|
-
});
|
|
53873
|
-
res.end("ok");
|
|
53874
|
-
return;
|
|
53875
|
-
}
|
|
53876
|
-
if (url.pathname === "/callback") {
|
|
53877
|
-
const token = url.searchParams.get("token");
|
|
53878
|
-
if (token) {
|
|
53879
|
-
res.writeHead(200, {
|
|
53880
|
-
"Content-Type": "text/html",
|
|
53881
|
-
"Access-Control-Allow-Origin": "https://claudemesh.com"
|
|
53882
|
-
});
|
|
53883
|
-
res.end("<html><body><h2>Done! You can close this tab.</h2><p>Launching claudemesh...</p></body></html>");
|
|
53884
|
-
resolveToken(token);
|
|
53885
|
-
setTimeout(() => server.close(), 500);
|
|
53886
|
-
} else {
|
|
53887
|
-
res.writeHead(400, { "Content-Type": "text/plain" });
|
|
53888
|
-
res.end("Missing token");
|
|
53889
|
-
}
|
|
53890
|
-
return;
|
|
53891
|
-
}
|
|
53892
|
-
res.writeHead(404);
|
|
53893
|
-
res.end();
|
|
53894
|
-
});
|
|
53895
|
-
server.listen(0, "127.0.0.1", () => {
|
|
53896
|
-
const addr = server.address();
|
|
53897
|
-
resolveStart({
|
|
53898
|
-
port: addr.port,
|
|
53899
|
-
token: tokenPromise,
|
|
53900
|
-
close: () => server.close()
|
|
53901
|
-
});
|
|
53902
|
-
});
|
|
53903
|
-
});
|
|
53904
|
-
}
|
|
53905
|
-
// src/auth/open-browser.ts
|
|
53906
|
-
import { exec } from "node:child_process";
|
|
53907
|
-
function openBrowser(url) {
|
|
53908
|
-
if (!url.startsWith("http://") && !url.startsWith("https://")) {
|
|
53909
|
-
return Promise.resolve(false);
|
|
53910
|
-
}
|
|
53911
|
-
const quoted = JSON.stringify(url);
|
|
53912
|
-
const browserCmd = process.env.BROWSER;
|
|
53913
|
-
const cmd = browserCmd ? `${browserCmd} ${quoted}` : process.platform === "darwin" ? `open ${quoted}` : process.platform === "win32" ? `rundll32 url.dll,FileProtocolHandler ${quoted}` : `xdg-open ${quoted}`;
|
|
53914
|
-
return new Promise((resolve2) => {
|
|
53915
|
-
exec(cmd, (err) => resolve2(!err));
|
|
53916
|
-
});
|
|
53917
|
-
}
|
|
53918
|
-
// src/auth/pairing-code.ts
|
|
53919
|
-
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
53920
|
-
var CHARS = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";
|
|
53921
|
-
function generatePairingCode() {
|
|
53922
|
-
const bytes = randomBytes2(4);
|
|
53923
|
-
return Array.from(bytes, (b) => CHARS[b % CHARS.length]).join("");
|
|
53924
|
-
}
|
|
53925
|
-
// src/commands/launch.ts
|
|
53926
53945
|
init_colors();
|
|
53927
53946
|
|
|
53928
53947
|
// src/tui/screen.ts
|
|
@@ -54890,8 +54909,9 @@ async function runDoctor() {
|
|
|
54890
54909
|
// src/commands/welcome.ts
|
|
54891
54910
|
init_config();
|
|
54892
54911
|
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
|
|
54893
|
-
import { homedir as homedir6 } from "node:os";
|
|
54912
|
+
import { homedir as homedir6, hostname as hostname3 } from "node:os";
|
|
54894
54913
|
import { join as join6 } from "node:path";
|
|
54914
|
+
import { createInterface as createInterface2 } from "node:readline";
|
|
54895
54915
|
init_colors();
|
|
54896
54916
|
init_spinner();
|
|
54897
54917
|
function detectState() {
|
|
@@ -54916,11 +54936,11 @@ async function runWelcome() {
|
|
|
54916
54936
|
if (!process.stdout.isTTY) {
|
|
54917
54937
|
return runWelcomePlain();
|
|
54918
54938
|
}
|
|
54919
|
-
|
|
54939
|
+
let state = detectState();
|
|
54920
54940
|
const { rows } = termSize();
|
|
54921
54941
|
enterFullScreen();
|
|
54922
54942
|
drawTopBar();
|
|
54923
|
-
const logoTop = Math.floor((rows - FRAME_HEIGHT -
|
|
54943
|
+
const logoTop = Math.floor((rows - FRAME_HEIGHT - 14) / 2);
|
|
54924
54944
|
const brandRow = logoTop + FRAME_HEIGHT + 1;
|
|
54925
54945
|
const subtitleRow = brandRow + 1;
|
|
54926
54946
|
const contentRow = subtitleRow + 2;
|
|
@@ -54935,109 +54955,188 @@ async function runWelcome() {
|
|
|
54935
54955
|
interval: 70
|
|
54936
54956
|
});
|
|
54937
54957
|
spinner.start();
|
|
54938
|
-
let
|
|
54939
|
-
|
|
54940
|
-
|
|
54941
|
-
|
|
54942
|
-
|
|
54943
|
-
|
|
54944
|
-
|
|
54945
|
-
|
|
54946
|
-
|
|
54947
|
-
|
|
54948
|
-
|
|
54949
|
-
|
|
54950
|
-
|
|
54951
|
-
|
|
54958
|
+
let row = contentRow;
|
|
54959
|
+
if (state === "no-install") {
|
|
54960
|
+
writeCentered(row, bold2("Welcome! Let's get you set up."));
|
|
54961
|
+
row += 2;
|
|
54962
|
+
writeCentered(row, `MCP server ${yellow("○")} not registered`);
|
|
54963
|
+
const mcpRow = row;
|
|
54964
|
+
row++;
|
|
54965
|
+
writeCentered(row, `Sign in ${dim("○")} waiting`);
|
|
54966
|
+
const signInRow = row;
|
|
54967
|
+
row++;
|
|
54968
|
+
writeCentered(row, `Mesh ${dim("○")} waiting`);
|
|
54969
|
+
const meshRow = row;
|
|
54970
|
+
row += 2;
|
|
54971
|
+
await new Promise((r) => setTimeout(r, 600));
|
|
54972
|
+
spinner.stop();
|
|
54973
|
+
exitFullScreen();
|
|
54974
|
+
runInstall();
|
|
54975
|
+
enterFullScreen();
|
|
54976
|
+
drawTopBar();
|
|
54977
|
+
writeCentered(brandRow, boldOrange("claudemesh"));
|
|
54978
|
+
writeCentered(subtitleRow, dim("peer mesh for Claude Code"));
|
|
54979
|
+
spinner.start();
|
|
54980
|
+
writeCentered(contentRow, bold2("Welcome! Let's get you set up."));
|
|
54981
|
+
writeCentered(mcpRow, `MCP server ${green("✓")} registered`);
|
|
54982
|
+
writeCentered(signInRow, `Sign in ${yellow("○")} waiting`);
|
|
54983
|
+
writeCentered(meshRow, `Mesh ${dim("○")} waiting`);
|
|
54984
|
+
state = detectState();
|
|
54985
|
+
row = meshRow + 2;
|
|
54986
|
+
}
|
|
54987
|
+
if (state === "no-meshes") {
|
|
54988
|
+
if (row === contentRow) {
|
|
54989
|
+
writeCentered(row, `MCP server ${green("✓")} registered`);
|
|
54990
|
+
row++;
|
|
54991
|
+
writeCentered(row, `Sign in ${yellow("○")} no meshes joined`);
|
|
54992
|
+
const signInRow = row;
|
|
54993
|
+
row += 2;
|
|
54994
|
+
}
|
|
54995
|
+
spinner.stop();
|
|
54996
|
+
const choice = await menuSelect({
|
|
54997
|
+
title: "Connect to a mesh",
|
|
54998
|
+
items: [
|
|
54999
|
+
"Sign in via browser (create or join meshes)",
|
|
55000
|
+
"Paste an invite URL",
|
|
55001
|
+
"Exit"
|
|
55002
|
+
],
|
|
55003
|
+
row
|
|
55004
|
+
});
|
|
55005
|
+
if (choice === 2) {
|
|
54952
55006
|
exitFullScreen();
|
|
54953
|
-
|
|
54954
|
-
console.log(green("$") + ` claudemesh install
|
|
54955
|
-
`);
|
|
54956
|
-
}
|
|
54957
|
-
break;
|
|
55007
|
+
return;
|
|
54958
55008
|
}
|
|
54959
|
-
|
|
54960
|
-
writeCentered(contentRow, green("✓") + " MCP registered. Now join a mesh.");
|
|
54961
|
-
writeCentered(contentRow + 2, dim("MCP server ") + green("✓") + dim(" registered"));
|
|
54962
|
-
writeCentered(contentRow + 3, dim("Mesh ") + yellow("○") + dim(" none joined"));
|
|
54963
|
-
menuRow = contentRow + 5;
|
|
54964
|
-
spinner.stop();
|
|
54965
|
-
const choice = await menuSelect({
|
|
54966
|
-
title: "Next step",
|
|
54967
|
-
items: [
|
|
54968
|
-
"Join with invite URL",
|
|
54969
|
-
"Create a new mesh",
|
|
54970
|
-
"Cancel"
|
|
54971
|
-
],
|
|
54972
|
-
row: menuRow
|
|
54973
|
-
});
|
|
55009
|
+
if (choice === 0) {
|
|
54974
55010
|
exitFullScreen();
|
|
54975
|
-
|
|
54976
|
-
|
|
54977
|
-
|
|
54978
|
-
|
|
54979
|
-
|
|
54980
|
-
|
|
54981
|
-
`
|
|
55011
|
+
console.log(dim(` Opening browser for sign-in...
|
|
55012
|
+
`));
|
|
55013
|
+
const { generatePairingCode: generatePairingCode2 } = await Promise.resolve().then(() => (init_auth(), exports_auth));
|
|
55014
|
+
const { startCallbackListener: startCallbackListener2, openBrowser: openBrowser2 } = await Promise.resolve().then(() => (init_auth(), exports_auth));
|
|
55015
|
+
const code = generatePairingCode2();
|
|
55016
|
+
const listener = await startCallbackListener2();
|
|
55017
|
+
const url = `https://claudemesh.com/cli-auth?port=${listener.port}&code=${code}&action=sync`;
|
|
55018
|
+
const opened = await openBrowser2(url);
|
|
55019
|
+
if (!opened) {
|
|
55020
|
+
console.log(" Couldn't open browser. Visit:");
|
|
55021
|
+
}
|
|
55022
|
+
console.log(dim(` ${url}
|
|
55023
|
+
`));
|
|
55024
|
+
const manualPromise = new Promise((resolve2) => {
|
|
55025
|
+
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
55026
|
+
rl.question(" Paste sync token (or wait for browser): ", (answer) => {
|
|
55027
|
+
rl.close();
|
|
55028
|
+
if (answer.trim())
|
|
55029
|
+
resolve2(answer.trim());
|
|
55030
|
+
});
|
|
55031
|
+
});
|
|
55032
|
+
const timeoutPromise = new Promise((resolve2) => {
|
|
55033
|
+
setTimeout(() => resolve2(null), 900000);
|
|
55034
|
+
});
|
|
55035
|
+
const syncToken = await Promise.race([
|
|
55036
|
+
listener.token,
|
|
55037
|
+
manualPromise,
|
|
55038
|
+
timeoutPromise
|
|
55039
|
+
]);
|
|
55040
|
+
listener.close();
|
|
55041
|
+
if (!syncToken) {
|
|
55042
|
+
console.error(`
|
|
55043
|
+
Timed out waiting for sign-in.`);
|
|
55044
|
+
process.exit(1);
|
|
54982
55045
|
}
|
|
54983
|
-
|
|
55046
|
+
const { generateKeypair: generateKeypair3 } = await Promise.resolve().then(() => (init_keypair(), exports_keypair));
|
|
55047
|
+
const keypair = await generateKeypair3();
|
|
55048
|
+
const displayName = `${hostname3()}-${process.pid}`;
|
|
55049
|
+
const { syncWithBroker: syncWithBroker2 } = await Promise.resolve().then(() => exports_sync_with_broker);
|
|
55050
|
+
const result = await syncWithBroker2(syncToken, keypair.publicKey, displayName);
|
|
55051
|
+
const config2 = loadConfig();
|
|
55052
|
+
const { saveConfig: saveConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
|
|
55053
|
+
for (const m of result.meshes) {
|
|
55054
|
+
config2.meshes.push({
|
|
55055
|
+
meshId: m.mesh_id,
|
|
55056
|
+
memberId: m.member_id,
|
|
55057
|
+
slug: m.slug,
|
|
55058
|
+
name: m.slug,
|
|
55059
|
+
pubkey: keypair.publicKey,
|
|
55060
|
+
secretKey: keypair.secretKey,
|
|
55061
|
+
brokerUrl: m.broker_url,
|
|
55062
|
+
joinedAt: new Date().toISOString()
|
|
55063
|
+
});
|
|
55064
|
+
}
|
|
55065
|
+
config2.accountId = result.account_id;
|
|
55066
|
+
saveConfig2(config2);
|
|
55067
|
+
console.log(`
|
|
55068
|
+
${green("✓")} Synced ${result.meshes.length} mesh(es): ${result.meshes.map((m) => m.slug).join(", ")}
|
|
55069
|
+
`);
|
|
55070
|
+
await runLaunch({}, []);
|
|
55071
|
+
return;
|
|
54984
55072
|
}
|
|
54985
|
-
|
|
54986
|
-
const cfg = loadConfig();
|
|
54987
|
-
const meshNames = cfg.meshes.map((m) => m.slug).join(", ");
|
|
54988
|
-
writeCentered(contentRow, green("✓") + " MCP registered");
|
|
54989
|
-
writeCentered(contentRow + 1, green("✓") + ` ${cfg.meshes.length} mesh(es): ${meshNames}`);
|
|
54990
|
-
writeCentered(contentRow + 2, "");
|
|
54991
|
-
writeCentered(contentRow + 3, bold2("Ready to launch."));
|
|
54992
|
-
menuRow = contentRow + 5;
|
|
54993
|
-
spinner.stop();
|
|
54994
|
-
const choice = await menuSelect({
|
|
54995
|
-
title: "What next?",
|
|
54996
|
-
items: [
|
|
54997
|
-
"Launch Claude Code session",
|
|
54998
|
-
"View peers",
|
|
54999
|
-
"Check status",
|
|
55000
|
-
"Run diagnostics",
|
|
55001
|
-
"Exit"
|
|
55002
|
-
],
|
|
55003
|
-
row: menuRow
|
|
55004
|
-
});
|
|
55073
|
+
if (choice === 1) {
|
|
55005
55074
|
exitFullScreen();
|
|
55006
|
-
|
|
55007
|
-
|
|
55008
|
-
|
|
55009
|
-
|
|
55010
|
-
|
|
55011
|
-
|
|
55012
|
-
|
|
55075
|
+
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
55076
|
+
const url = await new Promise((resolve2) => {
|
|
55077
|
+
rl.question(" Invite URL: ", (answer) => {
|
|
55078
|
+
rl.close();
|
|
55079
|
+
resolve2(answer.trim());
|
|
55080
|
+
});
|
|
55081
|
+
});
|
|
55082
|
+
if (url) {
|
|
55083
|
+
await runLaunch({ join: url }, []);
|
|
55084
|
+
}
|
|
55085
|
+
return;
|
|
55086
|
+
}
|
|
55087
|
+
}
|
|
55088
|
+
if (state === "ready") {
|
|
55089
|
+
const cfg = loadConfig();
|
|
55090
|
+
const meshNames = cfg.meshes.map((m) => m.slug).join(", ");
|
|
55091
|
+
writeCentered(row, `MCP server ${green("✓")} registered`);
|
|
55092
|
+
row++;
|
|
55093
|
+
writeCentered(row, `Meshes ${green("✓")} ${cfg.meshes.length}: ${meshNames}`);
|
|
55094
|
+
row += 2;
|
|
55095
|
+
spinner.stop();
|
|
55096
|
+
const choice = await menuSelect({
|
|
55097
|
+
title: "What next?",
|
|
55098
|
+
items: [
|
|
55099
|
+
"Launch Claude Code session",
|
|
55100
|
+
"View peers",
|
|
55101
|
+
"Check status",
|
|
55102
|
+
"Run diagnostics",
|
|
55103
|
+
"Exit"
|
|
55104
|
+
],
|
|
55105
|
+
row
|
|
55106
|
+
});
|
|
55107
|
+
exitFullScreen();
|
|
55108
|
+
switch (choice) {
|
|
55109
|
+
case 0:
|
|
55110
|
+
await runLaunch({}, []);
|
|
55111
|
+
return;
|
|
55112
|
+
case 1:
|
|
55113
|
+
console.log(green("$") + ` claudemesh peers
|
|
55013
55114
|
`);
|
|
55014
|
-
|
|
55015
|
-
|
|
55016
|
-
|
|
55115
|
+
break;
|
|
55116
|
+
case 2:
|
|
55117
|
+
console.log(green("$") + ` claudemesh status
|
|
55017
55118
|
`);
|
|
55018
|
-
|
|
55019
|
-
|
|
55020
|
-
|
|
55119
|
+
break;
|
|
55120
|
+
case 3:
|
|
55121
|
+
console.log(green("$") + ` claudemesh doctor
|
|
55021
55122
|
`);
|
|
55022
|
-
|
|
55023
|
-
}
|
|
55024
|
-
break;
|
|
55123
|
+
break;
|
|
55025
55124
|
}
|
|
55026
|
-
|
|
55027
|
-
|
|
55028
|
-
|
|
55029
|
-
|
|
55030
|
-
|
|
55031
|
-
|
|
55032
|
-
|
|
55033
|
-
|
|
55034
|
-
|
|
55035
|
-
|
|
55036
|
-
|
|
55037
|
-
|
|
55125
|
+
return;
|
|
55126
|
+
}
|
|
55127
|
+
if (state === "broken-config") {
|
|
55128
|
+
writeCentered(row, yellow("⚠") + " ~/.claudemesh/config.json is unreadable.");
|
|
55129
|
+
row += 2;
|
|
55130
|
+
spinner.stop();
|
|
55131
|
+
const choice = await menuSelect({
|
|
55132
|
+
title: "Recover",
|
|
55133
|
+
items: ["Run diagnostics", "Exit"],
|
|
55134
|
+
row
|
|
55135
|
+
});
|
|
55136
|
+
exitFullScreen();
|
|
55137
|
+
if (choice === 0) {
|
|
55138
|
+
console.log(green("$") + ` claudemesh doctor
|
|
55038
55139
|
`);
|
|
55039
|
-
}
|
|
55040
|
-
break;
|
|
55041
55140
|
}
|
|
55042
55141
|
}
|
|
55043
55142
|
}
|
|
@@ -55066,7 +55165,7 @@ function runWelcomePlain() {
|
|
|
55066
55165
|
}
|
|
55067
55166
|
|
|
55068
55167
|
// src/commands/connect.ts
|
|
55069
|
-
import { hostname as
|
|
55168
|
+
import { hostname as hostname4 } from "node:os";
|
|
55070
55169
|
init_config();
|
|
55071
55170
|
async function withMesh(opts, fn) {
|
|
55072
55171
|
const config2 = loadConfig();
|
|
@@ -55089,7 +55188,7 @@ async function withMesh(opts, fn) {
|
|
|
55089
55188
|
Joined: ${config2.meshes.map((m) => m.slug).join(", ")}`);
|
|
55090
55189
|
process.exit(1);
|
|
55091
55190
|
}
|
|
55092
|
-
const displayName = opts.displayName ?? config2.displayName ?? `${
|
|
55191
|
+
const displayName = opts.displayName ?? config2.displayName ?? `${hostname4()}-${process.pid}`;
|
|
55093
55192
|
const client2 = new BrokerClient(mesh, { displayName });
|
|
55094
55193
|
try {
|
|
55095
55194
|
await client2.connect();
|
|
@@ -55603,9 +55702,10 @@ function runCreate(args) {
|
|
|
55603
55702
|
|
|
55604
55703
|
// src/commands/sync.ts
|
|
55605
55704
|
init_config();
|
|
55606
|
-
|
|
55607
|
-
import { hostname as hostname4 } from "node:os";
|
|
55705
|
+
init_auth();
|
|
55608
55706
|
init_keypair();
|
|
55707
|
+
import { createInterface as createInterface3 } from "node:readline";
|
|
55708
|
+
import { hostname as hostname5 } from "node:os";
|
|
55609
55709
|
async function runSync(args) {
|
|
55610
55710
|
const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
|
|
55611
55711
|
const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
|
|
@@ -55618,7 +55718,7 @@ async function runSync(args) {
|
|
|
55618
55718
|
console.log(dim2(`Visit: ${url}`));
|
|
55619
55719
|
await openBrowser(url);
|
|
55620
55720
|
const manualPromise = new Promise((resolve2) => {
|
|
55621
|
-
const rl =
|
|
55721
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
55622
55722
|
rl.question("Paste sync token (or wait for browser): ", (answer) => {
|
|
55623
55723
|
rl.close();
|
|
55624
55724
|
if (answer.trim())
|
|
@@ -55639,7 +55739,7 @@ async function runSync(args) {
|
|
|
55639
55739
|
process.exit(1);
|
|
55640
55740
|
}
|
|
55641
55741
|
const keypair = config2.meshes.length > 0 ? { publicKey: config2.meshes[0].pubkey, secretKey: config2.meshes[0].secretKey } : await generateKeypair2();
|
|
55642
|
-
const displayName = config2.displayName ?? `${
|
|
55742
|
+
const displayName = config2.displayName ?? `${hostname5()}-${process.pid}`;
|
|
55643
55743
|
const result = await syncWithBroker(syncToken, keypair.publicKey, displayName);
|
|
55644
55744
|
let added = 0;
|
|
55645
55745
|
for (const m of result.meshes) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudemesh-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
"typescript": "5.9.3",
|
|
50
50
|
"vitest": "4.0.14",
|
|
51
51
|
"@turbostarter/prettier-config": "0.1.0",
|
|
52
|
-
"@turbostarter/eslint-config": "0.1.0",
|
|
53
52
|
"@turbostarter/vitest-config": "0.1.0",
|
|
54
|
-
"@turbostarter/tsconfig": "0.1.0"
|
|
53
|
+
"@turbostarter/tsconfig": "0.1.0",
|
|
54
|
+
"@turbostarter/eslint-config": "0.1.0"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"build": "bun build src/index.ts --target=node --outfile dist/index.js --banner \"#!/usr/bin/env node\" && chmod +x dist/index.js",
|