claudemesh-cli 0.9.9 → 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.
Files changed (2) hide show
  1. package/dist/index.js +280 -179
  2. 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.9.9",
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
- const state = detectState();
54939
+ let state = detectState();
54920
54940
  const { rows } = termSize();
54921
54941
  enterFullScreen();
54922
54942
  drawTopBar();
54923
- const logoTop = Math.floor((rows - FRAME_HEIGHT - 10) / 2);
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,108 +54955,188 @@ async function runWelcome() {
54935
54955
  interval: 70
54936
54956
  });
54937
54957
  spinner.start();
54938
- let menuRow = contentRow;
54939
- switch (state) {
54940
- case "no-install": {
54941
- writeCentered(contentRow, "Welcome. Let's get you set up.");
54942
- writeCentered(contentRow + 1, "");
54943
- writeCentered(contentRow + 2, dim("MCP server ") + yellow("○") + dim(" not registered"));
54944
- writeCentered(contentRow + 3, dim("Mesh ") + dim("○") + dim(" waiting"));
54945
- menuRow = contentRow + 5;
54946
- spinner.stop();
54947
- const choice = await menuSelect({
54948
- title: "Get started",
54949
- items: ["Install MCP server", "Cancel"],
54950
- row: menuRow
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
- if (choice === 0) {
54954
- console.log(green("$") + ` claudemesh install
54955
- `);
54956
- }
54957
- break;
55007
+ return;
54958
55008
  }
54959
- case "no-meshes": {
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
- if (choice === 0) {
54976
- console.log(green("$") + ` claudemesh join https://claudemesh.com/join/<token>
54977
- `);
54978
- console.log(dim(" Don't have an invite? Create one at ") + bold2("https://claudemesh.com") + dim(" or ask a mesh owner."));
54979
- } else if (choice === 1) {
54980
- console.log(green("$") + ` claudemesh create
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
- break;
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
- case "ready": {
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
- switch (choice) {
55007
- case 0:
55008
- await runLaunch({}, []);
55009
- return;
55010
- case 1:
55011
- console.log(green("$") + ` claudemesh peers
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
55012
55114
  `);
55013
- break;
55014
- case 2:
55015
- console.log(green("$") + ` claudemesh status
55115
+ break;
55116
+ case 2:
55117
+ console.log(green("$") + ` claudemesh status
55016
55118
  `);
55017
- break;
55018
- case 3:
55019
- console.log(green("$") + ` claudemesh doctor
55119
+ break;
55120
+ case 3:
55121
+ console.log(green("$") + ` claudemesh doctor
55020
55122
  `);
55021
- break;
55022
- }
55023
- break;
55123
+ break;
55024
55124
  }
55025
- case "broken-config": {
55026
- writeCentered(contentRow, yellow("⚠") + " ~/.claudemesh/config.json is unreadable.");
55027
- menuRow = contentRow + 2;
55028
- spinner.stop();
55029
- const choice = await menuSelect({
55030
- title: "Recover",
55031
- items: ["Run diagnostics", "Cancel"],
55032
- row: menuRow
55033
- });
55034
- exitFullScreen();
55035
- if (choice === 0) {
55036
- console.log(green("$") + ` claudemesh doctor
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
55037
55139
  `);
55038
- }
55039
- break;
55040
55140
  }
55041
55141
  }
55042
55142
  }
@@ -55065,7 +55165,7 @@ function runWelcomePlain() {
55065
55165
  }
55066
55166
 
55067
55167
  // src/commands/connect.ts
55068
- import { hostname as hostname3 } from "node:os";
55168
+ import { hostname as hostname4 } from "node:os";
55069
55169
  init_config();
55070
55170
  async function withMesh(opts, fn) {
55071
55171
  const config2 = loadConfig();
@@ -55088,7 +55188,7 @@ async function withMesh(opts, fn) {
55088
55188
  Joined: ${config2.meshes.map((m) => m.slug).join(", ")}`);
55089
55189
  process.exit(1);
55090
55190
  }
55091
- const displayName = opts.displayName ?? config2.displayName ?? `${hostname3()}-${process.pid}`;
55191
+ const displayName = opts.displayName ?? config2.displayName ?? `${hostname4()}-${process.pid}`;
55092
55192
  const client2 = new BrokerClient(mesh, { displayName });
55093
55193
  try {
55094
55194
  await client2.connect();
@@ -55602,9 +55702,10 @@ function runCreate(args) {
55602
55702
 
55603
55703
  // src/commands/sync.ts
55604
55704
  init_config();
55605
- import { createInterface as createInterface2 } from "node:readline";
55606
- import { hostname as hostname4 } from "node:os";
55705
+ init_auth();
55607
55706
  init_keypair();
55707
+ import { createInterface as createInterface3 } from "node:readline";
55708
+ import { hostname as hostname5 } from "node:os";
55608
55709
  async function runSync(args) {
55609
55710
  const useColor = !process.env.NO_COLOR && process.env.TERM !== "dumb" && process.stdout.isTTY;
55610
55711
  const dim2 = (s) => useColor ? `\x1B[2m${s}\x1B[22m` : s;
@@ -55617,7 +55718,7 @@ async function runSync(args) {
55617
55718
  console.log(dim2(`Visit: ${url}`));
55618
55719
  await openBrowser(url);
55619
55720
  const manualPromise = new Promise((resolve2) => {
55620
- const rl = createInterface2({ input: process.stdin, output: process.stdout });
55721
+ const rl = createInterface3({ input: process.stdin, output: process.stdout });
55621
55722
  rl.question("Paste sync token (or wait for browser): ", (answer) => {
55622
55723
  rl.close();
55623
55724
  if (answer.trim())
@@ -55638,7 +55739,7 @@ async function runSync(args) {
55638
55739
  process.exit(1);
55639
55740
  }
55640
55741
  const keypair = config2.meshes.length > 0 ? { publicKey: config2.meshes[0].pubkey, secretKey: config2.meshes[0].secretKey } : await generateKeypair2();
55641
- const displayName = config2.displayName ?? `${hostname4()}-${process.pid}`;
55742
+ const displayName = config2.displayName ?? `${hostname5()}-${process.pid}`;
55642
55743
  const result = await syncWithBroker(syncToken, keypair.publicKey, displayName);
55643
55744
  let added = 0;
55644
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.9.9",
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/vitest-config": "0.1.0",
52
53
  "@turbostarter/tsconfig": "0.1.0",
53
- "@turbostarter/eslint-config": "0.1.0",
54
- "@turbostarter/vitest-config": "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",