claudemesh-cli 1.22.0 → 1.23.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.
@@ -88,7 +88,7 @@ __export(exports_urls, {
88
88
  VERSION: () => VERSION,
89
89
  URLS: () => URLS
90
90
  });
91
- var URLS, VERSION = "1.22.0", env;
91
+ var URLS, VERSION = "1.23.0", env;
92
92
  var init_urls = __esm(() => {
93
93
  URLS = {
94
94
  BROKER: process.env.CLAUDEMESH_BROKER_URL ?? "wss://ic.claudemesh.com/ws",
@@ -962,6 +962,13 @@ var ready = false;
962
962
  var init_keypair = () => {};
963
963
 
964
964
  // src/services/crypto/file-crypto.ts
965
+ var exports_file_crypto = {};
966
+ __export(exports_file_crypto, {
967
+ sealKeyForPeer: () => sealKeyForPeer,
968
+ openSealedKey: () => openSealedKey,
969
+ encryptFile: () => encryptFile,
970
+ decryptFile: () => decryptFile
971
+ });
965
972
  async function encryptFile(plaintext) {
966
973
  const s = await ensureSodium();
967
974
  const key = s.randombytes_buf(s.crypto_secretbox_KEYBYTES);
@@ -10179,6 +10186,7 @@ __export(exports_daemon, {
10179
10186
  async function runDaemonCommand(sub, opts, rest = []) {
10180
10187
  switch (sub) {
10181
10188
  case undefined:
10189
+ return printDaemonUsage();
10182
10190
  case "up":
10183
10191
  case "start":
10184
10192
  return runDaemon({
@@ -10187,6 +10195,10 @@ async function runDaemonCommand(sub, opts, rest = []) {
10187
10195
  mesh: opts.mesh,
10188
10196
  displayName: opts.displayName
10189
10197
  });
10198
+ case "help":
10199
+ case "--help":
10200
+ case "-h":
10201
+ return printDaemonUsage();
10190
10202
  case "status":
10191
10203
  return runStatus(opts);
10192
10204
  case "version":
@@ -10204,12 +10216,46 @@ async function runDaemonCommand(sub, opts, rest = []) {
10204
10216
  return runUninstallService(opts);
10205
10217
  default:
10206
10218
  process.stderr.write(`unknown daemon subcommand: ${sub}
10219
+
10207
10220
  `);
10208
- process.stderr.write(`usage: claudemesh daemon [up|status|version|down|accept-host|outbox|install-service|uninstall-service]
10209
- `);
10221
+ printDaemonUsage(process.stderr);
10210
10222
  return 2;
10211
10223
  }
10212
10224
  }
10225
+ function printDaemonUsage(stream = process.stdout) {
10226
+ stream.write(`claudemesh daemon — long-lived peer mesh runtime (v0.9.0)
10227
+
10228
+ USAGE
10229
+ claudemesh daemon <command> [options]
10230
+
10231
+ COMMANDS
10232
+ up | start start the daemon in the foreground
10233
+ status show running pid + IPC health
10234
+ version ipc + schema version of the running daemon
10235
+ down | stop stop the running daemon (SIGTERM, then wait)
10236
+ accept-host pin the current host fingerprint
10237
+ outbox list list local outbox rows (newest first)
10238
+ outbox requeue <id> re-enqueue an aborted / dead outbox row
10239
+ install-service --mesh <s> write launchd (macOS) / systemd-user (Linux) unit
10240
+ uninstall-service remove the platform service unit
10241
+
10242
+ OPTIONS
10243
+ --mesh <slug> attach to / target this mesh
10244
+ --name <displayName> override CLAUDEMESH_DISPLAY_NAME
10245
+ --no-tcp disable the loopback TCP listener (UDS only)
10246
+ --public-health expose /v1/health unauthenticated on TCP
10247
+ --json machine-readable output where supported
10248
+
10249
+ OUTBOX FLAGS (for 'daemon outbox list')
10250
+ --pending --inflight --done --failed --aborted filter by status
10251
+
10252
+ OUTBOX FLAGS (for 'daemon outbox requeue')
10253
+ --new-client-id <id> mint the new row with this client_message_id
10254
+
10255
+ See ${"https://claudemesh.com/docs"} for the full daemon spec.
10256
+ `);
10257
+ return 0;
10258
+ }
10213
10259
  async function runOutbox(rest, opts) {
10214
10260
  const sub = rest[0];
10215
10261
  switch (sub) {
@@ -12698,11 +12744,14 @@ var exports_platform_actions = {};
12698
12744
  __export(exports_platform_actions, {
12699
12745
  runWebhookList: () => runWebhookList,
12700
12746
  runWebhookDelete: () => runWebhookDelete,
12747
+ runWebhookCreate: () => runWebhookCreate,
12701
12748
  runWatchList: () => runWatchList,
12749
+ runWatchAdd: () => runWatchAdd,
12702
12750
  runVectorStore: () => runVectorStore,
12703
12751
  runVectorSearch: () => runVectorSearch,
12704
12752
  runVectorDelete: () => runVectorDelete,
12705
12753
  runVectorCollections: () => runVectorCollections,
12754
+ runVaultSet: () => runVaultSet,
12706
12755
  runVaultList: () => runVaultList,
12707
12756
  runVaultDelete: () => runVaultDelete,
12708
12757
  runUnwatch: () => runUnwatch,
@@ -13149,6 +13198,40 @@ async function runVaultDelete(key, opts) {
13149
13198
  return ok ? EXIT.SUCCESS : EXIT.NOT_FOUND;
13150
13199
  });
13151
13200
  }
13201
+ async function runVaultSet(key, value, opts) {
13202
+ if (!key || value == null) {
13203
+ render.err("Usage: claudemesh vault set <key> <value> [--type env|file] [--mount /path] [--description ...]");
13204
+ return EXIT.INVALID_ARGS;
13205
+ }
13206
+ const { encryptFile: encryptFile2, sealKeyForPeer: sealKeyForPeer2 } = await Promise.resolve().then(() => (init_file_crypto(), exports_file_crypto));
13207
+ const { getMeshConfig: getMeshConfig2 } = await Promise.resolve().then(() => (init_facade(), exports_facade));
13208
+ const { readConfig: readConfig2 } = await Promise.resolve().then(() => (init_facade(), exports_facade));
13209
+ const config = readConfig2();
13210
+ const slug = opts.mesh ?? (config.meshes.length === 1 ? config.meshes[0].slug : null);
13211
+ if (!slug) {
13212
+ render.err("multiple meshes joined; pass --mesh <slug>");
13213
+ return EXIT.INVALID_ARGS;
13214
+ }
13215
+ const mesh = getMeshConfig2(slug);
13216
+ if (!mesh) {
13217
+ render.err(`not joined to mesh "${slug}"`);
13218
+ return EXIT.NOT_FOUND;
13219
+ }
13220
+ const plaintext = new TextEncoder().encode(value);
13221
+ const enc = await encryptFile2(plaintext);
13222
+ const ciphertextB64 = Buffer.from(enc.ciphertext).toString("base64");
13223
+ const sealed = await sealKeyForPeer2(enc.key, mesh.pubkey);
13224
+ return await withMesh({ meshSlug: slug }, async (client) => {
13225
+ const ok = await client.vaultSet(key, ciphertextB64, enc.nonce, sealed, opts.entryType ?? "env", opts.mountPath, opts.description);
13226
+ if (opts.json)
13227
+ emitJson({ key, stored: ok });
13228
+ else if (ok)
13229
+ render.ok(`vault[${bold(key)}] stored`, dim(`(${ciphertextB64.length}b)`));
13230
+ else
13231
+ render.err(`vault set failed for "${key}"`);
13232
+ return ok ? EXIT.SUCCESS : EXIT.IO_ERROR;
13233
+ });
13234
+ }
13152
13235
  async function runWatchList(opts) {
13153
13236
  return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
13154
13237
  const watches = await client.watchList();
@@ -13171,6 +13254,34 @@ async function runWatchList(opts) {
13171
13254
  return EXIT.SUCCESS;
13172
13255
  });
13173
13256
  }
13257
+ async function runWatchAdd(url, opts) {
13258
+ if (!url) {
13259
+ render.err("Usage: claudemesh watch add <url> [--label ...] [--interval <sec>] [--extract <css>] [--notify-on changed|always]");
13260
+ return EXIT.INVALID_ARGS;
13261
+ }
13262
+ return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
13263
+ const result = await client.watch(url, {
13264
+ label: opts.label,
13265
+ interval: opts.interval,
13266
+ mode: opts.mode,
13267
+ extract: opts.extract,
13268
+ notify_on: opts.notifyOn
13269
+ });
13270
+ if (result?.error) {
13271
+ if (opts.json)
13272
+ emitJson({ ok: false, error: result.error });
13273
+ else
13274
+ render.err(`watch add failed: ${result.error}`);
13275
+ return EXIT.IO_ERROR;
13276
+ }
13277
+ const id = String(result?.id ?? result?.watch_id ?? "?");
13278
+ if (opts.json)
13279
+ emitJson({ ok: true, id, url, ...opts.label ? { label: opts.label } : {} });
13280
+ else
13281
+ render.ok(`watching ${clay(url)}`, dim(id.slice(0, 8)));
13282
+ return EXIT.SUCCESS;
13283
+ });
13284
+ }
13174
13285
  async function runUnwatch(id, opts) {
13175
13286
  if (!id) {
13176
13287
  render.err("Usage: claudemesh watch remove <id>");
@@ -13207,6 +13318,32 @@ async function runWebhookList(opts) {
13207
13318
  return EXIT.SUCCESS;
13208
13319
  });
13209
13320
  }
13321
+ async function runWebhookCreate(name, opts) {
13322
+ if (!name) {
13323
+ render.err("Usage: claudemesh webhook create <name>");
13324
+ return EXIT.INVALID_ARGS;
13325
+ }
13326
+ return await withMesh({ meshSlug: opts.mesh ?? null }, async (client) => {
13327
+ const created = await client.createWebhook(name);
13328
+ if (!created) {
13329
+ if (opts.json)
13330
+ emitJson({ ok: false, error: "create failed (timeout or duplicate)" });
13331
+ else
13332
+ render.err(`webhook create "${name}" failed`);
13333
+ return EXIT.IO_ERROR;
13334
+ }
13335
+ if (opts.json)
13336
+ emitJson({ ok: true, ...created });
13337
+ else {
13338
+ render.ok(`created webhook ${bold(created.name)}`);
13339
+ process.stdout.write(` url: ${clay(created.url)}
13340
+ `);
13341
+ process.stdout.write(` secret: ${dim(created.secret)} ${dim("(shown once)")}
13342
+ `);
13343
+ }
13344
+ return EXIT.SUCCESS;
13345
+ });
13346
+ }
13210
13347
  async function runWebhookDelete(name, opts) {
13211
13348
  if (!name) {
13212
13349
  render.err("Usage: claudemesh webhook delete <name>");
@@ -13501,6 +13638,23 @@ claudemesh send "<from_name>" "..." --mesh "<mesh_slug>"
13501
13638
 
13502
13639
  If the parent Claude session was launched via \`claudemesh launch\`, an MCP push-pipe is running and holds the per-mesh WS connection. CLI invocations dial \`~/.claudemesh/sockets/<mesh-slug>.sock\` and reuse that warm connection (~200ms total round-trip including Node.js startup). If no push-pipe is running (cron, scripts, hooks fired outside a session), the CLI opens its own WS, which takes ~500-700ms cold. **You don't manage this** — every verb auto-detects and falls through.
13503
13640
 
13641
+ ### Daemon path (v0.9.0, opt-in, fastest)
13642
+
13643
+ \`claudemesh daemon up [--mesh <slug>]\` starts a persistent per-user runtime that holds the broker WS, a durable SQLite outbox/inbox, and listens on \`~/.claudemesh/daemon/daemon.sock\` (UDS) plus an optional loopback TCP. When the daemon socket is present, every verb routes through it first (~1ms IPC) before falling back to bridge / cold paths. The send envelope carries a caller-stable \`client_message_id\`, so a \`claudemesh send\` that started before a daemon crash survives the restart via the on-disk outbox.
13644
+
13645
+ Lifecycle:
13646
+
13647
+ \`\`\`bash
13648
+ claudemesh daemon up --mesh <slug> # foreground
13649
+ claudemesh daemon install-service --mesh <slug> # macOS launchd / Linux systemd-user
13650
+ claudemesh daemon status [--json] # health + pid
13651
+ claudemesh daemon outbox list [--failed|--pending|...] # local queue inspection
13652
+ claudemesh daemon outbox requeue <id> # re-enqueue an aborted/dead row
13653
+ claudemesh daemon down # SIGTERM + wait
13654
+ \`\`\`
13655
+
13656
+ \`claudemesh install\` (MCP + hooks registration) and the daemon are independent — install does not start the daemon, and the daemon does not require install. Run both for the warmest path: install gives you the in-session push-pipe, daemon gives you cross-invocation persistence and a survivable outbox.
13657
+
13504
13658
  ## Spawning new sessions (no wizard)
13505
13659
 
13506
13660
  \`claudemesh launch\` is the canonical way to start a new Claude Code session connected to claudemesh. Pass every required flag up front so no interactive prompt fires — that's what makes the verb scriptable from tmux send-keys, AppleScript/iTerm spawn helpers, hooks, cron, and the \`claudemesh launch\` you call from inside another session. **Always use this verb, never \`claude\` directly with hand-rolled flags** — it sets up the per-session ed25519 keypair, exports \`CLAUDEMESH_DISPLAY_NAME\`, isolates the mesh config in a tmpdir, and passes the \`--dangerously-load-development-channels server:claudemesh\` plumbing that the MCP push-pipe needs.
@@ -17428,9 +17582,9 @@ Platform
17428
17582
  claudemesh stream create|publish|list pub/sub event bus
17429
17583
  claudemesh sql query|execute|schema per-mesh SQL
17430
17584
  claudemesh skill list|get|remove mesh-published skills
17431
- claudemesh vault list|delete encrypted secrets
17432
- claudemesh watch list|remove URL change watchers
17433
- claudemesh webhook list|delete outbound HTTP triggers
17585
+ claudemesh vault set|list|delete encrypted secrets (set: --type env|file --mount /p)
17586
+ claudemesh watch add|list|remove URL change watchers (add: --label --interval --extract)
17587
+ claudemesh webhook create|list|delete outbound HTTP triggers
17434
17588
  claudemesh file share <path> [--to peer] upload (or local-host fast path if --to matches)
17435
17589
  claudemesh file get <id> [--out path] download by id
17436
17590
  claudemesh file list|status|delete shared mesh files
@@ -17452,6 +17606,17 @@ Security
17452
17606
  claudemesh backup [file] encrypt config → portable recovery file
17453
17607
  claudemesh restore <file> restore config from a backup file
17454
17608
 
17609
+ Daemon (long-lived peer mesh runtime, v0.9.0)
17610
+ claudemesh daemon up start daemon (alias: start) [--mesh <slug>] [--no-tcp]
17611
+ claudemesh daemon status show running pid + IPC health [--json]
17612
+ claudemesh daemon down stop daemon (alias: stop)
17613
+ claudemesh daemon version ipc + schema version of running daemon
17614
+ claudemesh daemon outbox list list local outbox rows [--failed|--pending|--inflight|--done]
17615
+ claudemesh daemon outbox requeue <id> re-enqueue an aborted/dead row [--new-client-id <id>]
17616
+ claudemesh daemon accept-host pin current host fingerprint
17617
+ claudemesh daemon install-service --mesh <slug> write launchd / systemd-user unit
17618
+ claudemesh daemon uninstall-service remove the unit
17619
+
17455
17620
  Setup
17456
17621
  claudemesh install register MCP server + hooks
17457
17622
  claudemesh uninstall remove MCP server + hooks
@@ -18083,8 +18248,16 @@ async function main() {
18083
18248
  } else if (sub === "delete") {
18084
18249
  const { runVaultDelete: runVaultDelete2 } = await Promise.resolve().then(() => (init_platform_actions(), exports_platform_actions));
18085
18250
  process.exit(await runVaultDelete2(positionals[1] ?? "", f));
18251
+ } else if (sub === "set") {
18252
+ const { runVaultSet: runVaultSet2 } = await Promise.resolve().then(() => (init_platform_actions(), exports_platform_actions));
18253
+ process.exit(await runVaultSet2(positionals[1] ?? "", positionals[2] ?? "", {
18254
+ ...f,
18255
+ entryType: flags.type,
18256
+ mountPath: flags.mount,
18257
+ description: flags.description
18258
+ }));
18086
18259
  } else {
18087
- console.error("Usage: claudemesh vault <list|delete> (set/get currently via MCP — needs crypto)");
18260
+ console.error("Usage: claudemesh vault <list|set|delete>");
18088
18261
  process.exit(EXIT.INVALID_ARGS);
18089
18262
  }
18090
18263
  break;
@@ -18098,8 +18271,18 @@ async function main() {
18098
18271
  } else if (sub === "remove") {
18099
18272
  const { runUnwatch: runUnwatch2 } = await Promise.resolve().then(() => (init_platform_actions(), exports_platform_actions));
18100
18273
  process.exit(await runUnwatch2(positionals[1] ?? "", f));
18274
+ } else if (sub === "add") {
18275
+ const { runWatchAdd: runWatchAdd2 } = await Promise.resolve().then(() => (init_platform_actions(), exports_platform_actions));
18276
+ process.exit(await runWatchAdd2(positionals[1] ?? "", {
18277
+ ...f,
18278
+ label: flags.label,
18279
+ interval: flags.interval ? Number(flags.interval) : undefined,
18280
+ mode: flags.mode,
18281
+ extract: flags.extract,
18282
+ notifyOn: flags["notify-on"]
18283
+ }));
18101
18284
  } else {
18102
- console.error("Usage: claudemesh watch <list|remove>");
18285
+ console.error("Usage: claudemesh watch <list|add|remove>");
18103
18286
  process.exit(EXIT.INVALID_ARGS);
18104
18287
  }
18105
18288
  break;
@@ -18113,8 +18296,11 @@ async function main() {
18113
18296
  } else if (sub === "delete") {
18114
18297
  const { runWebhookDelete: runWebhookDelete2 } = await Promise.resolve().then(() => (init_platform_actions(), exports_platform_actions));
18115
18298
  process.exit(await runWebhookDelete2(positionals[1] ?? "", f));
18299
+ } else if (sub === "create") {
18300
+ const { runWebhookCreate: runWebhookCreate2 } = await Promise.resolve().then(() => (init_platform_actions(), exports_platform_actions));
18301
+ process.exit(await runWebhookCreate2(positionals[1] ?? "", f));
18116
18302
  } else {
18117
- console.error("Usage: claudemesh webhook <list|delete>");
18303
+ console.error("Usage: claudemesh webhook <list|create|delete>");
18118
18304
  process.exit(EXIT.INVALID_ARGS);
18119
18305
  }
18120
18306
  break;
@@ -18426,4 +18612,4 @@ main().catch((err) => {
18426
18612
  process.exit(EXIT.INTERNAL_ERROR);
18427
18613
  });
18428
18614
 
18429
- //# debugId=BA4EDB138BD2E1AE64756E2164756E21
18615
+ //# debugId=DF34DB4C8E61E91564756E2164756E21