Commit graph

1598 commits

Author SHA1 Message Date
A
793dee20ae
fix: improve CloudSigma error messages and update RamNode README (#947)
CloudSigma UX fixes:
- Use log_error consistently for remediation hints (was log_warn)
- Add "Common issues" block to create_server failure
- Add actionable hints to server timeout error
- Extract API error message instead of dumping raw response
- Fix README: VNC password is random, not hardcoded

RamNode README:
- Update implemented agents list from 9 to all 15

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 07:54:31 -08:00
A
8dbe5d0710
fix: validate CLOUDSIGMA_REGION to prevent SSRF via URL injection (#948)
CloudSigma was the only cloud provider that did not validate its region
env var before interpolating it into the API base URL. A crafted
CLOUDSIGMA_REGION value (e.g. "evil.com/foo#") could redirect all API
calls — including HTTP Basic Auth credentials — to an attacker's server.

Adds validate_region_name check in create_server, matching the pattern
used by all other providers (DigitalOcean, Vultr, Hetzner, Fly, etc.).

Agent: security-auditor

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 07:51:07 -08:00
A
65127e2e24
refactor: extract ensure_jq to shared lib and decompose CloudSigma helpers (#946)
- Extract duplicated _ensure_jq from hetzner and hostkey into shared
  ensure_jq in shared/common.sh (removes ~60 lines of duplication)
- Replace CloudSigma hand-rolled ensure_cloudsigma_credentials with
  ensure_multi_credentials (removes ~20 lines of inline Python)
- Replace _wait_for_cloudsigma_server (63 lines) with
  generic_wait_for_instance + _resolve_cloudsigma_ip helper
- Extract _find_ubuntu_image_uuid and _clone_drive from
  create_cloudsigma_drive (60 -> 23 lines)
- Extract _get_ssh_key_uuid from create_server inline Python
- Replace hand-rolled SSH functions with shared SSH helpers
  (SSH_USER=cloudsigma)

Net reduction: ~158 lines across 4 files.

Agent: complexity-hunter
-- refactor/complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 07:34:36 -08:00
A
51d217add1
refactor: deduplicate _ensure_jq and decompose DO create_server (#943)
- Extract `ensure_jq()` from hetzner and hostkey into shared/common.sh,
  eliminating 64 lines of identical duplicated code
- Decompose DigitalOcean `create_server()` by extracting error handling
  into `_do_check_create_error()` helper, and using the shared
  `extract_api_error_message` instead of inline Python parsing
- Use shared `_extract_json_field` for droplet ID extraction

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 07:25:08 -08:00
A
904bebfb70
test: add 68 tests for run retry logic and display formatting helpers (#945)
Cover previously untested internal functions:
- formatCacheAge (index.ts): cache age to human-readable string conversion
- handleUserInterrupt (commands.ts): Ctrl+C detection in error messages
- runWithRetries (commands.ts): SSH failure retry logic with MAX_RETRIES
- printInfoHeader (commands.ts): agent/cloud info page header formatting
- printGroupedList (commands.ts): grouped display with type labels
- renderListTable (commands.ts): spawn history table output formatting

Includes boundary transition tests, edge cases, and integration scenarios.

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 07:24:49 -08:00
A
527e701676
feat: Add ramnode/codex (#796)
* feat: Add ramnode/codex script

Agent: gap-filler
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: address security review feedback for ramnode/codex

- Use inject_env_vars_ssh instead of raw heredoc (fixes command injection)
- Restore wait_for_cloud_init call after verify_server_connectivity
- Use .zshrc instead of .bashrc for consistency with other ramnode scripts
- Restore server info in success message

Agent: pr-maintainer

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

---------

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 07:19:00 -08:00
A
2e7b083f8f
fix: show cloud URL for missing credentials in dry-run and add spawn list --clear (#944)
Two UX improvements:

1. Dry-run credential status now shows the cloud provider's URL next to
   missing cloud-specific auth vars (e.g., HCLOUD_TOKEN), helping users
   find where to create their credentials. Previously only
   OPENROUTER_API_KEY showed a URL hint.

2. Added `spawn list --clear` command to let users clear their spawn
   history. Previously there was no way to reset the 100-entry history
   file without manually deleting ~/.spawn/history.json.

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 07:16:14 -08:00
A
78d95d0399
fix: use safe inject_env_vars helpers in 4 missed scripts (#941)
Replaces unsafe direct shell interpolation of OPENROUTER_API_KEY with
the inject_env_vars_ssh/inject_env_vars_local helpers that use
single-quoted values to prevent shell injection.

Affected scripts:
- codesandbox/codex.sh
- codesandbox/interpreter.sh
- codesandbox/gptme.sh
- atlanticnet/goose.sh

This is the same class of fix applied in PR #937 to 3 other scripts,
but these 4 were missed.

Agent: security-auditor

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 07:00:26 -08:00
A
eacaf6fd03
refactor: replace hand-rolled polling with generic_wait_for_instance in 3 clouds (#850)
Cherry, RamNode, and Scaleway each had custom IP-polling loops (30-38 lines)
that duplicated the logic already in shared/common.sh's generic_wait_for_instance.
Replace them with single-call delegates, removing ~100 lines and 2 helper functions.

- cherry: _cherry_wait_for_ip -> generic_wait_for_instance, remove _cherry_extract_primary_ip
- ramnode: _ramnode_wait_for_ip -> generic_wait_for_instance
- scaleway: _scaleway_power_on_and_wait polling -> generic_wait_for_instance, remove _scaleway_extract_ip

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 06:52:22 -08:00
A
1124af265c
feat: add CloudSigma cloud provider (#860)
* feat: add CloudSigma cloud provider

Add CloudSigma as a new cloud provider with API-first architecture:

- Create cloudsigma/lib/common.sh with HTTP Basic Auth support
- Implement cloudsigma/claude.sh and cloudsigma/aider.sh agent scripts
- Add CloudSigma to manifest.json (38th cloud provider)
- Add matrix entries for all 15 agents (2 implemented, 13 missing)
- Update test/record.sh with CloudSigma endpoints and auth handling
- Update test/mock.sh with URL-stripping for CloudSigma API
- Add cloudsigma/README.md with usage documentation

CloudSigma features:
- API v2.0 with HTTP Basic Auth (email:password)
- Regions: ZRH (Zurich), WDC (Washington DC), LVS (Las Vegas)
- Granular resource control (CPU/RAM/Disk independently configurable)
- Ubuntu 24.04 cloned from public library drives
- SSH access via cloudsigma user
- Pay-as-you-go pricing starting at ~$14/month

Agent: cloud-scout

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: address security review comments for CloudSigma provider

- [CRITICAL] Fix command injection in credential saving: use sys.argv
  instead of raw shell interpolation in Python strings
- [CRITICAL] Fix shell injection in create_cloudsigma_drive: pass name
  and size via sys.argv instead of inline interpolation
- [CRITICAL] Fix shell injection in SSH key fingerprint lookups: pass
  fingerprint via sys.argv
- [HIGH] Replace hardcoded VNC password with random generation via
  openssl rand -hex 8
- [MEDIUM] Fix config file path injection: pass via sys.argv

Agent: pr-maintainer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 06:50:25 -08:00
A
a74a8cebcb
refactor: decompose Daytona create_server and test_daytona_token into focused helpers (#939)
Break the 94-line create_server into smaller single-responsibility functions:
- _daytona_create_with_resources: explicit CPU/memory/disk creation path
- _daytona_create_with_class: class-based creation path
- _resolve_sandbox_id: sandbox ID extraction from daytona info
- _is_snapshot_conflict: snapshot/resource conflict detection

Extract duplicated auth error handling from test_daytona_token:
- _is_daytona_auth_error: auth error pattern matching
- _daytona_auth_error: formatted auth error message

No functional changes. All public function signatures preserved.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 06:46:13 -08:00
A
f806085bb6
fix: improve UX of error messages and status output (#938)
- Remove redundant "Warning:" prefix from API key format message (log_warn
  already conveys warning status)
- Fix incorrect `export VAR=token spawn ...` syntax in auth failure hint
  (export makes it persistent, inline env var syntax is correct)
- Replace attempt/retry jargon with elapsed time in SSH wait and instance
  polling messages (users care about time, not internal retry counts)
- Show instance IP in friendlier "ready (IP: x.x.x.x)" format
- Move HTTP status codes from error title to body in download failures
  (cleaner error headline, details still available)
- Simplify dry-run credential warning (remove confusing double-negative
  "without --dry-run")
- Remove redundant "Warning:" prefix from extra arguments message

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
2026-02-13 06:45:04 -08:00
A
fa52d5978a
fix: use safe inject_env_vars helpers in 3 missed scripts (#937)
Three scripts were missed in the previous inject_env_vars migration
(commit d785571): atlanticnet/amazonq.sh, codesandbox/cline.sh, and
civo/continue.sh. These still used raw heredoc/echo patterns that
embed OPENROUTER_API_KEY directly into shell command strings without
escaping, allowing potential command injection if the API key contained
shell metacharacters (quotes, backticks, dollar signs).

Replace with inject_env_vars_ssh (Atlantic.Net, Civo) and
inject_env_vars_local (CodeSandbox) which use generate_env_config
to safely single-quote all values.

Agent: security-auditor

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 06:42:13 -08:00
L
13575a7a20
feat: Add PR comment triage to security reviewer and refactor pr-maintainer (#940)
Both the security team's pr-reviewer and the refactor team's pr-maintainer
now read PR comments before passing verdict. If comments indicate a PR is
superseded, duplicate, or abandoned, they close it instead of reviewing.

Security reviewer: new step 2 (comment-based triage) before staleness check,
steps renumbered 3→4 through 11→12, verdict options include closed-duplicate.

Refactor pr-maintainer: reads comments first, closes when clearly indicated,
rule updated from "NEVER close" to "only close when comments justify it".

Also updates CLAUDE.md dual-mode table: Agents → Teammates.

Co-authored-by: Security Reviewer <security-reviewer@spawn.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 06:25:45 -08:00
A
f696f57129
test: add 44 tests for extract_api_error_message and generic_wait_for_instance (#798)
These two critical shared/common.sh functions had zero test coverage despite
being used across 4+ and 9 cloud providers respectively (10+ call sites each).

extract_api_error_message tests cover:
- All JSON error field patterns (message, error, error.message, error_message, reason)
- Field priority ordering
- Fallback behavior for invalid JSON, empty input, unrecognized fields
- Real-world API response formats (Hetzner, DigitalOcean, Vultr, Contabo)
- Edge cases (special characters, unicode, arrays, null)

generic_wait_for_instance tests cover:
- Successful polling (first attempt and multi-attempt)
- IP extraction from flat and deeply nested JSON
- Timeout behavior when status never reaches target
- Continued polling when API returns errors or invalid JSON
- Polling when status matches but IP is empty
- Logging output (progress, success, timeout)

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-13 06:25:25 -08:00
A
0fa2b630df
docs: Sync README matrix with manifest.json (#884)
Agent: team-lead

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 06:23:55 -08:00
A
71e5eb6ab7
feat: Add codesandbox/kilocode (#874)
Agent: gap-filler-4

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 06:23:50 -08:00
A
c0cb32f9ce
test: add 97 tests for list command output helpers (#846)
* test: add 97 tests for list command output helpers

Cover buildRetryCommand (prompt truncation at 80 chars, quote escaping,
prompt-file fallback), resolveDisplayName (null manifest fallback),
buildRecordLabel/buildRecordHint (30-char hint truncation, picker
formatting), parseAuthEnvVars (multi-var parsing, validation),
hasCloudCredentials (multi-var auth, empty/unset vars),
getImplementedClouds/getImplementedAgents (manifest filtering),
isRetryableExitCode (SSH 255 detection), formatTimestamp (edge cases),
and getStatusDescription (404 special case).

Agent: test-engineer
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>

* fix: import actual functions instead of duplicating them in tests

- Export formatTimestamp, buildRecordLabel, buildRecordHint from commands.ts
- Replace 11 duplicated function implementations with imports from commands.ts
- Add @clack/prompts mock (required when importing commands.ts)
- All 97 tests still pass against the real production code

Agent: pr-maintainer
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: resolve rebase conflicts and update tests for formatRelativeTime

Merged formatRelativeTime from main, exported formatTimestamp and
buildRecordHint, updated tests to use relative time assertions.

Agent: pr-maintainer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-13 06:22:18 -08:00
A
4bb0165d59
feat: Add codesandbox/gptme (#872)
* feat: Add codesandbox/gptme

Agent: gap-filler
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: use safe quoting pattern for API key injection in gptme

Agent: pr-maintainer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 06:21:50 -08:00
A
c2ed7a21ad
feat: Add cline on Atlantic.Net (#892)
* feat: Add cline on Atlantic.Net

Agent: gap-filler

* fix: use inject_env_vars_ssh, fix README markdown, fix trailing comma

Agent: pr-maintainer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 06:21:44 -08:00
A
ce904383d2
feat: Add interpreter on Atlantic.Net (#890)
* feat: Add interpreter on Atlantic.Net

Agent: gap-filler

* fix: use inject_env_vars_ssh, fix README markdown, use zshrc

Agent: pr-maintainer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 06:16:59 -08:00
L
58dcc6405c
refactor: Replace 'agent' with 'teammate' terminology in team prompts (#936)
Team leaders were outputting "Continue waiting for agent results" because
the prompts used "agent" language throughout. Updated all 4 team scripts
to use "teammate" and "spawn team" terminology per the Anthropic agent
teams documentation (https://code.claude.com/docs/en/agent-teams).

Changes across refactor.sh, security.sh, discovery.sh, qa-cycle.sh:
- "agents" → "teammates" when referring to team members
- "agent teams" → "spawn teams" when referring to the coordination concept
- Preserved: Agent: commit trailers, AGENT-NAME sign-offs, subagent_type,
  agent-teams URL, and "agent" as software product (AI agents)

Co-authored-by: Security Reviewer <security-reviewer@spawn.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 06:14:14 -08:00
A
c72b442411
feat: Add codex on CodeSandbox (#889)
Agent: gap-filler

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
2026-02-13 06:11:54 -08:00
A
de04724c6d
feat: Add local/amazonq (#871)
Implements Amazon Q CLI on local machine with OpenRouter integration.

Agent: gap-filler-5

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 06:11:13 -08:00
A
35ef679a38
feat: Add goose on Atlantic.Net (#886)
Agent: gap-filler

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
2026-02-13 06:11:10 -08:00
A
bdde11c356
feat: Add interpreter on CodeSandbox (#891)
Agent: gap-filler

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
2026-02-13 06:10:50 -08:00
A
c833f4ed3e
fix: improve UX with macOS compat fix, clearer messages, and less alarming prompts (#934)
- Fix macOS compatibility bug in Atlantic.Net API signature: `base64 -w 0`
  fails on macOS (no `-w` flag); add fallback like other providers
- Replace misleading "Use 'csb' CLI dashboard" in CodeSandbox interactive
  session with link to the actual web terminal at codesandbox.io/dashboard
- Soften preflight credential check prompt from "will likely fail" to
  "will prompt you to authenticate" (scripts have built-in auth flows)
- Bump CLI version to 0.2.72

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 06:10:47 -08:00
A
75d7be29a4
fix: improve UX for stale manifest cache, list rerun hints, and version info (#805)
- Show warning when manifest is loaded from stale cache (offline fallback)
  so users know the data may be outdated
- Fix list footer rerun command: reuse buildRetryCommand instead of
  truncating prompts with "..." which produced broken copy-paste commands
- Show manifest cache age in "spawn version" output for troubleshooting
- Bump CLI version to 0.2.67

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 06:09:56 -08:00
A
4c1a344a7a
test: add 59 tests for JSON extraction helpers in shared/common.sh (#804)
Cover _extract_json_field and extract_api_error_message functions that
were recently extracted (PRs #673, #767) but had zero test coverage.
These are critical infrastructure used by Hetzner, DigitalOcean, Vultr,
and Contabo for API error parsing and by generic_wait_for_instance for
status polling.

Tests cover:
- _extract_json_field: basic extraction, nested fields, default values,
  complex Python expressions, real-world cloud provider patterns, edge cases
- extract_api_error_message: all standard error field patterns (message,
  error, error.message, error.error_message, reason), field priority order,
  fallback behavior, real-world cloud provider error formats, edge cases

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 06:07:50 -08:00
A
28ed8d09b7
feat: Add amazonq on Atlantic.Net (#888)
Agent: gap-filler

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
2026-02-13 06:05:05 -08:00
A
099d8020cc
test: add 343 cloud lib source chain verification tests (#935)
Verify that every cloud provider's lib/common.sh correctly sources
shared/common.sh and exposes required shared functions. Tests run
each cloud's lib in a real bash subprocess to catch source chain
breaks, syntax errors, and missing function definitions.

Coverage:
- Source chain integrity for all 36 cloud lib files
- Required shared function availability (logging, OAuth, API, SSH)
- json_escape behavior (quotes, newlines, backslashes, tabs)
- validate_api_token and validate_server_name security
- calculate_retry_backoff bounds
- extract_api_error_message parsing
- Cross-cloud consistency (SSH_OPTS, API helpers)
- bash -n syntax check on all lib files

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 06:02:06 -08:00
A
8c1183cdbc
feat: Add cline on CodeSandbox (#885)
Agent: gap-filler

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
2026-02-13 06:01:30 -08:00
A
5948de15b8
fix: show 'ready to go' in quick start when all credentials are set (#866)
When all required credentials (OPENROUTER_API_KEY + cloud auth vars) are
already configured, the Quick start section in `spawn <agent>` and
`spawn <cloud>` now shows a concise "credentials detected -- ready to go"
message with just the launch command, instead of showing export instructions
the user doesn't need.

Previously, the `hasCreds` variable was computed but unused in both
`printCloudQuickStart` and `cmdAgentInfo`. This change puts it to use
to give users a clear signal when they're ready to launch.

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 05:58:22 -08:00
A
d785571026
fix: use safe inject_env_vars helpers instead of raw shell interpolation (#932)
Replace unsafe heredoc/echo patterns with inject_env_vars_ssh (Atlantic.Net)
and inject_env_vars_local (CodeSandbox) for API key injection. The previous
patterns embedded OPENROUTER_API_KEY values directly into shell command strings
without escaping, allowing potential command injection if the API key contained
shell metacharacters (quotes, backticks, dollar signs).

Affected scripts (11 total):
- atlanticnet: codex, continue, gemini, gptme, kilocode, opencode
- codesandbox: amazonq, gemini, goose, opencode, plandex

The safe helpers (generate_env_config) properly single-quote all values and
escape embedded single quotes, preventing shell interpretation of special chars.

Agent: security-auditor

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 05:57:06 -08:00
A
bcb2d63f35
refactor: extract shared SDK wrapper in codesandbox/lib/common.sh (#862)
The file had 5 nearly-identical inline Node.js scripts, each repeating
the same require/init/async-IIFE/try-catch boilerplate. Extract two
shared helpers:

- _csb_sdk_eval: runs arbitrary JS with an authenticated SDK instance
- _csb_run_cmd: connects to a sandbox and runs a command (used by
  run_server and interactive_session)

interactive_session was a verbatim copy of run_server — it now delegates
to run_server directly.

Net result: -96 lines, +49 lines (287 → 241 lines total).

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-13 05:56:35 -08:00
A
1d73f8e04b
fix: improve local script UX -- add SPAWN_PROMPT support, fix prompt escaping, standardize messages (#863)
- local/cline.sh: Add missing SPAWN_PROMPT non-interactive mode support,
  replace manual sed -i.bak env var handling with inject_env_vars_local
  (eliminates leftover .bak files), add installation verification
- local/plandex.sh: Replace manual shell config handling with
  inject_env_vars_local for consistency, fix printf '%q' prompt escaping
  that corrupted prompt text with literal backslashes
- local/aider.sh: Fix printf '%q' prompt escaping -- pass SPAWN_PROMPT
  directly as quoted argument instead of shell-escaping it
- local/interpreter.sh: Same printf '%q' fix as aider.sh
- 7 local scripts: Standardize "Appending environment variables to
  ~/.zshrc..." to "Setting up environment variables..." for consistency
  with all other cloud providers

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 05:56:29 -08:00
A
dd224612e9
refactor: replace raw curl calls in render/lib/common.sh with render_api wrapper (#933)
Add a centralized `render_api` function that delegates to `generic_cloud_api`,
giving Render the same automatic retry logic (429/503/network errors with
exponential backoff) that all other providers already have.

- `_render_create_service`: raw curl POST -> `render_api POST`
- `_render_wait_for_service`: raw curl GET -> `render_api GET` + `_extract_json_field`
- `cleanup_server`: raw curl DELETE -> `render_api DELETE`

Also improves the wait loop with `INSTANCE_STATUS_POLL_DELAY` support and
better timeout messaging matching the standard provider pattern.

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 05:56:20 -08:00
A
6589fd1f2f
refactor: extract helpers from performAutoUpdate in update-check.ts (#881)
Break down the 70-line performAutoUpdate function (depth-4 nesting, mixed
concerns) into focused helpers:

- shellQuote: reusable shell-quoting utility
- printUpdateBanner: boxed update notification formatting
- reExecWithArgs: binary re-exec with exit code forwarding
- performAutoUpdate: clean 22-line orchestrator

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 05:53:33 -08:00
A
a0d1d1b40b
fix: replace jargon "Remediation" with plain "How to fix" in error messages (#925)
Replace technical "Remediation steps:" with "How to fix:" and
"Remediation: Check <url>" with "Check your dashboard: <url>" across
14 cloud providers for clearer error guidance. Add actionable error
messages to Atlantic.Net create_server and SSH key registration failures.

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 05:52:31 -08:00
A
84681fe092
refactor: replace hand-rolled API wrapper and polling loop with shared helpers (#927)
- hostkey: replace 22-line raw curl wrapper with generic_cloud_api
  delegation (adds retry logic, standardizes METHOD ENDPOINT [BODY] signature)
- exoscale: replace 30-line hand-rolled polling loop with
  generic_wait_for_instance via thin CLI wrapper

Agent: complexity-hunter

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 05:48:07 -08:00
A
ebc5a6cc2f
test: add 84 tests for interactive input validation helpers in shared/common.sh (#880)
Cover get_resource_name, get_validated_server_name, get_model_id_interactive,
interactive_pick, _display_and_select, and show_server_name_requirements --
all previously untested functions used by every agent/cloud script.

Tests exercise env-var bypass paths (critical for CI/non-interactive use),
validation rejection of injection attempts, boundary conditions, and menu
rendering output.

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 05:47:30 -08:00
A
317f2a7704
feat: Add codesandbox/continue (#878)
Agent: gap-filler-4

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 05:47:24 -08:00
A
0905994d8a
feat: Add Amazon Q CLI on local machine (#887)
Implemented local/amazonq.sh to run Amazon Q CLI directly on the user's local
machine. Uses the standard local provider pattern with OpenRouter API key
injection via OPENAI_API_KEY and OPENAI_BASE_URL environment variables.

Agent: gap-filler

Co-authored-by: B (Discovery Team) <6723574+louisgv@users.noreply.github.com>
2026-02-13 05:47:17 -08:00
A
6c762494e2
test: add Atlantic.Net and CodeSandbox provider pattern tests (268 tests) (#928)
Validates provider-specific patterns for the two most recently added clouds:
- Atlantic.Net: HMAC-SHA256 signing, query-param API, SSH delegation, dual-credential auth
- CodeSandbox: Node.js SDK exec, sandbox ID validation, env-var-based injection security
- Cross-provider contrast tests verifying SSH vs SDK architecture divergence
- Manifest consistency checks for both providers

Agent: test-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-13 05:47:01 -08:00
L
069f0ecb7a
fix: Add workflow_dispatch to trigger server's valid reasons (#931)
The simplified security workflow passes github.event_name directly as
the reason parameter, which includes workflow_dispatch for manual
triggers. The trigger server was rejecting it with a 400 error.

Co-authored-by: Security Reviewer <security-reviewer@spawn.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 05:39:26 -08:00
L
890b99dbfd
feat: Add pre-cycle stale branch cleanup to security.sh (#930)
* refactor: Simplify security workflow to match discovery/refactor pattern

Move mode-detection logic from the GitHub Actions workflow into
security.sh where it belongs. The workflow now passes github.event_name
directly as the reason parameter (like discovery.yml and refactor.yml),
and security.sh uses `gh issue view` to check labels when reason=issues.

- Remove 25-line if/elif/else reason-mapping block from security.yml
- Remove workflow_dispatch mode input (server-side handles it)
- Add `if:` label guard for issues (safe-to-work + team-building/security)
- Add `labeled` to issue trigger types
- Set cancel-in-progress: false (prevents killing long review_all runs)
- Bump cron to */5
- Handle schedule/workflow_dispatch → review_all in security.sh
- Keep backwards compat for direct team_building/triage reasons

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

* feat: Add pre-cycle stale branch cleanup to security.sh

Clean up merged and stale security-related branches (team-building/*,
review-pr-*) and leftover worktrees before each cycle starts. Follows
the same pattern as qa-cycle.sh.

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

* feat: Add pre-cycle stale branch cleanup to discovery.sh and refactor.sh

Each agent script now cleans up its own merged branches before starting:
- discovery.sh: add-*, impl-*, gap-filler-* branches
- refactor.sh: fix/*, refactor/*, test/*, ux/* branches
- (security.sh already added in prior commit)
- (qa-cycle.sh already had this)

Replaces the "branch pruning handled by security team" comments with
actual cleanup, following the qa-cycle.sh pattern.

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

---------

Co-authored-by: Security Reviewer <security-reviewer@spawn.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 05:34:09 -08:00
L
f69f95c7c7
refactor: Simplify security workflow to match discovery/refactor pattern (#929)
Move mode-detection logic from the GitHub Actions workflow into
security.sh where it belongs. The workflow now passes github.event_name
directly as the reason parameter (like discovery.yml and refactor.yml),
and security.sh uses `gh issue view` to check labels when reason=issues.

- Remove 25-line if/elif/else reason-mapping block from security.yml
- Remove workflow_dispatch mode input (server-side handles it)
- Add `if:` label guard for issues (safe-to-work + team-building/security)
- Add `labeled` to issue trigger types
- Set cancel-in-progress: false (prevents killing long review_all runs)
- Bump cron to */5
- Handle schedule/workflow_dispatch → review_all in security.sh
- Keep backwards compat for direct team_building/triage reasons

Co-authored-by: Security Reviewer <security-reviewer@spawn.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 05:26:21 -08:00
A
00f8913f20
fix: show credential readiness in spawn clouds and relative timestamps in spawn list (#910)
Two UX improvements:

1. `spawn clouds` now shows a green "ready" indicator next to clouds where
   credentials are already configured in the environment, making it immediately
   clear which providers the user can use without additional setup.

2. `spawn list` now shows relative timestamps ("5 min ago", "yesterday",
   "3d ago") instead of absolute dates, giving immediate temporal context.

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 05:20:04 -08:00
A
ad6f12f6c5
fix: improve Atlantic.Net error messages with actionable troubleshooting (#913)
Replace raw API JSON dumps with extracted error messages and actionable
troubleshooting steps for server creation and SSH key registration failures.

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 05:19:59 -08:00
A
3a3826cff6
fix: use --class instead of --cpu/--memory/--disk for Daytona sandboxes (#920)
Daytona now rejects explicit resource flags (--cpu, --memory, --disk)
when using snapshots. Switch to --class (default: small) which works
with all sandbox configurations. Explicit resource env vars are still
supported but auto-retry with --class on snapshot conflict.

Fixes #800

Agent: ux-engineer

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-13 05:19:54 -08:00