Tests three previously untested logic paths in commands.ts and manifest.ts:
- detectAndFixSwappedArgs: 8 tests covering swap detection, no-swap cases,
and swap with missing implementations
- resolveAndLog: 6 tests for case-insensitive key and display name resolution
- isValidManifest: 7 tests for manifest structure validation via loadManifest
- Prompt handling with swapped args: 2 tests for prompt+swap interaction
Agent: test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Add direct unit tests for parseAuthEnvVars, getImplementedAgents,
getMissingClouds, getErrorMessage, getStatusDescription,
calculateColumnWidth, getTerminalWidth, and getImplementedClouds.
These functions were either completely untested or only tested via
inline replicas rather than the actual exports. parseAuthEnvVars is
particularly important as it parses auth config strings used in
user-facing quick-start instructions.
Agent: test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Add Netcup as a new cloud provider - a German budget VPS provider
with REST API support starting at €3.86/mo.
Changes:
- Created netcup/lib/common.sh with session-based REST API primitives
- Added Netcup to manifest.json clouds section
- Added 15 matrix entries (claude/aider/goose implemented, rest missing)
- Implemented netcup/claude.sh, netcup/aider.sh, netcup/goose.sh
- Created netcup/README.md with usage documentation
Netcup uses session-based authentication requiring:
- NETCUP_CUSTOMER_NUMBER
- NETCUP_API_KEY
- NETCUP_API_PASSWORD
API launched Oct 2025, replaces legacy SOAP service (deprecated May 2026).
Agent: cloud-scout-2
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Tests expected old error wording after PR #387 changed the messages.
Agent: team-lead
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract resolveAndLog() from cmdRun to handle argument resolution
- Extract detectAndFixSwappedArgs() from cmdRun for swap detection
- Extract printInfoHeader() shared by cmdAgentInfo and cmdCloudInfo
- Extract groupByType() used by cmdAgentInfo, cmdCloudInfo, cmdClouds
- Extract printGroupedList() for displaying grouped items with hints
All tests pass (3260/3260). No functional changes.
Agent: complexity-hunter
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
- Fix auto-update unicode symbols (checkmark/cross) that bypassed unicode
detection, causing garbled output in SSH sessions and dumb terminals
- Use log_info (green) instead of log_warn (yellow) for OAuth progress
messages, so normal authentication flow doesn't look like a warning
- Add install path to `spawn version` output for easier debugging when
multiple versions are installed
- Improve --prompt-file errors to distinguish file-not-found, permission
denied, and is-a-directory cases with actionable guidance
- Bump CLI version to 0.2.30
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Validates CLI helper functions (getImplementedClouds, parseAuthEnvVars,
resolveAgentKey, resolveCloudKey, calculateColumnWidth, fuzzy matching)
against the real manifest.json with all 21 clouds and 14 agents. Unlike
mock-based tests, these catch real-world issues like the local cloud's
auth: "none" pattern, multi-var auth strings, cloud type grouping, and
matrix key consistency. Includes dedicated tests for the new local cloud
provider (PR #383).
Agent: test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
- Fix cmdCloudInfo quick-start showing "none" as a command for local cloud
- Always show OPENROUTER_API_KEY in cloud quick-start (needed for all agents)
- Update local scripts to explicitly say "Appending environment variables to ~/.zshrc"
- Update local README with spawn CLI usage and "What It Does" section
- Add 3 tests for quick-start auth display (none auth, env var auth)
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
OVH: Extract _ovh_extract_public_ipv4() and _ovh_extract_status() from
wait_for_ovh_instance() to reduce inline Python and improve readability.
Latitude: Extract _latitude_extract_error(), _latitude_get_ssh_key_ids(),
and _latitude_build_server_body() from create_server() and
latitude_register_ssh_key(). Deduplicates error extraction logic used in
two places.
Agent: complexity-hunter
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Adds a "local" cloud provider that installs and runs agents directly on the
user's machine without any cloud provisioning. This is useful for local
development and testing.
- local/lib/common.sh: Cloud lib with local execution functions
- local/claude.sh: Claude Code agent script
- local/openclaw.sh: OpenClaw agent script
- local/nanoclaw.sh: NanoClaw agent script
- manifest.json: Added local cloud + matrix entries
- test/: Updated record.sh and mock.sh for local cloud support
Fixes#378
Agent: issue-fixer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a "local" cloud provider that installs and runs agents directly on the
user's machine without any cloud provisioning. This is useful for local
development and testing.
- local/lib/common.sh: Cloud lib with local execution functions
- local/claude.sh: Claude Code agent script
- local/openclaw.sh: OpenClaw agent script
- local/nanoclaw.sh: NanoClaw agent script
- manifest.json: Added local cloud + matrix entries
- test/: Updated record.sh and mock.sh for local cloud support
Fixes#378
Agent: issue-fixer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The showInfoOrError function loaded the manifest without a spinner,
causing no visual feedback on cold cache. Now uses loadManifestWithSpinner
so users see a loading indicator while the manifest fetches.
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace vulnerable heredoc patterns across 27 continue.sh scripts with
setup_continue_config() helper that uses json_escape() + upload_config_file()
to safely handle API keys containing special characters like quotes or braces.
Also fix _save_token_to_config() in shared/common.sh which had the same
unescaped heredoc vulnerability for local token storage.
Relates to #104
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>
Show actionable auth setup commands in `spawn <cloud>` and `spawn <agent>`
output so users can get started immediately without reading README docs.
For clouds with env var auth (e.g. Hetzner), shows exact export commands:
Quick start:
export HCLOUD_TOKEN=your-hcloud-token-here
spawn claude hetzner
For agents, shows OpenRouter API key and example launch command:
Quick start:
export OPENROUTER_API_KEY=sk-or-v1-...
spawn claude sprite
Also adds parseAuthEnvVars() utility with 6 tests and 8 quick-start
integration tests.
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>
Export and test 7 previously-unexported utility functions from commands.ts:
getTerminalWidth, getMissingClouds, getImplementedAgents, getImplementedClouds,
getErrorMessage, calculateColumnWidth, getStatusDescription.
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>
Cover previously untested code paths:
- cmdCloudInfo "Not yet available" missing agents text (<=5 threshold)
- cmdCloudInfo setup URL and auth field display
- cmdCloudInfo agent count (N of M) format
- cmdAgentInfo URL and notes display
- cmdAgentInfo cloud count and type grouping
Agent: test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Split the two longest functions in the codebase into focused sub-functions:
Contabo create_server (108 -> 52 lines):
- _contabo_get_ssh_secret_ids: fetch SSH secret IDs from API
- _contabo_build_instance_body: construct API request JSON
- _contabo_wait_for_instance: poll until instance is running
Genesis Cloud create_server (91 -> 42 lines):
- _genesis_get_ssh_key_ids: fetch SSH key IDs from API
- _genesis_build_instance_body: construct API request JSON
- _genesis_wait_for_instance: poll until instance is active
No behavioral changes - pure restructuring for readability.
Agent: complexity-hunter
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
- Manifest load failure now shows specific troubleshooting steps including
cache directory path for manual cleanup
- Non-TTY mode explains why interactive picker is unavailable and suggests
the direct launch syntax instead of silently falling through to help
- `spawn update` network failure now includes recovery steps and manual
update command
Agent: ux-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement contabo/nanoclaw.sh with WhatsApp-based AI agent support.
- Uses Contabo VPS provisioning via OAuth API
- Installs tsx, clones nanoclaw repo, builds with npm
- Configures OpenRouter API credentials via env vars and .env file
- Launches interactive session with WhatsApp QR code auth
Agent: gap-filler-contabo-1
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>