spawn/local
Ahmed Abushagur be904cbe1c
fix: install_agent double-escaping + github-auth reliability (#1460)
* docs: add spawn delete command to README

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: harden openclaw across all clouds — validation, reliability, performance

Fixes multiple issues causing openclaw to break on most clouds:

Bugs fixed:
- Double-prefixed model ID (openrouter/openrouter/auto) in config generation
- AWS gateway starting without env vars (missing .zshrc source)
- DigitalOcean sourcing .spawnrc instead of .zshrc for gateway
- Destructive rm -rf ~/.openclaw on re-runs (now mkdir -p)

Validation added:
- API key checked against OpenRouter /auth/key endpoint with re-prompt on failure
- Model ID verified against OpenRouter model list with re-prompt loop
- openrouter/auto and openrouter/free bypass model check

Reliability improvements:
- Standardized gateway launch with </dev/null & disown across all 9 clouds
- Gateway log auto-displayed on startup timeout for diagnostics
- 2GB swap added to cloud-init to prevent OOM on small VMs
- Portable install timeout (10 min) with macOS gtimeout fallback

Performance:
- Reordered spawn_agent: OAuth runs while VM provisions (saves 30-60s)
- Fly.io: bumped to 2GB RAM + 2 shared CPUs for openclaw
- Fly.io: tries bun first (faster), falls back to npm

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: skip sudo in gh install when running as root (Fly.io containers)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review — skip validation in tests, quote escaped cmd, escape model_id

- verify_openrouter_key and verify_openrouter_model skip network calls when
  SPAWN_SKIP_API_VALIDATION, BUN_ENV=test, or NODE_ENV=test is set
- install_agent timeout wrapper now quotes the escaped command for defense in depth
- model_id in openclaw JSON now uses json_escape() for consistency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: remove double-escaping in install_agent that broke shell operators

install_agent() was wrapping commands with printf '%q' + bash -c before
passing them to the run callback. But run callbacks (run_server, run_sprite,
ssh_run_server) already handle escaping for remote transport. The double-
escaping turned && || > | into literal characters, causing 'source' to
treat the entire command as a single filename.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use local github-auth.sh instead of curling from main

When running from a local checkout, base64-encode the local
github-auth.sh and send it inline to the remote machine. This
ensures fixes (like the sudo skip for root) take effect immediately
without waiting for a merge to main.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: handle github-auth errors gracefully instead of terminating

GitHub CLI setup is optional — failures should not abort the spawn
session. Guard both run_callback calls in offer_github_auth with
|| log_warn so the script continues even if gh install fails.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: use GOOGLE_GEMINI_BASE_URL to route Gemini CLI through OpenRouter

Gemini CLI ignores OPENAI_BASE_URL — it uses GEMINI_API_KEY to talk
directly to Google's API. The OpenRouter key is not a valid Google
API key, so all requests fail with "API key not valid".

Use GOOGLE_GEMINI_BASE_URL to redirect Gemini CLI to OpenRouter's
endpoint. Fixes all 9 cloud gemini scripts + manifest.json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: guard optional spawn_agent hooks so failures don't kill the session

With set -eo pipefail, any unguarded failure terminates the script.
Several optional operations in spawn_agent were unguarded:

- agent_configure: config file uploads (agent works with defaults)
- agent_save_connection: convenience JSON for spawn list
- agent_pre_launch: gateway daemons, startup hooks
- agent_pre_provision: pre-provision prompts
- .spawnrc shell hooks: hooking env vars into .bashrc/.zshrc

These now log warnings and continue instead of aborting. Critical
steps (cloud_authenticate, agent_install, cloud_provision) still
exit on failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 05:21:55 -05:00
..
lib feat: add server lifecycle management (reconnect + delete) (#1363) 2026-02-16 17:06:49 -08:00
aider.sh fix: prevent SSH hangs, fix command escaping, pin Python 3.12 for aider (#1439) 2026-02-18 04:23:15 -05:00
amazonq.sh refactor: introduce cloud adapter + spawn_agent runner system (#1340) 2026-02-16 16:25:44 -08:00
claude.sh fix: use ~/.spawnrc for env vars instead of inlining into .bashrc (#1362) 2026-02-16 17:05:17 -08:00
cline.sh refactor: introduce cloud adapter + spawn_agent runner system (#1340) 2026-02-16 16:25:44 -08:00
codex.sh refactor: introduce cloud adapter + spawn_agent runner system (#1340) 2026-02-16 16:25:44 -08:00
continue.sh refactor: introduce cloud adapter + spawn_agent runner system (#1340) 2026-02-16 16:25:44 -08:00
gemini.sh fix: install_agent double-escaping + github-auth reliability (#1460) 2026-02-19 05:21:55 -05:00
goose.sh refactor: introduce cloud adapter + spawn_agent runner system (#1340) 2026-02-16 16:25:44 -08:00
gptme.sh fix: use uv --upgrade to ensure Python 3.13-compatible Pillow across all clouds (#1436) 2026-02-18 03:21:59 -05:00
interpreter.sh fix: use uv --upgrade to ensure Python 3.13-compatible Pillow across all clouds (#1436) 2026-02-18 03:21:59 -05:00
kilocode.sh refactor: introduce cloud adapter + spawn_agent runner system (#1340) 2026-02-16 16:25:44 -08:00
nanoclaw.sh refactor: introduce cloud adapter + spawn_agent runner system (#1340) 2026-02-16 16:25:44 -08:00
openclaw.sh ux: wait for OpenClaw gateway to be ready before launching TUI (#1385) 2026-02-17 03:49:53 -05:00
plandex.sh refactor: introduce cloud adapter + spawn_agent runner system (#1340) 2026-02-16 16:25:44 -08:00
README.md feat: Add Amazon Q CLI on local machine (#887) 2026-02-13 05:47:17 -08:00

Local Machine

Run agents directly on your local machine without any cloud provisioning.

No server creation or destruction. Installs agents and injects OpenRouter credentials locally. Useful for local development and testing.

Quick Start

If you have the spawn CLI installed:

spawn claude local
spawn openclaw local
spawn nanoclaw local
spawn aider local
spawn goose local
spawn codex local
spawn interpreter local
spawn gemini local
spawn amazonq local
spawn cline local
spawn gptme local
spawn opencode local
spawn plandex local
spawn kilocode local
spawn continue local

Or run directly without the CLI:

bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/claude.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/openclaw.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/nanoclaw.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/aider.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/goose.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/codex.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/interpreter.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/gemini.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/amazonq.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/cline.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/gptme.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/opencode.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/plandex.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/kilocode.sh)
bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/continue.sh)

Non-Interactive Mode

OPENROUTER_API_KEY=sk-or-v1-xxxxx \
  bash <(curl -fsSL https://openrouter.ai/labs/spawn/local/claude.sh)

What It Does

Local scripts will:

  • Install the agent if not already present
  • Obtain an OpenRouter API key (via OAuth or environment variable)
  • Append environment variables to ~/.zshrc for the agent to use
  • Launch the agent

No cloud servers are created or destroyed.

Environment Variables

Variable Description
OPENROUTER_API_KEY OpenRouter API key (prompted via OAuth if not set)
SPAWN_PROMPT If set, runs the agent non-interactively with this prompt