diff --git a/apps/cli/CHANGELOG.md b/apps/cli/CHANGELOG.md index f62bc4f..0463903 100644 --- a/apps/cli/CHANGELOG.md +++ b/apps/cli/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 1.22.1 (2026-05-03) — daemon docs + help + +- Root `claudemesh --help` now lists the `daemon` subcommand suite under + its own section (was missing in 1.22.0). +- `claudemesh daemon` (no subcommand) now prints a usage block instead of + silently launching the daemon. `daemon help|--help|-h` work too. +- Bundled SKILL.md gained a "Daemon path (v0.9.0, opt-in, fastest)" + section explaining the runtime, lifecycle commands, and how it relates + to `claudemesh install` (independent — not auto-started). + ## 1.22.0 (2026-05-03) — daemon v0.9.0 ### New: `claudemesh daemon` — long-lived peer mesh runtime diff --git a/apps/cli/package.json b/apps/cli/package.json index 6d788e5..7b60370 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,6 +1,6 @@ { "name": "claudemesh-cli", - "version": "1.22.0", + "version": "1.22.1", "description": "Peer mesh for Claude Code sessions — CLI + MCP server.", "keywords": [ "claude-code", diff --git a/apps/cli/skills/claudemesh/SKILL.md b/apps/cli/skills/claudemesh/SKILL.md index c4f298a..3a98821 100644 --- a/apps/cli/skills/claudemesh/SKILL.md +++ b/apps/cli/skills/claudemesh/SKILL.md @@ -45,6 +45,23 @@ claudemesh send "" "..." --mesh "" 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/.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. +### Daemon path (v0.9.0, opt-in, fastest) + +`claudemesh daemon up [--mesh ]` 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. + +Lifecycle: + +```bash +claudemesh daemon up --mesh # foreground +claudemesh daemon install-service --mesh # macOS launchd / Linux systemd-user +claudemesh daemon status [--json] # health + pid +claudemesh daemon outbox list [--failed|--pending|...] # local queue inspection +claudemesh daemon outbox requeue # re-enqueue an aborted/dead row +claudemesh daemon down # SIGTERM + wait +``` + +`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. + ## Spawning new sessions (no wizard) `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. diff --git a/apps/cli/src/commands/daemon.ts b/apps/cli/src/commands/daemon.ts index 0fb0963..c904c56 100644 --- a/apps/cli/src/commands/daemon.ts +++ b/apps/cli/src/commands/daemon.ts @@ -22,6 +22,8 @@ export async function runDaemonCommand( ): Promise { switch (sub) { case undefined: + return printDaemonUsage(); + case "up": case "start": return runDaemon({ @@ -31,6 +33,11 @@ export async function runDaemonCommand( displayName: opts.displayName, }); + case "help": + case "--help": + case "-h": + return printDaemonUsage(); + case "status": return runStatus(opts); @@ -54,12 +61,47 @@ export async function runDaemonCommand( return runUninstallService(opts); default: - process.stderr.write(`unknown daemon subcommand: ${sub}\n`); - process.stderr.write(`usage: claudemesh daemon [up|status|version|down|accept-host|outbox|install-service|uninstall-service]\n`); + process.stderr.write(`unknown daemon subcommand: ${sub}\n\n`); + printDaemonUsage(process.stderr); return 2; } } +function printDaemonUsage(stream: NodeJS.WritableStream = process.stdout): number { + stream.write(`claudemesh daemon — long-lived peer mesh runtime (v0.9.0) + +USAGE + claudemesh daemon [options] + +COMMANDS + up | start start the daemon in the foreground + status show running pid + IPC health + version ipc + schema version of the running daemon + down | stop stop the running daemon (SIGTERM, then wait) + accept-host pin the current host fingerprint + outbox list list local outbox rows (newest first) + outbox requeue re-enqueue an aborted / dead outbox row + install-service --mesh write launchd (macOS) / systemd-user (Linux) unit + uninstall-service remove the platform service unit + +OPTIONS + --mesh attach to / target this mesh + --name override CLAUDEMESH_DISPLAY_NAME + --no-tcp disable the loopback TCP listener (UDS only) + --public-health expose /v1/health unauthenticated on TCP + --json machine-readable output where supported + +OUTBOX FLAGS (for 'daemon outbox list') + --pending --inflight --done --failed --aborted filter by status + +OUTBOX FLAGS (for 'daemon outbox requeue') + --new-client-id mint the new row with this client_message_id + +See ${"https://claudemesh.com/docs"} for the full daemon spec. +`); + return 0; +} + interface OutboxRowResp { id: string; client_message_id: string; diff --git a/apps/cli/src/entrypoints/cli.ts b/apps/cli/src/entrypoints/cli.ts index c75de22..d895a7b 100644 --- a/apps/cli/src/entrypoints/cli.ts +++ b/apps/cli/src/entrypoints/cli.ts @@ -180,6 +180,17 @@ Security claudemesh backup [file] encrypt config → portable recovery file claudemesh restore restore config from a backup file +Daemon (long-lived peer mesh runtime, v0.9.0) + claudemesh daemon up start daemon (alias: start) [--mesh ] [--no-tcp] + claudemesh daemon status show running pid + IPC health [--json] + claudemesh daemon down stop daemon (alias: stop) + claudemesh daemon version ipc + schema version of running daemon + claudemesh daemon outbox list list local outbox rows [--failed|--pending|--inflight|--done] + claudemesh daemon outbox requeue re-enqueue an aborted/dead row [--new-client-id ] + claudemesh daemon accept-host pin current host fingerprint + claudemesh daemon install-service --mesh write launchd / systemd-user unit + claudemesh daemon uninstall-service remove the unit + Setup claudemesh install register MCP server + hooks claudemesh uninstall remove MCP server + hooks