claudemesh-cli 0.8.0 → 0.8.2

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 +201 -2
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -47795,6 +47795,28 @@ async function signHello(meshId, memberId, pubkey, secretKeyHex) {
47795
47795
 
47796
47796
  // src/ws/client.ts
47797
47797
  init_keypair();
47798
+ function detectClaudeSessionId() {
47799
+ try {
47800
+ const { readdirSync, statSync, readFileSync: readFileSync2 } = __require("node:fs");
47801
+ const { join: join2 } = __require("node:path");
47802
+ const { homedir: homedir2 } = __require("node:os");
47803
+ const cwd = process.cwd();
47804
+ const projectsDir = join2(homedir2(), ".claude", "projects");
47805
+ const cwdHash = cwd.replace(/\//g, "-");
47806
+ const entries = readdirSync(projectsDir);
47807
+ const projectDir = entries.find((e) => e === cwdHash || e.startsWith(cwdHash));
47808
+ if (!projectDir)
47809
+ return null;
47810
+ const fullDir = join2(projectsDir, projectDir);
47811
+ const jsonls = readdirSync(fullDir).filter((f) => f.endsWith(".jsonl")).map((f) => ({ name: f, mtime: statSync(join2(fullDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
47812
+ if (jsonls.length === 0)
47813
+ return null;
47814
+ const latest = jsonls[0];
47815
+ return latest.name.replace(".jsonl", "");
47816
+ } catch {
47817
+ return null;
47818
+ }
47819
+ }
47798
47820
  var MAX_QUEUED = 100;
47799
47821
  var HELLO_ACK_TIMEOUT_MS = 5000;
47800
47822
  var BACKOFF_CAPS = [1000, 2000, 4000, 8000, 16000, 30000];
@@ -47884,7 +47906,7 @@ class BrokerClient {
47884
47906
  pubkey: this.mesh.pubkey,
47885
47907
  sessionPubkey: this.sessionPubkey,
47886
47908
  displayName: process.env.CLAUDEMESH_DISPLAY_NAME || this.opts.displayName || undefined,
47887
- sessionId: `${process.pid}-${Date.now()}`,
47909
+ sessionId: process.env.CLAUDEMESH_SESSION_ID || detectClaudeSessionId() || `${process.pid}-${Date.now()}`,
47888
47910
  pid: process.pid,
47889
47911
  cwd: process.cwd(),
47890
47912
  hostname: __require("os").hostname(),
@@ -50972,6 +50994,178 @@ ${lines.join(`
50972
50994
  const ok = await client2.deleteWebhook(delName);
50973
50995
  return text(ok ? `Webhook "${delName}" deactivated.` : `Failed to deactivate webhook "${delName}".`, !ok);
50974
50996
  }
50997
+ case "vault_set": {
50998
+ const { key, value, type: vType, mount_path, description } = args ?? {};
50999
+ if (!key || !value)
51000
+ return text("vault_set: `key` and `value` required", true);
51001
+ const client2 = allClients()[0];
51002
+ if (!client2)
51003
+ return text("vault_set: not connected", true);
51004
+ const entryType = vType ?? "env";
51005
+ let plaintext = value;
51006
+ if (entryType === "file") {
51007
+ const { existsSync: existsSync2, readFileSync: readFileSync2 } = await import("node:fs");
51008
+ if (!existsSync2(value))
51009
+ return text(`vault_set: file not found: ${value}`, true);
51010
+ plaintext = readFileSync2(value, "base64");
51011
+ }
51012
+ const encoded = Buffer.from(plaintext).toString("base64");
51013
+ const ok = await client2.vaultSet(key, encoded, "placeholder-nonce", "placeholder-sealed", entryType, mount_path, description);
51014
+ if (!ok)
51015
+ return text("vault_set: broker did not acknowledge", true);
51016
+ return text(`Vault entry "${key}" stored (${entryType}).`);
51017
+ }
51018
+ case "vault_list": {
51019
+ const client2 = allClients()[0];
51020
+ if (!client2)
51021
+ return text("vault_list: not connected", true);
51022
+ const entries = await client2.vaultList();
51023
+ if (entries.length === 0)
51024
+ return text("Vault is empty.");
51025
+ const lines = entries.map((e) => `- **${e.key}** (${e.entry_type}${e.mount_path ? ` → ${e.mount_path}` : ""})${e.description ? ` — ${e.description}` : ""} (${e.updated_at})`);
51026
+ return text(`${entries.length} vault entry(s):
51027
+ ${lines.join(`
51028
+ `)}`);
51029
+ }
51030
+ case "vault_delete": {
51031
+ const { key } = args ?? {};
51032
+ if (!key)
51033
+ return text("vault_delete: `key` required", true);
51034
+ const client2 = allClients()[0];
51035
+ if (!client2)
51036
+ return text("vault_delete: not connected", true);
51037
+ const ok = await client2.vaultDelete(key);
51038
+ return text(ok ? `Vault entry "${key}" deleted.` : `Vault entry "${key}" not found.`);
51039
+ }
51040
+ case "mesh_mcp_deploy": {
51041
+ const { server_name, file_id, git_url, git_branch, env: deployEnv, runtime, memory_mb, network_allow, scope } = args ?? {};
51042
+ if (!server_name)
51043
+ return text("mesh_mcp_deploy: `server_name` required", true);
51044
+ if (!file_id && !git_url)
51045
+ return text("mesh_mcp_deploy: either `file_id` or `git_url` required", true);
51046
+ const client2 = allClients()[0];
51047
+ if (!client2)
51048
+ return text("mesh_mcp_deploy: not connected", true);
51049
+ const source = file_id ? { type: "zip", file_id } : { type: "git", url: git_url, branch: git_branch };
51050
+ const config3 = {};
51051
+ if (deployEnv)
51052
+ config3.env = deployEnv;
51053
+ if (runtime)
51054
+ config3.runtime = runtime;
51055
+ if (memory_mb)
51056
+ config3.memory_mb = memory_mb;
51057
+ if (network_allow)
51058
+ config3.network_allow = network_allow;
51059
+ const result = await client2.mcpDeploy(server_name, source, Object.keys(config3).length > 0 ? config3 : undefined, scope);
51060
+ const toolList = result.tools?.map((t) => ` - ${t.name}: ${t.description}`).join(`
51061
+ `) ?? " (pending)";
51062
+ return text(`Deployed "${server_name}" (status: ${result.status}).
51063
+
51064
+ Tools:
51065
+ ${toolList}
51066
+
51067
+ Default scope: peer (private). Use mesh_mcp_scope to share.`);
51068
+ }
51069
+ case "mesh_mcp_undeploy": {
51070
+ const { server_name } = args ?? {};
51071
+ if (!server_name)
51072
+ return text("mesh_mcp_undeploy: `server_name` required", true);
51073
+ const client2 = allClients()[0];
51074
+ if (!client2)
51075
+ return text("mesh_mcp_undeploy: not connected", true);
51076
+ const ok = await client2.mcpUndeploy(server_name);
51077
+ return text(ok ? `Service "${server_name}" undeployed.` : `Failed to undeploy "${server_name}".`);
51078
+ }
51079
+ case "mesh_mcp_update": {
51080
+ const { server_name } = args ?? {};
51081
+ if (!server_name)
51082
+ return text("mesh_mcp_update: `server_name` required", true);
51083
+ const client2 = allClients()[0];
51084
+ if (!client2)
51085
+ return text("mesh_mcp_update: not connected", true);
51086
+ const result = await client2.mcpUpdate(server_name);
51087
+ return text(`Updated "${server_name}" (status: ${result.status}).`);
51088
+ }
51089
+ case "mesh_mcp_logs": {
51090
+ const { server_name, lines: logLines } = args ?? {};
51091
+ if (!server_name)
51092
+ return text("mesh_mcp_logs: `server_name` required", true);
51093
+ const client2 = allClients()[0];
51094
+ if (!client2)
51095
+ return text("mesh_mcp_logs: not connected", true);
51096
+ const logs = await client2.mcpLogs(server_name, logLines);
51097
+ if (logs.length === 0)
51098
+ return text(`No logs for "${server_name}".`);
51099
+ return text(`Logs for "${server_name}" (${logs.length} lines):
51100
+ \`\`\`
51101
+ ${logs.join(`
51102
+ `)}
51103
+ \`\`\``);
51104
+ }
51105
+ case "mesh_mcp_scope": {
51106
+ const { server_name, scope } = args ?? {};
51107
+ if (!server_name)
51108
+ return text("mesh_mcp_scope: `server_name` required", true);
51109
+ const client2 = allClients()[0];
51110
+ if (!client2)
51111
+ return text("mesh_mcp_scope: not connected", true);
51112
+ const result = await client2.mcpScope(server_name, scope);
51113
+ if (scope !== undefined) {
51114
+ return text(`Scope for "${server_name}" updated to: ${JSON.stringify(result.scope)}`);
51115
+ }
51116
+ return text(`**${server_name}** scope: ${JSON.stringify(result.scope)}
51117
+ Deployed by: ${result.deployed_by}`);
51118
+ }
51119
+ case "mesh_mcp_schema": {
51120
+ const { server_name, tool_name } = args ?? {};
51121
+ if (!server_name)
51122
+ return text("mesh_mcp_schema: `server_name` required", true);
51123
+ const client2 = allClients()[0];
51124
+ if (!client2)
51125
+ return text("mesh_mcp_schema: not connected", true);
51126
+ const tools = await client2.mcpServiceSchema(server_name, tool_name);
51127
+ if (tools.length === 0)
51128
+ return text(`No tools found for "${server_name}"${tool_name ? ` (tool: ${tool_name})` : ""}.`);
51129
+ const lines = tools.map((t) => `### ${t.name}
51130
+ ${t.description}
51131
+ \`\`\`json
51132
+ ${JSON.stringify(t.inputSchema, null, 2)}
51133
+ \`\`\``);
51134
+ return text(`Tools for "${server_name}":
51135
+
51136
+ ${lines.join(`
51137
+
51138
+ `)}`);
51139
+ }
51140
+ case "mesh_mcp_catalog": {
51141
+ const client2 = allClients()[0];
51142
+ if (!client2)
51143
+ return text("mesh_mcp_catalog: not connected", true);
51144
+ const services = await client2.mcpCatalog();
51145
+ if (services.length === 0)
51146
+ return text("No services deployed in the mesh.");
51147
+ const lines = services.map((s) => {
51148
+ const scopeStr = typeof s.scope === "string" ? s.scope : JSON.stringify(s.scope);
51149
+ return `- **${s.name}** (${s.type}, ${s.status}) — ${s.description}
51150
+ ${s.tool_count} tools | scope: ${scopeStr} | by ${s.deployed_by} | ${s.source_type}${s.runtime ? ` (${s.runtime})` : ""}`;
51151
+ });
51152
+ return text(`${services.length} service(s) in mesh:
51153
+
51154
+ ${lines.join(`
51155
+ `)}`);
51156
+ }
51157
+ case "mesh_skill_deploy": {
51158
+ const { file_id, git_url, git_branch } = args ?? {};
51159
+ if (!file_id && !git_url)
51160
+ return text("mesh_skill_deploy: either `file_id` or `git_url` required", true);
51161
+ const client2 = allClients()[0];
51162
+ if (!client2)
51163
+ return text("mesh_skill_deploy: not connected", true);
51164
+ const source = file_id ? { type: "zip", file_id } : { type: "git", url: git_url, branch: git_branch };
51165
+ const result = await client2.skillDeploy(source);
51166
+ return text(`Skill "${result.name}" deployed.
51167
+ Files: ${result.files.join(", ")}`);
51168
+ }
50975
51169
  default:
50976
51170
  return text(`Unknown tool: ${name}`, true);
50977
51171
  }
@@ -51940,6 +52134,7 @@ async function runHook(args) {
51940
52134
  // src/commands/launch.ts
51941
52135
  init_config();
51942
52136
  import { spawn } from "node:child_process";
52137
+ import { randomUUID } from "node:crypto";
51943
52138
  import { mkdtempSync, writeFileSync as writeFileSync4, rmSync, readdirSync, statSync, existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
51944
52139
  import { tmpdir, hostname as hostname2, homedir as homedir4 } from "node:os";
51945
52140
  import { join as join4 } from "node:path";
@@ -52248,9 +52443,12 @@ async function runLaunch(flags, rawArgs) {
52248
52443
  }
52249
52444
  filtered.push(args.claudeArgs[i]);
52250
52445
  }
52446
+ const claudeSessionId = randomUUID();
52251
52447
  const claudeArgs = [
52252
52448
  "--dangerously-load-development-channels",
52253
52449
  "server:claudemesh",
52450
+ "--session-id",
52451
+ claudeSessionId,
52254
52452
  ...args.skipPermConfirm ? ["--dangerously-skip-permissions"] : [],
52255
52453
  ...args.systemPrompt ? ["--system-prompt", args.systemPrompt] : [],
52256
52454
  ...filtered
@@ -52263,6 +52461,7 @@ async function runLaunch(flags, rawArgs) {
52263
52461
  ...process.env,
52264
52462
  CLAUDEMESH_CONFIG_DIR: tmpDir,
52265
52463
  CLAUDEMESH_DISPLAY_NAME: displayName,
52464
+ CLAUDEMESH_SESSION_ID: claudeSessionId,
52266
52465
  MCP_TIMEOUT: process.env.MCP_TIMEOUT ?? "30000",
52267
52466
  MAX_MCP_OUTPUT_TOKENS: process.env.MAX_MCP_OUTPUT_TOKENS ?? "50000",
52268
52467
  ...role ? { CLAUDEMESH_ROLE: role } : {}
@@ -52319,7 +52518,7 @@ init_config();
52319
52518
  // package.json
52320
52519
  var package_default = {
52321
52520
  name: "claudemesh-cli",
52322
- version: "0.8.0",
52521
+ version: "0.8.2",
52323
52522
  description: "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
52324
52523
  keywords: [
52325
52524
  "claude-code",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudemesh-cli",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "Claude Code MCP client for claudemesh — peer mesh messaging between Claude sessions.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -48,10 +48,10 @@
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",
53
- "@turbostarter/tsconfig": "0.1.0",
54
- "@turbostarter/vitest-config": "0.1.0"
52
+ "@turbostarter/eslint-config": "0.1.0",
53
+ "@turbostarter/vitest-config": "0.1.0",
54
+ "@turbostarter/tsconfig": "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",