From 9ecf2d65af9c7c535459d27d12e637379dbbe4cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Guti=C3=A9rrez?= <35082514+alezmad@users.noreply.github.com> Date: Sat, 2 May 2026 22:44:00 +0100 Subject: [PATCH] docs(skill): wizard-free `launch` patterns for spawning peer sessions Adds a "Spawning new sessions (no wizard)" section to the bundled claudemesh skill. Documents every flag of `claudemesh launch` (--name, --mesh, --join, --groups, --role, --message-mode, --system-prompt, --resume, --continue, -y, -q, plus -- pass-through), shows wizard-free spawn templates from minimal to cold-start-with- join, and the canonical pane-creation primitives (tmux send-keys, iTerm2 osascript, Terminal.app, gnome-terminal, screen) that wrap the verb when spawning into a fresh terminal pane or window. Closes the gap where Claude knew the verb existed but had no playbook for "how do I start another peer in a new pane without an interactive prompt firing." Bumps CLI to 1.9.4 so the skill ships on `claudemesh install`. --- apps/cli/package.json | 2 +- apps/cli/skills/claudemesh/SKILL.md | 98 +++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/apps/cli/package.json b/apps/cli/package.json index e1eb5e0..9fdeef1 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,6 +1,6 @@ { "name": "claudemesh-cli", - "version": "1.9.3", + "version": "1.9.4", "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 68f09c1..e54ce77 100644 --- a/apps/cli/skills/claudemesh/SKILL.md +++ b/apps/cli/skills/claudemesh/SKILL.md @@ -45,6 +45,104 @@ 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. +## 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. + +### Full flag surface + +| Flag | What it skips | Notes | +|---|---|---| +| `--name ` | the "What's your name?" prompt | required when spawning unattended; persists as the session's display name and `from_name` in inbound channels | +| `--mesh ` | the multi-mesh picker | required when the user has joined >1 mesh; otherwise the single mesh is auto-selected | +| `--join ` | the "join a mesh first" branch | run join + launch in one step; pair with `-y` for fully non-interactive | +| `--groups "name:role,name2:role2,all"` | the group selection prompt | comma-separated `:` entries; the literal `all` joins `@all` | +| `--role ` | the role prompt | applied to all groups in `--groups` that didn't specify their own | +| `--message-mode ` | the message-mode prompt | `push` (default) emits `` notifications mid-turn; `inbox` only buffers — quieter for headless agents | +| `--system-prompt ` | nothing — pure pass-through | forwarded to `claude --append-system-prompt` | +| `--resume ` | nothing — pure pass-through | forwarded to `claude --resume` to continue a prior Claude Code session | +| `--continue` | nothing — pure pass-through | forwarded to `claude --continue` | +| `-y` / `--yes` | every confirmation prompt | including the "you'll skip ALL permission prompts" gate. **Use for autonomous agents; omit for shared/multi-person meshes.** | +| `-q` / `--quiet` | the welcome banner | useful when the spawning script wants clean stdout | +| `--` | (separator) | everything after `--` is forwarded verbatim to `claude`. Example: `claudemesh launch --name X -y -- --resume abc123 --model opus` | + +### Wizard-free spawn templates + +```bash +# Minimal — single joined mesh, fresh agent, autonomous: +claudemesh launch --name "Lug Nut" -y + +# Multi-mesh user — pick mesh explicitly: +claudemesh launch --name "Mou" --mesh openclaw -y + +# Cold-start a peer who hasn't joined the mesh yet: +claudemesh launch \ + --name "Lug Nut" \ + --join "https://claudemesh.com/i/abc123" \ + --groups "frontend:member,reviewers:observer,all" \ + --message-mode push \ + -y + +# Resume a specific Claude session inside claudemesh: +claudemesh launch --name "Mou" --mesh openclaw -y -- --resume abc123-... + +# Quiet, headless, system-prompt loaded — for cron / hooks: +claudemesh launch --name "ci-bot" --mesh openclaw \ + --system-prompt /path/to/ci-bot.md \ + --message-mode inbox \ + -q -y +``` + +If any required flag is missing AND stdin is a TTY, `launch` falls back to its prompt for that single field. **In a non-TTY context (Bash tool, cron, AppleScript pipe), missing flags cause the verb to fail-closed — never silently use a default that affects identity.** + +### Spawning into new terminal panes/windows + +The launch verb itself is just a shell command — wrap it in whatever pane-creation primitive the host platform uses. The patterns that work today: + +```bash +# tmux — send into a pane you control. NEVER send-keys into a pane +# you didn't create; you risk typing into another live TUI. +tmux new-window -t "$SESSION" -n claudemesh-lugnut +tmux send-keys -t "$SESSION:claudemesh-lugnut" \ + 'claudemesh launch --name "Lug Nut" --mesh openclaw -y' Enter + +# macOS iTerm2 (split current window into a vertical pane): +osascript <<'OSA' +tell application "iTerm2" + tell current window + create tab with default profile + tell current session of current tab + write text "claudemesh launch --name \"Lug Nut\" --mesh openclaw -y" + end tell + end tell +end tell +OSA + +# macOS Terminal.app (new window): +osascript -e 'tell application "Terminal" to do script "claudemesh launch --name \"Lug Nut\" --mesh openclaw -y"' + +# GNOME Terminal / generic Linux: +gnome-terminal -- bash -lc 'claudemesh launch --name "Lug Nut" --mesh openclaw -y' + +# screen detached: +screen -dmS lugnut bash -lc 'claudemesh launch --name "Lug Nut" --mesh openclaw -y' +``` + +The user's environment may also have these pre-built helpers (CLAUDE.md will tell you): + +- `~/tools/scripts/spawn-iterm-panes.sh` and `spawn-iterm-window.sh` — safer iTerm spawners that only write into sessions they themselves created. +- `~/tools/scripts/claude-peers.sh` — tmux wrapper that opens a split running `claudemesh launch` with sensible defaults. + +Prefer those when available — they handle pane ownership / cleanup correctly. + +### Sanity rules for unattended spawns + +1. **Always pass `--name`.** A nameless session falls back to `-`, which makes peer attribution opaque in `peer list` and inbound channels. +2. **Always pass `--mesh` when the user has multiple meshes joined.** Otherwise the picker fires and the spawn hangs waiting for stdin. +3. **Pass `-y` only when you understand the consent it grants.** It skips every permission gate — fine for an autonomous agent on a private mesh, dangerous on a shared mesh where peers can drive your file system. +4. **For long-running daemonised peers, use `--message-mode inbox`** so they don't fire `` interrupts on every received DM. They poll `claudemesh inbox` on their own cadence. +5. **Confirm the spawn worked** by waiting a few seconds and running `claudemesh peer list` — the new peer's `displayName` should appear with `status: "idle"`. + ## Universal flags | Flag | Behavior |