Commit graph

333 commits

Author SHA1 Message Date
Ahmed Abushagur
c61736e511
feat: add Cursor CLI agent across all clouds (#3018)
* 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>
2026-03-26 13:53:49 -07:00
A
18b1a5f50f
fix(install): force IPv4 DNS for npm installs and add junie binary verify (#2920)
* 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>
2026-03-24 05:13:12 +07:00
A
9280489ada
fix(qa): load ANTHROPIC_AUTH_TOKEN as ANTHROPIC_API_KEY for interactive E2E (#2894)
* 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>
2026-03-23 11:24:26 +07:00
A
b46524887d
feat(hetzner): fetch locations from API, re-prompt on unavailable location (#2766)
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>
2026-03-18 10:39:42 -07:00
A
0e5bfd830b
fix(e2e): double GCP cloud-init wait timeout to 10 minutes for Node install (#2713)
* 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>
2026-03-17 11:51:41 -07:00
A
566695a256
chore: fix stale AWS default bundle in manifest (medium_3_0 → nano_3_0) (#2578)
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>
2026-03-13 07:15:34 -04:00
A
0541a70d64
chore: fix stale openclaw model default in manifest and hetzner type in discovery rules (#2576)
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>
2026-03-13 05:18:25 -04:00
A
ff8bff4c02
chore: standardize featured_cloud to digitalocean + sprite for all agents (#2548)
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>
2026-03-12 19:47:08 -04:00
Ahmed Abushagur
553cbad7bf
fix: revert OpenClaw default model to openrouter/auto (#2509)
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>
2026-03-12 01:06:50 -04:00
Ahmed Abushagur
24a3c7328d
feat: show cloud prices as lead indicator (#2347)
* 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>
2026-03-08 23:41:39 -07:00
A
2d69b2806b
fix: improve cloud descriptions for non-technical users (#2328)
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>
2026-03-08 04:07:25 -07:00
A
252e8fc726
feat: add Junie CLI (JetBrains) agent across all 6 clouds (#2300)
Adds JetBrains' Junie CLI as a new agent in the spawn matrix.

- agent: npm install -g @jetbrains/junie-cli, launched via `junie`
- env: JUNIE_OPENROUTER_API_KEY (native OpenRouter BYOK support)
- cloudInitTier: node (npm-based install)
- matrix: all 6 clouds implemented (local, hetzner, aws, digitalocean, gcp, sprite)
- icon: JetBrains org avatar (assets/agents/junie.png)
- tests: 7 unit tests in junie-agent.test.ts
- version bump: 0.15.9 → 0.15.10

Closes #2296

Agent: issue-fixer

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-03-07 19:38:45 -08:00
A
035e4bf830
Remove Daytona cloud provider from codebase (#2261)
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>
2026-03-06 18:53:08 -05:00
A
df0593fb21
feat(e2e): Run E2E tests on all configured clouds, not just AWS (#2236)
- 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>
2026-03-06 00:06:36 -08:00
A
9291dd9c76
fix: Exclude Daytona from key-request emails (#2237)
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>
2026-03-06 00:04:48 -08:00
L
65a81edc57
fix: add unique spawn IDs to prevent history record corruption (#2235)
* 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>
2026-03-05 23:27:03 -08:00
A
4d44353464
fix: ensure all icons are PNG and add icon-integrity test (#2191)
- 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>
2026-03-04 09:38:07 -08:00
A
1f879e1d1e
chore: refresh agent GitHub stars and icon metadata (#2179)
Notable star count changes:
- openclaw: 212,334 → 256,970 (+44,636)
- opencode: 107,223 → 115,408 (+8,185)
- zeroclaw: 15,177 → 21,867 (+6,690)
- claude: 67,857 → 73,410 (+5,553)
- codex: 61,159 → 62,925 (+1,766)
- hermes: 1,016 → 1,617 (+601)
- kilocode: 15,619 → 16,172 (+553)

Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-03 23:49:15 -08:00
A
b755c6966c
feat: add local/hermes to complete the 7x7 matrix (#2091)
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>
2026-03-01 22:04:38 -05:00
A
d713f9650f
feat: add hermes agent to 4 clouds, bump install wait to 600s (#2084)
- 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>
2026-03-01 19:31:50 -05:00
A
dc27f456ea
fix(e2e): add sh/aws/hermes.sh and mark aws/hermes as implemented (#2042)
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>
2026-02-28 20:38:26 -05:00
A
187cd6aafc
feat(agent): add Hermes Agent (Nous Research) (#2023)
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>
2026-02-28 06:53:13 -08:00
A
d04096a15b
feat!: remove Fly.io cloud provider support (#1979)
* 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>
2026-02-27 00:06:32 -05:00
A
0b7f035e4a
fix: update opencode GitHub org from anomalyco to sst/opencode (#1951)
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>
2026-02-26 06:34:26 -08:00
A
7419ff8290
fix: use npm install for OpenClaw to fix Node module resolution (#1878)
OpenClaw runs under Node, but bun's flat node_modules layout breaks
Node's require() resolver when dynamically loading channel plugins.
Switching to npm install ensures standard node_modules layout.

Fixes #1875

Agent: code-health

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-24 04:51:09 -05:00
A
8812f693c0
fix: switch ZeroClaw install to bootstrap.sh with --prefer-prebuilt (#1836)
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>
2026-02-24 00:08:49 -05:00
A
b51b5aa11e
feat: configure zeroclaw for full autonomy in spawned VMs (#1811)
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>
2026-02-23 12:29:48 -05:00
A
9f43113452
fix: pin zeroclaw installer to commit SHA instead of mutable main branch (#1683)
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>
2026-02-22 01:49:44 -05:00
A
9b068aae0b
fix: update featured_cloud lists in manifest (#1671)
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>
2026-02-21 21:30:47 -08:00
Ahmed Abushagur
76cb8ead3b
fix: unpin Codex version, restore wire_api=responses (#1608)
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>
2026-02-21 20:12:23 +00:00
L
031b8fbcf0
update: Claude Code description to match Anthropic's official branding (#1542)
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-02-20 20:19:28 -08:00
A
6782618b7c
feat: add user-friendly cloud descriptions to manifest (#1529)
Replace technical API-focused cloud descriptions with short,
user-friendly ones that highlight pricing and key selling points.

Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-20 08:18:19 -08:00
L
f2df9bffa5
feat: add gcp and aws (Lightsail) to featured_cloud for all agents (#1524)
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-02-20 07:08:02 -08:00
Ahmed Abushagur
b5d174a472
fix: pin Codex to 0.94.0 + wire_api=chat for multi-turn stability (#1518)
* 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>
2026-02-20 04:49:35 -05:00
A
d8785708c9
feat: add cloud provider icons and metadata support (#1503)
Download favicon/icons for all 8 cloud providers into assets/clouds/:
- local.png     — OpenRouter apple-touch-icon (6.4K)
- hetzner.png   — Hetzner 180x180 apple icon (1.9K)
- fly.png       — Fly.io apple-touch-icon (6.4K)
- aws.png       — AWS 144x144 touch icon (3.1K)
- daytona.png   — Daytona favicon from Framer CDN (1.2K)
- digitalocean.png — DigitalOcean apple-touch-icon (6.0K)
- gcp.png       — Google Cloud super_cloud icon (4.2K)
- sprite.png    — Sprites.dev apple-touch-icon (1.9K)

Add assets/clouds/.sources.json tracking canonical source URLs.
Add optional `icon` field to CloudDef interface.
Update manifest.json with raw.githubusercontent.com icon URLs.
Add icon URL type validation test for clouds.
Bump CLI version 0.5.13 → 0.5.14.

Co-authored-by: lab <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-20 00:51:40 -05:00
A
6ae650b5e8
feat: add agent stats & metadata to manifest (#1501)
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>
2026-02-19 21:21:18 -08:00
L
635d358ca3
feat: add agent icon assets and refresh-favicon skill (#1499)
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>
2026-02-19 20:55:13 -08:00
A
87d6fdd240
feat: implement local/opencode script (#1481)
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>
2026-02-19 16:49:50 -05:00
L
57d7d2b014
feat: add icon URLs to all agent manifest entries (#1482)
Add GitHub org avatar URLs as icon fields for all 6 agents,
sourced from the GitHub API (avatars.githubusercontent.com):

- claude:    u/76263028 (Anthropic)
- openclaw:  u/139423088 (OpenRouterTeam)
- zeroclaw:  u/261820148 (zeroclaw-labs)
- codex:     u/14957082 (OpenAI)
- opencode:  u/208539476 (opencode-ai)
- kilocode:  u/201822503 (Kilo-Org)

All use s=200&v=4 for consistent 200px square sizing.
Add optional icon?: string field to AgentDef TypeScript type.
Bump CLI version 0.5.10 → 0.5.11.

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-02-19 13:32:01 -08:00
A
48d418ccb5
fix: update OpenClaw and OpenCode repository URLs (#1478)
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>
2026-02-19 11:53:15 -08:00
L
a67d83ed38
feat: reorder agents and remove NanoClaw (#1477)
* feat: add ZeroClaw agent (14.9k stars, native OpenRouter support)

Add ZeroClaw — a Rust-based autonomous AI assistant framework by
Harvard/MIT/Sundai.Club communities — across all 8 clouds.

Scripts: local, hetzner, digitalocean, fly, aws, gcp, daytona, sprite
Install: bootstrap.sh with --install-rust + --install-system-deps
Config:  zeroclaw onboard --provider openrouter (via agent_configure)
Env:     OPENROUTER_API_KEY + ZEROCLAW_PROVIDER=openrouter (native support)
Launch:  zeroclaw agent

Note: ZeroClaw compiles from Rust source (~5-10 min build time).
A build-time warning is shown to set expectations.

Also update test/mock-curl-script.sh to stub zeroclaw install URLs and
add zeroclaw to mock agent binaries in test/mock.sh.

Bump CLI version 0.5.8 → 0.5.9.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

* feat: reorder agents and remove NanoClaw

New agent order: claude → openclaw → zeroclaw → codex → opencode → kilocode

- Remove NanoClaw (8 scripts + manifest entry + matrix entries + README row)
- Reorder manifest.json agents section to match new order
- Reorder matrix entries by cloud (local/hetzner/fly/aws/daytona/digitalocean/gcp/sprite)
  with agents in new order within each cloud block
- Update README matrix table row order
- Update test/mock.sh mock agent binary list to match
- Bump CLI version 0.5.9 → 0.5.10

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-02-19 11:39:03 -08:00
L
f7458952b0
feat: remove Cline, gptme, Plandex, and Continue agents (#1475)
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>
2026-02-19 11:12:46 -08:00
L
32522882c1
feat: remove OVH cloud and make featured_cloud an array (#1474)
- 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>
2026-02-19 11:06:27 -08:00
A
5612cda40b
feat: remove Aider, Goose, Open Interpreter, Gemini CLI, Amazon Q from matrix (#1472)
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>
2026-02-19 12:31:00 -05:00
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
A
8a4f5873f9
feat: remove Oracle Cloud, add featured_cloud per agent (#1430)
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>
2026-02-17 22:52:41 -08:00
A
c4eccbd72f
feat: prioritize clouds with CLI installed + hcloud CLI integration (#1375)
* 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>
2026-02-16 20:12:35 -08:00
A
3db288c3dd
feat: trim to 9 curated launch clouds, upvote-driven discovery (#1184)
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>
2026-02-15 00:19:39 -08:00
A
aaa886a7a9
test: fix failing test assertions to match actual implementation (#1130)
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>
2026-02-14 14:14:33 -08:00
A
a67f8dd837
test: Fix manifest consistency and improve test assertions (#1087)
- 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>
2026-02-14 01:10:03 -08:00