* feat: add Cursor CLI agent across all clouds
Adds Cursor's terminal-based AI coding agent (the `agent` command from
cursor.com/cli) to the spawn matrix. Routes LLM requests through
OpenRouter via --endpoint flag and CURSOR_API_KEY env var.
- manifest.json: new cursor agent entry + all 6 cloud matrix entries
- agent-setup.ts: install, configure, launch, and update definitions
- Shell scripts for all 6 clouds (local, hetzner, aws, do, gcp, sprite)
- Config: writes ~/.cursor/cli-config.json with full permissions
- Icon: cursor.png from cursor.com/apple-touch-icon.png
- All cloud READMEs updated with cursor.sh usage
- CLI version bumped to 0.26.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add spawn skill injection for Cursor CLI
Writes a .cursor/rules/spawn.mdc rule file with alwaysApply: true
during setup, teaching the Cursor agent how to use the spawn CLI
to provision child cloud VMs. Uses the same base64 upload pattern
as other agent config files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Signed-off-by: Ahmed Abushagur <ahmed@abushagur.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: A <258483684+la14-1@users.noreply.github.com>
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* fix(install): force IPv4 DNS for npm installs and add junie binary verify
On Sprite VMs (and potentially other clouds with flaky IPv6 routing), npm
install of packages with native-binary postinstall scripts (kilocode, junie)
fails with i/o timeout when connecting to the npm registry over IPv6.
Changes:
- Add NODE_OPTIONS=--dns-result-order=ipv4first to NPM_PREFIX_SETUP so all
npm installs prefer IPv4, preventing the IPv6 timeout on first attempt
- Add cd ~ before postinstall re-run in KILOCODE_BINARY_VERIFY to avoid
"current working directory was deleted" errors in bun/node on retry
- Add JUNIE_BINARY_VERIFY snippet (analogous to kilocode) that detects and
recovers from a failed junie postinstall by re-running it from $HOME
- Apply JUNIE_BINARY_VERIFY to the junie install command
Fixes sprite kilocode and junie failures seen in E2E run 2026-03-23.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: update agent GitHub star counts
* fix(qa): load ANTHROPIC_AUTH_TOKEN as ANTHROPIC_API_KEY for interactive E2E
QA VMs store the Anthropic key as ANTHROPIC_AUTH_TOKEN in
/etc/spawn-qa-auth.env, but the e2e-interactive handler only looked for
ANTHROPIC_API_KEY — causing the 6am cron to fail immediately with
"ANTHROPIC_API_KEY not set". Accept either name when loading from the
auth env file.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(e2e): bump interactive harness timeout to 20min, fix zombie VM teardown
- SESSION_TIMEOUT_MS: 10min → 20min — provisioning a VM takes 3-4 min
before onboarding even starts; 10min wasn't enough headroom
- interactive.sh: call cloud_provision_verify even on harness failure so
teardown can find and delete any VM that was partially created (e.g.
on timeout mid-provision) — previously left zombie VMs with no .meta file
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: L <6723574+louisgv@users.noreply.github.com>
Hetzner disabled fsn1 (Falkenstein), causing a fatal HTTP 412 error for
all users using the default location. This change:
- Fetches available locations dynamically from GET /locations API
- Falls back to a hardcoded list if the API call fails
- On location-unavailable errors (HTTP 412 resource_unavailable),
prompts the user to pick a different location instead of crashing
- Changes default location from fsn1 to nbg1 (Nuremberg)
- Excludes previously-failed locations from the re-pick list
Closes#2764
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Security Reviewer <security@openrouter.ai>
Co-authored-by: L <6723574+louisgv@users.noreply.github.com>
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* chore: update agent GitHub star counts
* fix(gcp): double cloud-init wait timeout to 120 attempts (10 min)
GCP startup scripts installing Node.js 22 via `n` from curl take longer
than 5 min on cold starts. The previous 60-attempt (5 min) poll timed
out with "Startup script may not have completed, continuing..." and
proceeded to run `npm install -g @kilocode/cli` before npm was available,
causing `npm: command not found` errors.
Increase `maxAttempts` from 60 to 120 (10 min) in `waitForCloudInit` to
give the Node install enough time to complete on GCP cold starts.
Confirmed by E2E run: GCP kilocode failed with npm not found after all 60
poll attempts exhausted; all other GCP agents passed (they don't need Node).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
The manifest.json aws.defaults.bundle said "medium_3_0" ($20/mo) but
the code in aws/aws.ts defaults to "nano_3_0" ($3.50/mo). This field
is displayed to users during --dry-run preview via buildCloudLines(),
so the mismatch was user-facing. The advertised AWS price of "$3.50/mo"
also confirms nano_3_0 is the intended default.
Agent: code-health
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
PR #2567 fixed the openclaw modelDefault in code but missed the manifest
interactive_prompts field. Also update discovery.md Hetzner entry from
the old CX22/€3.29 to the current cx23/€3.49.
Agent: code-health
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Set every agent's featured_cloud to ["digitalocean", "sprite"] — one
primary recommendation (DigitalOcean) and one fallback (Sprite).
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: L <6723574+louisgv@users.noreply.github.com>
OpenClaw requires the openrouter/ provider prefix for model IDs.
The previous default (moonshotai/kimi-k2.5) was missing the prefix,
causing "Unknown model" warnings. Reverted to openrouter/openrouter/auto
which uses OpenRouter's auto-router to pick the best model per prompt.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: L <6723574+louisgv@users.noreply.github.com>
* feat: show cloud prices as lead indicator, default OpenClaw to Kimi K2.5
- Add `price` field to all clouds in manifest.json
- Show price as lead indicator in cloud picker hints, cloud listings, cloud info, and dry-run preview
- Change OpenClaw default model from openrouter/auto to moonshotai/kimi-k2.5 (top used model by OpenClaw users)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: add defensive guards for undefined cloud price in cached manifests
When users upgrade CLI but have cached manifests from before the price
field was added, c.price is undefined. Add ?? "" fallbacks and an
if-guard to prevent runtime crashes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: A <258483684+la14-1@users.noreply.github.com>
Cherry-picks UX improvements from #2321: simplifies cloud descriptions
to plain language, adds account/payment requirements upfront so users
know what they need before starting.
Fixes#2323
Agent: ux-engineer
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Simplify the cloud matrix by removing Daytona. All Daytona-specific code,
scripts, tests, and configuration have been removed. Daytona has been moved
to "Previously Considered" in the Cloud Provider Wishlist (#1183) and can
be revived on community demand.
Closes#2260
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- manifest.json: change aws auth to AWS_ACCESS_KEY_ID+AWS_SECRET_ACCESS_KEY
so the key-request system includes AWS in its missing-key emails
- sh/e2e/e2e.sh: clouds missing credentials now SKIP (not FAIL), so
running --cloud all is safe and only tests what's configured
- qa.sh: include e2e mode in cloud credential loading (was fixtures+quality only)
- qa-quality-prompt.md: e2e-tester now runs e2e.sh --cloud all --parallel 6 --skip-input-test
- qa-e2e-prompt.md: standalone e2e bot now runs e2e.sh --cloud all --parallel 6
Also wires KEY_SERVER_URL + KEY_SERVER_SECRET into /etc/spawn-qa-auth.env
(system change, not in this commit) so missing-key emails are actually sent.
Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: L <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Ahmed Abushagur <ahmed@abushagur.com>
Add key_request: false to Daytona in manifest.json and update
_parse_cloud_auths() to skip clouds with that flag set.
Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: add unique spawn IDs to prevent history record corruption
History records were matched by heuristic ("most recent record for this
cloud without a connection"), which caused saveVmConnection and
saveLaunchCmd to overwrite the wrong record during concurrent or failed
spawns.
Fix: every SpawnRecord now has a unique `id` (UUID). All history
operations (saveVmConnection, saveLaunchCmd, removeRecord,
markRecordDeleted, mergeLastConnection) match by id when available,
falling back to the old heuristic for pre-migration records.
The orchestrator (TS path) now creates the history record AFTER server
creation succeeds, not before — so failed provisions don't leave orphan
entries.
Also adds "Remove from history" option to the spawn ls action picker,
restoring the ability to soft-delete entries without destroying the VM.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add 18 unit tests for spawn ID history behavior
Tests cover:
- generateSpawnId returns unique UUIDs
- saveSpawnRecord auto-generates id when not provided
- saveVmConnection matches by spawnId (not heuristic)
- saveVmConnection does not cross-contaminate concurrent spawns
- saveVmConnection falls back to heuristic without spawnId
- saveLaunchCmd matches by spawnId (not heuristic)
- saveLaunchCmd falls back without spawnId
- removeRecord matches by id, not by timestamp+agent+cloud
- removeRecord handles duplicate timestamps correctly
- removeRecord falls back for legacy records without id
- markRecordDeleted targets correct record by id
- mergeLastConnection uses spawn_id from last-connection.json
- mergeLastConnection falls back to heuristic without spawn_id
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: enable biome import sorting with grouped imports
Adds organizeImports to biome assist config with groups:
1. Type imports
2. Node built-ins
3. Third-party packages
4. @openrouter/* packages
5. Aliases
Auto-fixed import order and lint issues across all TypeScript files,
including .claude/skills/ and packages/cli/src/.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Convert zeroclaw icon from mislabeled JPEG to actual PNG
- Fix zeroclaw .sources.json ext from "jpg" to "png"
- Fix zeroclaw manifest icon URL from .jpg to .png
- Add icon-integrity.test.ts (54 tests) that validates:
- Every agent/cloud icon exists as .png in assets/
- Every .png file contains actual PNG data (magic bytes check)
- Manifest icon URLs end with {id}.png
- .sources.json ext fields are all "png"
- No .jpg files exist in asset directories
Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fixes#2079 — local/hermes was the only remaining missing entry in the
cloud×agent matrix. All 49 entries are now implemented.
Agent: ux-engineer
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add hermes shim scripts for GCP, Hetzner, DigitalOcean, and Daytona
- Update manifest.json matrix entries from "missing" to "implemented"
- Bump default INSTALL_WAIT from 300s to 600s to fix zeroclaw timeout
on small VMs where Rust compilation takes 8-12 minutes
- Update cloud READMEs with hermes usage docs
- Bump CLI version to 0.11.18
Co-authored-by: Ahmed Abushagur <ahmed@abushagur.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Hermes agent was fully implemented in shared/agent-setup.ts (createAgents
includes hermes with install, envVars, and launchCmd) but the convenience
shell script sh/aws/hermes.sh was missing and the matrix showed "missing".
- Add sh/aws/hermes.sh (matching pattern of all other aws agent scripts)
- Update manifest.json: "aws/hermes" -> "implemented"
- Update sh/aws/README.md with Hermes Agent install command
Discovered during QA E2E sweep: E2E suite lists hermes in ALL_AGENTS and
would attempt to provision it; without the matrix entry and script the
agent was silently untracked as a missing implementation gap.
Co-authored-by: spawn-qa-bot <qa@openrouter.ai>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements Hermes Agent on Sprite cloud. Hermes is a persistent AI
agent by Nous Research with multi-platform messaging (Telegram,
Discord, Slack, CLI), memory across sessions, tool use, and native
OpenRouter support.
- Add hermes agent entry to manifest.json with env config
- Add matrix entries for all 7 clouds (sprite implemented, rest missing)
- Create sh/sprite/hermes.sh thin bash shim
Closes#1952
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat!: remove Fly.io cloud provider support
Drop Fly.io as a supported cloud provider. Sprite (which uses Fly.io
infrastructure internally) is retained.
- Delete packages/cli/src/fly/ module, sh/fly/ scripts, fixtures/fly/
- Remove fly cloud entry and 6 fly matrix entries from manifest.json
- Remove fly imports, destroy cases, and connection handlers from commands.ts
- Remove fly-ssh sentinel from security.ts
- Port E2E test suite from Fly.io to AWS Lightsail (fly-e2e.sh → aws-e2e.sh)
- Update README (7 clouds, 42 combinations), CLAUDE.md, and skill prompts
- Clean up fly references in build config, gitignore, icon sources
- Bump CLI version to 0.11.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* chore: restore Docker image build under sh/docker/
Move openclaw Dockerfile from sh/fly/docker/ to sh/docker/ and rename
workflow from fly-docker.yml to docker.yml with updated paths.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* style: fix extra blank lines in commands.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: spawn-bot <spawn-bot@openrouter.ai>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: L <6723574+louisgv@users.noreply.github.com>
The opencode project migrated from github.com/anomalyco/opencode to
github.com/sst/opencode. The old org's releases may no longer be
updated, causing opencode provisioning to fail.
Updates:
- Release download URL in agent-setup.ts
- url, creator, and repo fields in manifest.json
- Agent table link in README.md
Fixes#1948
Agent: code-health
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
The pinned scripts/install.sh is deprecated and does `git clone --depth 1`
of the latest ZeroClaw main branch, pulling in commit 63f485e which added
leak_detector.rs with Rust 2021 edition string literal errors.
Fix by switching to scripts/bootstrap.sh (the canonical installer) and
adding --prefer-prebuilt so ZeroClaw installs from a pre-built release
binary instead of compiling from source. The v0.1.6 release binary was
compiled before the problematic code was merged.
Fixes#1829
Agent: issue-fixer
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Adds ~/.zeroclaw/config.toml with autonomy settings (equivalent to
Claude Code's dangerouslySkipPermissions) so zeroclaw runs without
approval prompts inside sandbox VMs.
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces all references to zeroclaw-labs/zeroclaw/main/scripts/install.sh
with a pinned commit SHA (a117be64). This prevents supply chain attacks via
the mutable 'main' branch reference in curl|bash installer patterns.
Other curl|bash patterns (bun.sh, claude.ai, sprites.dev) use HTTPS to
vendor-controlled domains with no stable commit SHA to pin to -- these
follow industry-standard installer patterns and are left as-is.
Fixes#1670
-- refactor/ux-engineer
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove fly from featured clouds for all agents. Add digitalocean to
all agents. Move sprite to bottom of Claude's list.
Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reverts the 0.94.0 pin — install latest Codex and use the required
wire_api="responses" format.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: switch Codex wire_api from "responses" to "chat" for multi-turn stability
The Responses API format causes "Invalid Responses API request" errors on
the second turn and beyond — conversation history items round-trip through
OpenRouter with null content fields and missing IDs that fail validation.
Chat Completions format is fully supported and avoids this issue.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: pin Codex to 0.94.0 + wire_api=chat for multi-turn stability
OpenRouter's Responses API proxy drops required fields (id, content) from
conversation-history items on multi-turn requests, causing "Invalid
Responses API request" at input[6]+. Codex >=0.97.0 removed wire_api=chat
support (openai/codex#10157), so we pin to 0.94.0 — the last release where
Chat Completions format still works.
Tracking: https://github.com/openai/codex/issues/12114
TODO: unpin once OpenRouter /responses handles round-trip correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Enrich each agent entry with curated metadata fields: creator, repo,
license, created/added dates, GitHub stars, language, runtime, category,
tagline, and tags. This helps users compare and choose agents.
- Extend AgentDef interface with 12 optional metadata fields
- Add metadata to all 6 agents in manifest.json
- Add type validation tests for new fields
- Bump CLI version 0.5.12 → 0.5.13
Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Download favicon/icons for all 6 agents into assets/agents/:
- claude.png — Anthropic GitHub org avatar (4.5K)
- openclaw.png — openclaw.ai/apple-touch-icon.png (5.8K)
- zeroclaw.png — zeroclaw-labs GitHub org avatar (11K)
- codex.png — OpenAI GitHub org avatar (4.0K)
- opencode.svg — opencode.ai/favicon.svg (612B)
- kilocode.png — Kilo-Org GitHub org avatar (1.3K)
Update manifest.json icon fields to point to raw.githubusercontent.com
URLs for the local files (stable, CDN-served, versioned in repo).
Add assets/agents/.sources.json tracking each agent's canonical source
URL and extension for use by the refresh-favicon skill.
Add .claude/skills/refresh-favicon/SKILL.md — a skill that re-downloads
all agent icons from their source URLs, detects content types, updates
.sources.json, and syncs manifest.json icon fields.
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Why: local/opencode was listed as 'missing' in manifest.json — users
could not run OpenCode on their local machine via spawn.
- Add local/opencode.sh following the same pattern as other local scripts
(sources lib/common.sh, uses opencode_install_cmd from shared/common.sh,
injects OPENROUTER_API_KEY via generate_env_config)
- Update manifest.json matrix entry from 'missing' to 'implemented'
Agent: team-lead
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Point OpenClaw to https://github.com/openclaw/openclaw and OpenCode to
https://github.com/anomalyco/opencode. Update the OpenCode install command
and binary download URL to match the new repo.
Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Delete 32 agent scripts ({cloud}/{cline,gptme,plandex,continue}.sh across
8 clouds), remove the 4 agents from manifest.json with all their matrix
entries, update README matrix rows, remove stale mock agent binaries and
plandex.ai URL patterns from test harness, update CLI help examples to use
remaining agents, and bump version 0.5.7 → 0.5.8.
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Remove OVH as a cloud provider: delete ovh/ directory (lib + 11 agent
scripts), remove from manifest.json clouds and all ovh/* matrix entries,
update README matrix table, remove OVH destroy case in CLI commands,
and clean up all test harness references (mock.sh, mock-curl-script.sh,
record.sh, e2e.sh, cloud-lib-api-surface.test.ts, test-infra-sync.test.ts)
- Make featured_cloud an array (string[]) so agents can recommend multiple
clouds; update manifest.ts type, all 10 manifest.json values, and the
prioritizeCloudsByCredentials() comparison in commands.ts
- Sandbox OAuth in subprocess tests: add OPENROUTER_API_KEY=sk-or-test-fake
to the default env in cli-entry-edge-cases.test.ts and
cmdrun-resolution.test.ts so get_or_prompt_api_key() never triggers the
real OAuth browser flow during test runs
- Fix upload-file-security.test.ts SSH cloud count (5→4) after OVH removal
- Bump CLI version 0.5.6 → 0.5.7
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
These 5 agents are being dropped from the Spawn matrix. This removes
45 agent scripts across 9 clouds, cleans the manifest, test fixtures,
READMEs, CLI source, and shared library comments.
Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* 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>
Oracle Cloud is removed as a supported provider. Each agent now has a
`featured_cloud` field in manifest.json that controls cloud sort order
in the CLI picker — featured clouds appear after credential-detected
clouds but before CLI-installed ones, with a "recommended" hint.
Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: auto-run gcloud auth login on expired GCP tokens
Instead of telling users to run `gcloud auth login` manually, just
run it automatically when auth check fails or instance creation hits
a reauthentication error, then retry.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: prioritize clouds with CLI installed + hcloud CLI integration
When selecting a cloud provider, clouds are now sorted in 3 tiers:
1. Credentials detected (env vars set) — top priority
2. CLI installed (e.g., gcloud, hcloud, aws) — middle priority
3. Neither — default order
Also adds hcloud CLI-first support for Hetzner operations (server
create/delete/list, SSH key management, auth) with automatic fallback
to the existing REST API when hcloud is not available.
Closes#1370
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: rename aws-lightsail to aws across the project
Simplifies the cloud key from "aws-lightsail" to "aws" — AWS should
have a single entry regardless of the underlying service used.
Renames the directory, updates manifest.json matrix keys, CLI map,
test fixtures, README, and all agent scripts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reduce from 41 cloud providers to 10 (9 + local) curated for launch:
- local (free), oracle (free tier), hetzner (~€3.29/mo), ovh (~€3.50/mo),
fly (free tier), aws-lightsail ($3.50/mo), daytona (pay-per-second),
digitalocean ($4/mo), gcp ($7.11/mo), sprite (Fly.io VMs)
Changes:
- Remove 30 cloud directories, test fixtures, and provider-specific tests
- Slim manifest.json from 600 to 150 matrix entries, sorted by price
- Update CLAUDE.md with higher bar for adding clouds (prestige + pricing)
- Transform discovery service from code-implementing team to upvote-driven
demand tracker that creates proposal issues and only implements when a
proposal reaches 50+ upvotes
- Create GitHub issue #1183 as cloud wishlist with all dropped clouds
- Add discovery-team/cloud-proposal/agent-proposal labels
- Protect discovery-team issues from refactor team (no comments/changes)
- Fix all CLI tests (8034 pass, 0 fail) and shell tests (80 pass, 0 fail)
Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updated test assertions to reflect refactored helper functions and changed
error messages. Key changes:
- Fixed atlanticnet security tests to verify ensure_multi_credentials
delegation instead of checking implementation details in provider code
- Updated shared-common-decomposed-helpers tests to check actual error output
messages instead of outdated wording
- Fixed shared-github-auth test mocking to properly override command
builtin for platform detection
- Updated CloudSigma manifest auth field to explicitly mention HTTP Basic Auth
Tests now pass with 517/517 success across affected test files.
Agent: test-engineer
Co-authored-by: spawn-refactor-bot <refactor@openrouter.ai>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix manifest.json matrix entries: change local/opencode and hostkey/open-interpreter from 'implemented' to 'missing' (scripts don't exist)
- Rename agent entries in matrix to match actual agent keys (codex-cli→codex, gemini-cli→gemini, kilo→kilocode, open-interpreter→interpreter)
- Update test assertions to match actual output formats (e.g., 'Extra argument ignored' instead of 'extra argument')
- Fix shared-common-error-polling tests to check stderr output correctly
- Simplify agent-config-setup tests to work within shell context limitations
- Remove outdated install.sh test that expected non-existent 'WRAPPER' string
- Ensure CLI dependencies are installed before test runs
Co-authored-by: Spawn Refactor Service <refactor@spawn.service>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>