From 3c236f8125c912404ee418583c2c8163acf432dc Mon Sep 17 00:00:00 2001 From: Ahmed Abushagur Date: Fri, 27 Mar 2026 22:38:17 -0700 Subject: [PATCH] fix: scope local warning to openclaw-only + improve spawn skill docs - Revert local security warning to openclaw-only (was blocking all agents) - Update spawn skill to document how to run prompts on child VMs: - Always use `bash -lc` (binaries in ~/.local/bin/ need login shell) - Claude uses `-p` not `--print` or `--headless` - Add `--dangerously-skip-permissions` for unattended child VMs - Don't waste tokens with `which`/`find` or creating non-root users - Sync all on-disk skill files with embedded version Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/cli/package.json | 2 +- packages/cli/src/local/main.ts | 5 ++-- packages/cli/src/shared/spawn-skill.ts | 36 ++++++++++++-------------- skills/claude/SKILL.md | 27 ++++++++++++++----- skills/codex/SKILL.md | 27 ++++++++++++++----- skills/hermes/SOUL.md | 1 + skills/junie/AGENTS.md | 28 +++++++++++++++----- skills/kilocode/spawn.md | 28 +++++++++++++++----- skills/openclaw/SKILL.md | 27 ++++++++++++++----- skills/opencode/AGENTS.md | 28 +++++++++++++++----- skills/zeroclaw/AGENTS.md | 28 +++++++++++++++----- 11 files changed, 166 insertions(+), 71 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 9831bafae..be1e999f9 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@openrouter/spawn", - "version": "0.27.5", + "version": "0.27.6", "type": "module", "bin": { "spawn": "cli.js" diff --git a/packages/cli/src/local/main.ts b/packages/cli/src/local/main.ts index 759d2d21e..3b2bcc2cd 100644 --- a/packages/cli/src/local/main.ts +++ b/packages/cli/src/local/main.ts @@ -21,8 +21,9 @@ async function main() { const agent = resolveAgent(agentName); - // Warn about security implications of installing agents locally - if (process.env.SPAWN_NON_INTERACTIVE !== "1") { + // Warn about security implications of installing OpenClaw locally + // (OpenClaw has browser access and broader system control than other agents) + if (agentName === "openclaw" && process.env.SPAWN_NON_INTERACTIVE !== "1") { process.stderr.write("\n"); logWarn("⚠ Local installation warning"); logWarn(` This will install ${agent.name} directly on your machine.`); diff --git a/packages/cli/src/shared/spawn-skill.ts b/packages/cli/src/shared/spawn-skill.ts index ce1c15340..a2b6f1546 100644 --- a/packages/cli/src/shared/spawn-skill.ts +++ b/packages/cli/src/shared/spawn-skill.ts @@ -24,37 +24,35 @@ const SKILL_BODY = `# Spawn — Create Child VMs You have the \`spawn\` CLI installed. Use it to provision cloud VMs with AI agents. -## Usage +## Provision a Child VM \`\`\`bash spawn --headless --output json --prompt "task description" \`\`\` -## Agents: claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie -## Clouds: hetzner, digitalocean, aws, gcp, sprite - -## Example - -\`\`\`bash -spawn claude hetzner --headless --output json --prompt "Implement the auth module" -\`\`\` +**Agents:** claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie +**Clouds:** hetzner, digitalocean, aws, gcp, sprite Returns JSON: \`{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}\` -## Running a prompt on a child VM +## Running Prompts on Child VMs -**--headless only provisions the VM — it does NOT run the prompt on it.** -To actually execute work on the child, SSH in and run the agent: +\`--headless\` only provisions — to run work on the child, SSH in with \`bash -lc\`: \`\`\`bash -ssh -o StrictHostKeyChecking=accept-new root@ '~/.local/bin/claude --print "your prompt"' +# Claude Code (use -p, NOT --print or --headless) +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'claude -p --dangerously-skip-permissions \\"your prompt\\"'" + +# Codex CLI +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'codex --quiet \\"your prompt\\"'" \`\`\` -### Known gotchas — do NOT waste time rediscovering these: -- Agent binaries are at \`~/.local/bin/\`, NOT on the default PATH. Always use the full path: \`~/.local/bin/claude\`, \`~/.local/bin/codex\`, etc. -- Claude Code blocks \`--dangerously-skip-permissions\` as root. Use \`--print\` for one-shot prompts instead — it works as root and returns the response directly. -- Do NOT try to create a non-root user to work around root restrictions — it requires copying config files (\`.claude.json\`, \`.claude/settings.json\`, env vars) and is fragile. Just use \`--print\`. -- For long-running tasks, use \`spawn delete --name --yes\` to clean up when done. +### IMPORTANT — do NOT waste tokens rediscovering these: +- **Always use \`bash -lc\`** — agent binaries are in \`~/.local/bin/\` which is only on PATH in login shells +- **Claude uses \`-p\`** for non-interactive output (NOT \`--print\`, NOT \`--headless\`) +- **Add \`--dangerously-skip-permissions\`** to skip approval prompts on child VMs +- **Never try \`which claude\` or \`find\`** to locate binaries — they are always at \`~/.local/bin/\` +- **Never create non-root users** to work around permission issues — just use \`-p\` ## Managing Children @@ -78,7 +76,7 @@ You have the \`spawn\` CLI for creating child cloud VMs with AI agents. Use \`spawn --headless --output json --prompt "task"\` to delegate work. Available agents: claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie. Cloud credentials are pre-configured. Run \`spawn list --json\` to see children. -Note: --headless only provisions the VM. To run a prompt, SSH in: \`ssh root@ '~/.local/bin/ --print "prompt"'\`. +\`--headless\` only provisions. To run a prompt on the child: \`ssh root@ "bash -lc 'claude -p --dangerously-skip-permissions \\"prompt\\"'"\`. Always use \`bash -lc\` (binaries are in ~/.local/bin/). `; // ─── Agent config ─────────────────────────────────────────────────────────── diff --git a/skills/claude/SKILL.md b/skills/claude/SKILL.md index 92e4ee65d..dafb83b96 100644 --- a/skills/claude/SKILL.md +++ b/skills/claude/SKILL.md @@ -8,27 +8,40 @@ allowed-tools: Bash You have the `spawn` CLI installed. Use it to provision cloud VMs with AI agents. -## Usage +## Provision a Child VM ```bash spawn --headless --output json --prompt "task description" ``` -## Agents: claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie -## Clouds: hetzner, digitalocean, aws, gcp, sprite +**Agents:** claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie +**Clouds:** hetzner, digitalocean, aws, gcp, sprite -## Example +Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` + +## Running Prompts on Child VMs + +`--headless` only provisions — to run work on the child, SSH in with `bash -lc`: ```bash -spawn claude hetzner --headless --output json --prompt "Implement the auth module" +# Claude Code (use -p, NOT --print or --headless) +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'claude -p --dangerously-skip-permissions \"your prompt\"'" + +# Codex CLI +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'codex --quiet \"your prompt\"'" ``` -Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` +### IMPORTANT — do NOT waste tokens rediscovering these: +- **Always use `bash -lc`** — agent binaries are in `~/.local/bin/` which is only on PATH in login shells +- **Claude uses `-p`** for non-interactive output (NOT `--print`, NOT `--headless`) +- **Add `--dangerously-skip-permissions`** to skip approval prompts on child VMs +- **Never try `which claude` or `find`** to locate binaries — they are always at `~/.local/bin/` +- **Never create non-root users** to work around permission issues — just use `-p` ## Managing Children - `spawn list --json` — see running children -- `spawn delete --name --yes` — tear down a child VM +- `spawn delete --name --yes` — tear down a child VM (headless) - `spawn tree` — see the full spawn tree ## Context diff --git a/skills/codex/SKILL.md b/skills/codex/SKILL.md index 92e4ee65d..dafb83b96 100644 --- a/skills/codex/SKILL.md +++ b/skills/codex/SKILL.md @@ -8,27 +8,40 @@ allowed-tools: Bash You have the `spawn` CLI installed. Use it to provision cloud VMs with AI agents. -## Usage +## Provision a Child VM ```bash spawn --headless --output json --prompt "task description" ``` -## Agents: claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie -## Clouds: hetzner, digitalocean, aws, gcp, sprite +**Agents:** claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie +**Clouds:** hetzner, digitalocean, aws, gcp, sprite -## Example +Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` + +## Running Prompts on Child VMs + +`--headless` only provisions — to run work on the child, SSH in with `bash -lc`: ```bash -spawn claude hetzner --headless --output json --prompt "Implement the auth module" +# Claude Code (use -p, NOT --print or --headless) +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'claude -p --dangerously-skip-permissions \"your prompt\"'" + +# Codex CLI +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'codex --quiet \"your prompt\"'" ``` -Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` +### IMPORTANT — do NOT waste tokens rediscovering these: +- **Always use `bash -lc`** — agent binaries are in `~/.local/bin/` which is only on PATH in login shells +- **Claude uses `-p`** for non-interactive output (NOT `--print`, NOT `--headless`) +- **Add `--dangerously-skip-permissions`** to skip approval prompts on child VMs +- **Never try `which claude` or `find`** to locate binaries — they are always at `~/.local/bin/` +- **Never create non-root users** to work around permission issues — just use `-p` ## Managing Children - `spawn list --json` — see running children -- `spawn delete --name --yes` — tear down a child VM +- `spawn delete --name --yes` — tear down a child VM (headless) - `spawn tree` — see the full spawn tree ## Context diff --git a/skills/hermes/SOUL.md b/skills/hermes/SOUL.md index f4ed732a7..56091717b 100644 --- a/skills/hermes/SOUL.md +++ b/skills/hermes/SOUL.md @@ -6,3 +6,4 @@ You have the `spawn` CLI for creating child cloud VMs with AI agents. Use `spawn --headless --output json --prompt "task"` to delegate work. Available agents: claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie. Cloud credentials are pre-configured. Run `spawn list --json` to see children. +`--headless` only provisions. To run a prompt on the child: `ssh root@ "bash -lc 'claude -p --dangerously-skip-permissions \"prompt\"'"`. Always use `bash -lc` (binaries are in ~/.local/bin/). diff --git a/skills/junie/AGENTS.md b/skills/junie/AGENTS.md index cf8db3a65..b1288f8c7 100644 --- a/skills/junie/AGENTS.md +++ b/skills/junie/AGENTS.md @@ -2,27 +2,40 @@ You have the `spawn` CLI installed. Use it to provision cloud VMs with AI agents. -## Usage +## Provision a Child VM ```bash spawn --headless --output json --prompt "task description" ``` -## Agents: claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie -## Clouds: hetzner, digitalocean, aws, gcp, sprite +**Agents:** claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie +**Clouds:** hetzner, digitalocean, aws, gcp, sprite -## Example +Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` + +## Running Prompts on Child VMs + +`--headless` only provisions — to run work on the child, SSH in with `bash -lc`: ```bash -spawn claude hetzner --headless --output json --prompt "Implement the auth module" +# Claude Code (use -p, NOT --print or --headless) +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'claude -p --dangerously-skip-permissions \"your prompt\"'" + +# Codex CLI +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'codex --quiet \"your prompt\"'" ``` -Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` +### IMPORTANT — do NOT waste tokens rediscovering these: +- **Always use `bash -lc`** — agent binaries are in `~/.local/bin/` which is only on PATH in login shells +- **Claude uses `-p`** for non-interactive output (NOT `--print`, NOT `--headless`) +- **Add `--dangerously-skip-permissions`** to skip approval prompts on child VMs +- **Never try `which claude` or `find`** to locate binaries — they are always at `~/.local/bin/` +- **Never create non-root users** to work around permission issues — just use `-p` ## Managing Children - `spawn list --json` — see running children -- `spawn delete --name --yes` — tear down a child VM +- `spawn delete --name --yes` — tear down a child VM (headless) - `spawn tree` — see the full spawn tree ## Context @@ -30,3 +43,4 @@ Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_ - You are running inside a spawned VM (SPAWN_DEPTH is set) - Cloud credentials are pre-configured — no auth prompts - OpenRouter billing is shared with the parent + diff --git a/skills/kilocode/spawn.md b/skills/kilocode/spawn.md index cf8db3a65..b1288f8c7 100644 --- a/skills/kilocode/spawn.md +++ b/skills/kilocode/spawn.md @@ -2,27 +2,40 @@ You have the `spawn` CLI installed. Use it to provision cloud VMs with AI agents. -## Usage +## Provision a Child VM ```bash spawn --headless --output json --prompt "task description" ``` -## Agents: claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie -## Clouds: hetzner, digitalocean, aws, gcp, sprite +**Agents:** claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie +**Clouds:** hetzner, digitalocean, aws, gcp, sprite -## Example +Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` + +## Running Prompts on Child VMs + +`--headless` only provisions — to run work on the child, SSH in with `bash -lc`: ```bash -spawn claude hetzner --headless --output json --prompt "Implement the auth module" +# Claude Code (use -p, NOT --print or --headless) +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'claude -p --dangerously-skip-permissions \"your prompt\"'" + +# Codex CLI +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'codex --quiet \"your prompt\"'" ``` -Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` +### IMPORTANT — do NOT waste tokens rediscovering these: +- **Always use `bash -lc`** — agent binaries are in `~/.local/bin/` which is only on PATH in login shells +- **Claude uses `-p`** for non-interactive output (NOT `--print`, NOT `--headless`) +- **Add `--dangerously-skip-permissions`** to skip approval prompts on child VMs +- **Never try `which claude` or `find`** to locate binaries — they are always at `~/.local/bin/` +- **Never create non-root users** to work around permission issues — just use `-p` ## Managing Children - `spawn list --json` — see running children -- `spawn delete --name --yes` — tear down a child VM +- `spawn delete --name --yes` — tear down a child VM (headless) - `spawn tree` — see the full spawn tree ## Context @@ -30,3 +43,4 @@ Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_ - You are running inside a spawned VM (SPAWN_DEPTH is set) - Cloud credentials are pre-configured — no auth prompts - OpenRouter billing is shared with the parent + diff --git a/skills/openclaw/SKILL.md b/skills/openclaw/SKILL.md index 92e4ee65d..dafb83b96 100644 --- a/skills/openclaw/SKILL.md +++ b/skills/openclaw/SKILL.md @@ -8,27 +8,40 @@ allowed-tools: Bash You have the `spawn` CLI installed. Use it to provision cloud VMs with AI agents. -## Usage +## Provision a Child VM ```bash spawn --headless --output json --prompt "task description" ``` -## Agents: claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie -## Clouds: hetzner, digitalocean, aws, gcp, sprite +**Agents:** claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie +**Clouds:** hetzner, digitalocean, aws, gcp, sprite -## Example +Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` + +## Running Prompts on Child VMs + +`--headless` only provisions — to run work on the child, SSH in with `bash -lc`: ```bash -spawn claude hetzner --headless --output json --prompt "Implement the auth module" +# Claude Code (use -p, NOT --print or --headless) +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'claude -p --dangerously-skip-permissions \"your prompt\"'" + +# Codex CLI +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'codex --quiet \"your prompt\"'" ``` -Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` +### IMPORTANT — do NOT waste tokens rediscovering these: +- **Always use `bash -lc`** — agent binaries are in `~/.local/bin/` which is only on PATH in login shells +- **Claude uses `-p`** for non-interactive output (NOT `--print`, NOT `--headless`) +- **Add `--dangerously-skip-permissions`** to skip approval prompts on child VMs +- **Never try `which claude` or `find`** to locate binaries — they are always at `~/.local/bin/` +- **Never create non-root users** to work around permission issues — just use `-p` ## Managing Children - `spawn list --json` — see running children -- `spawn delete --name --yes` — tear down a child VM +- `spawn delete --name --yes` — tear down a child VM (headless) - `spawn tree` — see the full spawn tree ## Context diff --git a/skills/opencode/AGENTS.md b/skills/opencode/AGENTS.md index cf8db3a65..b1288f8c7 100644 --- a/skills/opencode/AGENTS.md +++ b/skills/opencode/AGENTS.md @@ -2,27 +2,40 @@ You have the `spawn` CLI installed. Use it to provision cloud VMs with AI agents. -## Usage +## Provision a Child VM ```bash spawn --headless --output json --prompt "task description" ``` -## Agents: claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie -## Clouds: hetzner, digitalocean, aws, gcp, sprite +**Agents:** claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie +**Clouds:** hetzner, digitalocean, aws, gcp, sprite -## Example +Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` + +## Running Prompts on Child VMs + +`--headless` only provisions — to run work on the child, SSH in with `bash -lc`: ```bash -spawn claude hetzner --headless --output json --prompt "Implement the auth module" +# Claude Code (use -p, NOT --print or --headless) +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'claude -p --dangerously-skip-permissions \"your prompt\"'" + +# Codex CLI +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'codex --quiet \"your prompt\"'" ``` -Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` +### IMPORTANT — do NOT waste tokens rediscovering these: +- **Always use `bash -lc`** — agent binaries are in `~/.local/bin/` which is only on PATH in login shells +- **Claude uses `-p`** for non-interactive output (NOT `--print`, NOT `--headless`) +- **Add `--dangerously-skip-permissions`** to skip approval prompts on child VMs +- **Never try `which claude` or `find`** to locate binaries — they are always at `~/.local/bin/` +- **Never create non-root users** to work around permission issues — just use `-p` ## Managing Children - `spawn list --json` — see running children -- `spawn delete --name --yes` — tear down a child VM +- `spawn delete --name --yes` — tear down a child VM (headless) - `spawn tree` — see the full spawn tree ## Context @@ -30,3 +43,4 @@ Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_ - You are running inside a spawned VM (SPAWN_DEPTH is set) - Cloud credentials are pre-configured — no auth prompts - OpenRouter billing is shared with the parent + diff --git a/skills/zeroclaw/AGENTS.md b/skills/zeroclaw/AGENTS.md index cf8db3a65..b1288f8c7 100644 --- a/skills/zeroclaw/AGENTS.md +++ b/skills/zeroclaw/AGENTS.md @@ -2,27 +2,40 @@ You have the `spawn` CLI installed. Use it to provision cloud VMs with AI agents. -## Usage +## Provision a Child VM ```bash spawn --headless --output json --prompt "task description" ``` -## Agents: claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie -## Clouds: hetzner, digitalocean, aws, gcp, sprite +**Agents:** claude, codex, openclaw, zeroclaw, opencode, kilocode, hermes, junie +**Clouds:** hetzner, digitalocean, aws, gcp, sprite -## Example +Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` + +## Running Prompts on Child VMs + +`--headless` only provisions — to run work on the child, SSH in with `bash -lc`: ```bash -spawn claude hetzner --headless --output json --prompt "Implement the auth module" +# Claude Code (use -p, NOT --print or --headless) +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'claude -p --dangerously-skip-permissions \"your prompt\"'" + +# Codex CLI +ssh -o StrictHostKeyChecking=accept-new root@ "bash -lc 'codex --quiet \"your prompt\"'" ``` -Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_id":"..."}` +### IMPORTANT — do NOT waste tokens rediscovering these: +- **Always use `bash -lc`** — agent binaries are in `~/.local/bin/` which is only on PATH in login shells +- **Claude uses `-p`** for non-interactive output (NOT `--print`, NOT `--headless`) +- **Add `--dangerously-skip-permissions`** to skip approval prompts on child VMs +- **Never try `which claude` or `find`** to locate binaries — they are always at `~/.local/bin/` +- **Never create non-root users** to work around permission issues — just use `-p` ## Managing Children - `spawn list --json` — see running children -- `spawn delete --name --yes` — tear down a child VM +- `spawn delete --name --yes` — tear down a child VM (headless) - `spawn tree` — see the full spawn tree ## Context @@ -30,3 +43,4 @@ Returns JSON: `{"status":"success","ip_address":"...","ssh_user":"root","server_ - You are running inside a spawned VM (SPAWN_DEPTH is set) - Cloud credentials are pre-configured — no auth prompts - OpenRouter billing is shared with the parent +