Commit graph

187 commits

Author SHA1 Message Date
A
ff13a5fda9
fix: suggest cross-kind fuzzy matches when args may be swapped with typos (#510)
When a user types `spawn htzner claude` (cloud name typo as first arg),
checkEntity now detects that "htzner" is close to cloud "hetzner" and
suggests the user may have swapped agent and cloud arguments. Previously,
this only worked for exact cloud names; typos would produce a generic
"Unknown agent" error with no helpful suggestion.

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-11 12:47:53 -08:00
A
9458836ca1
refactor: extract helpers from showDryRunPreview and cmdUpdate to reduce complexity (#509)
- showDryRunPreview: extract printDryRunSection, buildAgentLines, buildCloudLines
  helpers to eliminate repeated header/body/blank-line pattern across 5 sections
- cmdUpdate: extract fetchRemoteVersion and performUpdate helpers to flatten
  nested try/catch, deduplicate install command string into INSTALL_CMD constant

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-11 12:34:51 -08:00
A
138fe91333
test: add 25 tests for cloud/agent Quick start and Not-yet-available display (#507)
Cover untested code paths in cmdCloudInfo and cmdAgentInfo:
- printCloudQuickStart with multi-auth env vars (e.g., UPCLOUD_USERNAME + UPCLOUD_PASSWORD)
- printCloudQuickStart URL hint only shown on first auth var (not repeated)
- printCloudQuickStart with OAuth auth (no parseable env vars)
- printCloudQuickStart with "none" auth (no extra export lines)
- printCloudQuickStart when no implemented agents (no example command)
- printAgentList "Not yet available" shown when missingAgents <= 5
- printAgentList "Not yet available" hidden when missingAgents > 5
- printAgentList boundary at exactly 5 missing agents
- cmdAgentInfo Quick start with multi-auth cloud as first available
- cmdAgentInfo Quick start with "none" auth cloud
- cmdAgentInfo no Quick start when no clouds implemented

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-11 12:28:43 -08:00
A
c7a3532825
refactor: extract helpers from cmdList and showInfoOrError to reduce complexity (#506)
cmdList (88 -> 28 lines): Extract suggestFilterCorrection, showEmptyListMessage,
and showListFooter as focused helpers.

showInfoOrError (44 -> 15 lines): Extract showUnknownCommandError for the
fuzzy-match suggestion display logic.

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-11 12:15:11 -08:00
A
dd2e79ed9f
test: add 47 tests for cmdList filter suggestions and cmdMatrix view modes (#505)
Cover the previously untested cmdList fuzzy suggestion path (when filters
don't match, the CLI loads the manifest and suggests corrections via
resolveAgentKey/resolveCloudKey/findClosestKeyByNameOrKey) and cmdMatrix
compact vs grid view selection based on terminal width.

Tests added:
- cmdList agent/cloud filter typo correction suggestions (7 tests)
- cmdList manifest-unavailable graceful fallback (1 test)
- cmdList empty history edge cases (2 tests)
- cmdList prompt display and truncation in output (5 tests)
- cmdList rerun hint with/without prompt (2 tests)
- cmdMatrix grid view rendering (2 tests)
- cmdMatrix compact view rendering with narrow terminal (4 tests)
- cmdMatrix total count and launch hints (3 tests)
- calculateColumnWidth helper (7 tests)
- getMissingClouds helper (5 tests)
- getImplementedClouds helper (5 tests)
- getTerminalWidth helper (3 tests)

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-11 12:09:30 -08:00
A
984a4371ad
fix: add ENVIRONMENT VARIABLES section to spawn help text (#504)
Users had no way to discover SPAWN_HOME, SPAWN_DEBUG, or SPAWN_UNICODE
env vars without reading source code. The help text now documents all
SPAWN_* environment variables in a dedicated section between
TROUBLESHOOTING and MORE INFO.

Also bumps CLI version to 0.2.50.

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-11 12:08:32 -08:00
A
e620e47c7e
test: add 40 tests for agent config setup and verification functions (#503)
Covers previously untested bash functions in shared/common.sh:
- verify_agent_installed: command existence, version check, error messages
- upload_config_file: temp file creation, content preservation, callbacks
- setup_claude_code_config: settings.json, .claude.json, json_escape security
- setup_openclaw_config: openclaw.json, gateway token, model ID
- setup_continue_config: config.json, OpenRouter model config

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-11 11:57:20 -08:00
A
f244a4278e
fix: add fuzzy suggestions and filter context to spawn list (#501)
When `spawn list -a/-c` filter returns no results, suggest corrections
using the same fuzzy matching used elsewhere in the CLI. Also show total
history count so users know other entries exist.

When filter matches results, show "Showing X of Y spawns" with a
"Clear filter" hint instead of the default footer.

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-11 11:53:44 -08:00
A
9e4ea1e474
test: add 31 tests for cmdList prompt display and suggestCloudsForPrompt (#500)
Cover untested prompt-related display paths in commands.ts and index.ts:
- cmdList prompt preview truncation at 40 chars in record rows
- cmdList rerun hint truncation at 30 chars for long prompts
- cmdList records with/without prompts showing correct output
- suggestCloudsForPrompt cloud suggestions with overflow (>5 limit)
- suggestCloudsForPrompt error messages and agent resolution paths

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-11 11:25:32 -08:00
A
34985e01f6
fix: add timeout to script downloads and validate list filter flags (#499)
- Add FETCH_TIMEOUT (10s) to script download fetches in
  downloadScriptWithFallback, preventing indefinite hangs when the
  server is unresponsive
- Show actionable error when `spawn list -a` or `spawn list -c` is
  used without a value, instead of silently showing unfiltered results
- Bump CLI version to 0.2.48

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-11 11:23:57 -08:00
A
28cb923e53
refactor: remove dead commands-logic.ts and unused errorMessage (#497)
commands-logic.ts (140 lines) duplicated functions already in commands.ts
and was never imported by the application. Its test file (275 lines) tested
these unused duplicates. The errorMessage function in commands.ts was defined
but never called. Total: 420 lines of dead code removed.

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-11 11:03:17 -08:00
A
19948d3ad5
test: add 55 tests for checkEntity validation function (#496)
checkEntity is a critical function in the run pipeline (commands.ts:182-206)
that validates user-provided agent/cloud names. It had zero test coverage
despite complex branching logic for wrong-type detection, fuzzy matching,
and error messaging.

Tests cover: valid entities, wrong-type detection (cloud-as-agent and
agent-as-cloud), non-existent entities, fuzzy match typos, empty/boundary
inputs, minimal manifests, kind parameter consistency, bulk validation
of all manifest entries, and overlapping key patterns.

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-11 11:01:52 -08:00
A
fa516bad89
fix: improve spawn list and clouds UX (#491)
- Show prompt preview in `spawn list` history for prompted runs
- Include prompt in rerun hint when last spawn used --prompt
- Show auth requirements in `spawn clouds` listing
- Change swap detection from warn to info (auto-correcting, not a warning)
- Update `spawn clouds` help text: "for setup instructions" instead of "for details"

Bump CLI version to 0.2.46.

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-11 10:34:28 -08:00
A
bc89a2821b
test: add 43 tests for list display logic (formatTimestamp, parseListFilters, cmdList) (#489)
Cover the history list feature display layer added in PRs #486-#488:
- formatTimestamp: valid ISO, invalid dates, edge cases (epoch, far future)
- parseListFilters: -a/-c flag extraction, missing values, duplicates, ordering
- cmdList output: table headers, rerun hint, count summary, filter messages,
  newest-first ordering, singular/plural, corrupted history resilience

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-11 10:29:50 -08:00
A
6c0e9116a5
fix: show spawn history newest-first with rerun hint (#488)
`spawn list` now shows records in reverse chronological order (newest
first), matching the convention of git log, shell history, and docker ps.
Adds a "Rerun last" hint showing the command to repeat the most recent spawn.

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-11 10:11:50 -08:00
A
783cba86d5
test: add 34 tests for history module (loadHistory, saveSpawnRecord, filterHistory) (#487)
The history.ts module had zero test coverage. This adds comprehensive tests for:
- getSpawnDir: SPAWN_HOME env var and ~/.spawn fallback
- getHistoryPath: correct path composition
- loadHistory: missing file, valid data, invalid JSON, non-array JSON, empty file
- saveSpawnRecord: directory creation, append, prompt field, pretty JSON, corruption recovery
- filterHistory: agent/cloud/combined filters, case-insensitivity, no-match 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-11 10:10:12 -08:00
A
a932bc3734
feat: store spawn history locally and repurpose spawn list (#486)
- Rename `spawn list` -> `spawn matrix` (alias: m) for the availability matrix
- New `spawn list` / `spawn ls` shows previously provisioned agents from ~/.spawn/history.json
- Support filtering: `spawn list -a <agent>`, `spawn list -c <cloud>`
- Auto-record each spawn with agent, cloud, timestamp, and prompt
- History path respects SPAWN_HOME env var for testability
- Bump CLI version to 0.2.44

Fixes #483

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-11 10:01:48 -08:00
A
c65b11abbe
test: add 24 tests for missing-cloud error paths and suggestCloudsForPrompt (#485)
Cover untested error paths in index.ts when agent/cloud arguments are missing:
- suggestCloudsForPrompt: --prompt with agent but no cloud shows cloud suggestions
- handleNoCommand: --dry-run and --prompt without any args
- handleDefaultCommand: --dry-run with agent but no cloud
- --prompt-file with agent but no cloud
- Combined flag edge cases

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-11 09:43:31 -08:00
A
7cb37ba88d
fix: show both agent and cloud errors at once instead of one at a time (#484)
Previously, `spawn badagent badcloud` would only show the agent error,
requiring users to fix it and re-run before discovering the cloud was
also wrong. Now both errors are shown together so users can fix
everything in one round trip.

Refactors validateEntity into checkEntity (returns bool) + validateEntity
(exits). cmdRun uses checkEntity for batch validation.

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-11 09:40:43 -08:00
A
285bc4c5c2
test: add 41 tests for dry-run preview feature (#482)
The showDryRunPreview function (added in PR #479) had only 1 basic
subprocess test. These tests cover all branches: agent info display
(name, description, install, launch), cloud info (name, description,
defaults), script URL format, env var display with OPENROUTER_API_KEY
redaction, prompt truncation at 100 chars, section ordering, and
verification that no script download occurs in dry-run mode.

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-11 09:13:14 -08:00
A
7fa9325683
refactor: deduplicate resolveAgentKey/resolveCloudKey into shared resolveEntityKey (#481)
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-11 09:11:41 -08:00
A
5851a9ce7b
fix: show error when --dry-run used without agent and cloud args (#480)
`spawn --dry-run` silently entered interactive mode, ignoring the flag.
Now it shows an actionable error like `--prompt` does. Also adds
`--dry-run` to the README commands table.

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-11 09:09:57 -08:00
A
ca510881f1
feat: add --dry-run flag to preview provisioning details (#478)
Allows users to see what would be provisioned (agent, cloud, server specs,
script URL, env vars) without actually spinning up a server.

Fixes #474

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>
2026-02-11 08:56:59 -08:00
A
d41706a377
test: add 39 tests for untested shared/common.sh helper functions (#477)
Cover _load_json_config_fields, _save_json_config, extract_ssh_key_ids,
_generate_csrf_state, and interactive_pick -- all had zero test coverage
despite being used by every cloud provider script.

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-11 08:49:18 -08:00
A
2ed89d5b52
refactor: reduce complexity in ensure_multi_credentials and handleDefaultCommand (#476)
Extract 4 helper functions from ensure_multi_credentials() (94 lines, CC=14
-> 48 lines, CC=4): _multi_creds_all_env_set, _multi_creds_load_config,
_multi_creds_prompt, _multi_creds_validate.

Flatten handleDefaultCommand() (39 lines, CC=7 -> 15 lines, CC=3) by
extracting suggestCloudsForPrompt() and using early returns to eliminate
nested if/else blocks.

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-11 08:45:47 -08:00
A
cbee5a8f15
fix: add -f shorthand for --prompt-file and improve CLI UX (#475)
- Add -f as short form for --prompt-file (parity with -p for --prompt)
- Show runnable command in "Did you mean" suggestions
- Show agent install command in agent info page
- Add agent count to "spawn agents" header (consistent with "spawn clouds")
- Update help text and examples to document -f flag
- Bump CLI version to 0.2.40

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-11 08:44:43 -08:00
A
1f6133dc47
test: fix 5 failing tests, add 31 cmdHelp content tests, remove stale skips (#472)
Fix download error tests that checked wrong mock target (consoleMocks.error
vs mockLogError) and expected outdated "Troubleshooting" text instead of
"How to fix". Remove 11 stale describe.skip blocks from commands.test.ts
that have been superseded by dedicated test files using mock.module().
Add cmd-help-content.test.ts with 31 tests verifying help output includes
all subcommands, flags, sections, and key content.

Before: 4579 pass, 5 fail, 11 skip
After:  4615 pass, 0 fail, 0 skip

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-11 08:25:15 -08:00
A
6e789f8cbf
fix: improve error message consistency and clarity across CLI (#470)
- Style all error messages with colored output (pc.red for errors, pc.cyan for commands)
- Fix inconsistent OpenRouter key URL (openrouter.ai/keys -> openrouter.ai/settings/keys)
- Improve exit code 130 guidance to suggest cloud dashboard instead of unhelpful spawn command
- Add actionable recovery hints to token/credential validation failures
- Remove redundant "Invalid input" message from validated_read (validator already shows error)
- Fix nested color codes in cmdUpdate failure spinner
- Clean up version display when binary path is unavailable

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-11 08:17:14 -08:00
A
f0dc891a51
refactor: deduplicate agent/cloud validation into generic validateEntity (#469)
Merged four nearly-identical functions (validateAgent, validateCloud,
validateAndGetAgent, validateAndGetCloud) into two generic ones
(validateEntity, validateAndGetEntity), eliminating ~20 lines of
duplicated validation, fuzzy matching, and swap-detection logic.

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-11 08:14:19 -08:00
A
e38a75ea17
test: add 42 tests for download fallback pipeline and failure reporting (#467)
Cover the real code paths through cmdRun for script downloading, fallback
to GitHub raw URLs, error reporting on 404/500/network errors, script
content validation, and exit code guidance. Tests exercise the actual
exported functions (getScriptFailureGuidance, getStatusDescription,
getErrorMessage) rather than reimplemented copies.

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-11 07:47:05 -08:00
A
d9037fad32
fix: improve error messages and UX consistency across CLI and shell scripts (#466)
- Clarify download error messages: distinguish HTTP errors from network errors
  with specific status codes in the message
- Add actionable next steps to OAuth timeout: re-run command or set key manually
- Standardize error help labels to "How to fix:" across CLI and shell scripts
  (was inconsistently "What to do:", "Troubleshooting:", or missing)
- Add API method/endpoint context to retry failure messages so users know
  which API call failed
- Make verify_agent_installed error cases mutually exclusive: first for
  PATH/installation issues, second for runtime/dependency issues

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-11 07:46:56 -08:00
A
f95d2e4a97
test: add 114 security regression tests for upload_file across all clouds (#465)
Static analysis tests that verify every cloud's upload_file() function
uses safe patterns to prevent command injection. Tests cover:
- Path validation (single-quote, $, backtick rejection) or printf '%q' escaping
- Base64 content encoding before shell embedding
- printf '%s' for safe output (no echo with variable expansion)
- No eval on user-controlled input
- PR #453 regression tests for fly, northflank, daytona, e2b, koyeb
- Classification of all 30+ clouds into safe categories (ssh/scp/cp/exec-based)

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-11 07:26:28 -08:00
A
9d50d8101b
fix: improve user-facing messages and error text across CLI and shell scripts (#464)
- Cancel handling: use p.outro instead of red error text for user cancellation
- Exit code 130: warn that server may still be running instead of falsely claiming it isn't
- Download errors: hide internal URLs, show user-friendly "could not be found" message
- Compact list legend: use "not yet available" consistently instead of jargon "missing"
- Update messages: say "Run your spawn command again" instead of vague "Restart your command"
- API token errors: show friendly "special characters" message instead of listing forbidden chars
- OAuth fallback: explain this is normal on remote/SSH/headless environments
- Interactive picker: show what was entered and valid range on invalid selection
- Bump CLI version to 0.2.39

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-11 07:26:00 -08:00
A
1316f9f609
fix: show runtime/platform in spawn version, clarify compact list legend (#456)
- `spawn version` now shows runtime (bun/node), version, platform,
  and architecture for easier bug reporting and diagnostics
- Compact list legend changed from confusing "N/N" to descriptive
  "green = all clouds  yellow = some missing"
- Bump CLI to v0.2.38

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-11 06:55:24 -08:00
A
b4580b4f8f
test: fix 6 broken tests and add coverage for exit code branches (#455)
The getScriptFailureGuidance function was updated (PRs #449, #450) to
add dedicated handlers for exit codes 130, 137, 255, and 2, but the
existing tests still expected these to fall through to the default case.

Fixed 4 broken assertions in script-failure-guidance.test.ts and 2 in
exec-script-errors.test.ts. Added 16 new tests covering the specific
guidance for each newly handled exit code (130=Ctrl+C, 137=OOM/killed,
255=SSH failure, 2=shell syntax error).

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-11 06:55:00 -08:00
A
55fd4022e8
fix: improve error messages with actionable guidance for common failures (#452)
- Add signal exit code handling (130/Ctrl+C, 137/killed, 255/SSH failure, 2/syntax error)
- Replace vague "Cloud API retry logic exhausted" with attempt count and retry advice
- Add network troubleshooting hint to API network error after retries
- Clarify OAuth fallback prompt: explain why OAuth failed and what happens next
- Consolidate auth cancellation message with three clear recovery options

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-11 06:26:19 -08:00
A
f2c9af0d79
test: add 35 tests for getScriptFailureGuidance() exit code branches (#451)
Cover all exit code paths in getScriptFailureGuidance() which had zero
direct test coverage despite being recently modified (PRs #450, #449):
- Exit code 127: command not found guidance with tool listing
- Exit code 126: permission denied message
- Exit code 1: credential/API/provisioning failure hints
- Default case: generic troubleshooting for unknown exit codes
- null exit code: falls through to default
- Edge cases: 0, negative, large codes, signal codes (130, 137)
- Structure: return type validation, non-empty arrays, distinct output

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-11 06:25:54 -08:00
A
79cf25d210
fix: improve 404 error message in reportDownloadFailure() (#450)
The old message "This agent + cloud combination doesn't exist yet" was
misleading because by the time reportDownloadFailure runs, the agent/cloud
combination has already been validated in the manifest. A 404 means the
script file is missing from the server, not that the combination is invalid.

New message explains the script couldn't be found, suggests checking the
matrix, retrying, or reporting the issue. Also adds a hint about temporary
server issues for 500-level errors.

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-11 05:58:27 -08:00
A
4b76b3422c
refactor: reduce complexity in execScript and netcup pick functions (#449)
Extract error handling from execScript() into dedicated helpers
(reportDownloadError, reportScriptFailure, getScriptFailureGuidance),
reducing the function from 52 to 15 lines and making error guidance
directly testable.

Replace duplicated _pick_vps_product() and _pick_datacenter() in
netcup/lib/common.sh with calls to shared interactive_pick(),
eliminating ~60 lines of copy-pasted selection logic.

Net reduction: 42 lines (-98/+56).

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-11 05:56:48 -08:00
A
02ecd4123b
test: add 15 tests for cmdInteractive cancel and selection paths (#448)
cmdInteractive is the primary user entry point (bare `spawn` command) with
zero test coverage. Adds tests for: user cancels agent/cloud selection via
Ctrl+C, agent with no implemented clouds, happy path through selection to
script execution, intro/outro messaging, and run-directly hint.

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-11 05:55:27 -08:00
A
e9e5f1bfea
fix: improve error messages with actionable guidance (#447)
- validatePrompt max-length error now suggests --prompt-file alternative
- validateScriptContent shebang error explains likely download issue
- Compact list view now shows color legend (green=all, yellow=partial)
- Exit code 1 gets specific guidance (credentials, API, provisioning)
- cmdUpdate network error shows current version for context
- Bump CLI version to 0.2.37

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-11 05:20:31 -08:00
A
305a782fea
test: add 496 manifest type contract validation tests (#446)
Validates that every field in manifest.json conforms to TypeScript type
definitions (AgentDef, CloudDef) at runtime. Catches data quality issues
that truthiness-only checks miss:

- Required fields are correct types (string, not number/boolean/array)
- Agent env values are all strings with valid env var name keys
- Agent env references OPENROUTER_API_KEY (mandatory per CLAUDE.md)
- Optional fields (pre_launch, deps, config_files, interactive_prompts,
  dotenv, notes, defaults) have correct types when present
- dotenv has path (string) and values (Record<string, string>)
- interactive_prompts entries have prompt+default string fields
- config_files values are objects with path-like keys
- deps is an array of strings
- Cloud type values are lowercase
- Env var interpolation ${...} references valid env var names
- Launch commands don't contain dangerous shell metacharacters
- Display names are unique, agent keys don't collide with cloud keys
- Matrix covers all cloud/agent combinations exhaustively

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-11 05:20:13 -08:00
A
2bc95fdf15
test: add tests for validateImplementation branching (0, 1-3, >3 clouds) (#442)
Cover the untested code paths in validateImplementation (commands.ts
lines 233-256) that show different error messages based on how many
alternative clouds are available for an agent:
- 0 clouds: "no implemented cloud providers" + suggest "spawn list"
- 1-3 clouds: show all available clouds as examples
- >3 clouds: show first 3 examples + "Run spawn X to see all N options"
- Boundary: exactly 3 vs 4 clouds threshold
- Error message formatting (display names, singular/plural)

24 new tests, all passing (3865 total).

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-11 04:48:52 -08:00
A
10a40ca574
fix: add log_step for progress messages, fix misleading prompt error (#440)
- Add log_step() function (cyan) for status/progress messages
- Convert misused log_warn calls to log_step in shared/common.sh
  (14 instances: SSH key gen, agent verification, waiting, configuring)
- Convert representative cloud scripts: hetzner, digitalocean, sprite
- Fix misleading validatePrompt error that suggested --prompt-file as a
  workaround when it has the same validation

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-11 04:28:17 -08:00
A
5722e13851
test: add 21 tests for execScript bash execution error handling (#433)
Cover the critical untested error paths in commands.ts when spawn scripts
fail with specific exit codes: 127 (command not found), 126 (permission
denied), 130 (Ctrl+C), and generic failures with troubleshooting advice.

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-11 04:24:09 -08:00
A
3e34133f54
test: fix non-TTY test expectations to match actual CLI behavior (#432)
Tests expected help output (USAGE/EXAMPLES) in non-TTY mode, but the CLI
actually shows a "No interactive terminal detected" hint with exit code 1.

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-11 04:09:53 -08:00
A
a1509ac8b3
fix: improve CLI error messages and cloud auth display (#431)
- Show URL hint only on the first auth var in multi-auth cloud quick-start
  (eliminates duplicate URLs for clouds like Contabo with 4 auth vars)
- Make script failure error messages exit-code-aware: show targeted guidance
  for command-not-found (127) and permission-denied (126) exit codes
- Consolidate generic failure hints into "Common causes" section

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-11 04:07:45 -08:00
A
81f1630424
test: Add 65 tests for untested shared/common.sh functions (#428)
Cover critical bash functions that had zero test coverage:
- validate_oauth_port: port validation boundary cases and injection
- generate_env_config: shell export generation and value escaping
- calculate_retry_backoff: exponential backoff with jitter range
- _update_retry_interval: indirect variable update via printf -v
- _parse_api_response: HTTP response code extraction
- _api_handle_transient_http_error: retry exhaustion messaging
- get_cloud_init_userdata: cloud-init YAML content validation

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-11 03:45:13 -08:00
A
5c4f830fea
fix: improve credential guidance in error messages and quick-start hints (#427)
- Show cloud provider URL alongside credential env vars in quick-start
  sections (both `spawn <agent>` and `spawn <cloud>` info views)
- Restructure script failure errors: separate credential issues from
  other causes, inline the `spawn <cloud>` hint next to cloud credentials
- Replace "Check cloud-specific READMEs" with actionable `spawn <cloud>`
  in help troubleshooting section
- Show concise 4-line guidance instead of full help dump when spawn is
  run without a TTY (e.g. piped or in CI)
- Add `spawn <agent> <cloud>` as primary action in `spawn list` footer

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-11 03:42:55 -08:00
A
bb4f0c29df
fix: improve credential guidance in error messages and quick-start hints (#426)
- Add OPENROUTER_API_KEY as first item in script failure error (most common cause)
- Replace external GitHub README link with actionable `spawn <cloud>` command in error output
- Fix help text: auth section now correctly says `spawn <cloud>` instead of `spawn <agent> <cloud>`
- Add inline URL hint next to OPENROUTER_API_KEY in quick-start sections
- Add cloud name label next to cloud auth vars in agent info quick-start

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-11 03:21:15 -08:00