Commit graph

40 commits

Author SHA1 Message Date
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
A
0181b73506
fix: warn on extra args and detect mismatched agent/cloud types (#422)
- Warn when extra positional arguments are silently ignored (e.g. "spawn
  claude sprite hetzner" now shows that "hetzner" was ignored)
- Detect when user passes two agents (e.g. "spawn claude aider") and
  explain that the second arg should be a cloud, not an agent
- Detect when user passes two clouds (e.g. "spawn hetzner sprite") and
  explain that the first arg should be an agent, not a cloud
- Add tests for both new behaviors

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 02:58:34 -08:00
A
fa11fed516
fix: improve UX with version hints, clearer non-TTY message, and retry bug fix (#417)
- Add "spawn update" hint to version output so users know how to update
- Simplify non-interactive TTY message (less alarming, more actionable)
- Fix _api_handle_transient_http_error passing wrong first arg to
  _api_should_retry_on_error (was "http_429" instead of attempt number)
- Sync README matrix count (444 -> 445)

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 02:33:38 -08:00
A
83440dd6f3
fix: improve fuzzy matching to check display names for better typo suggestions (#414)
Fuzzy matching now checks both keys (e.g. "claude") and display names
(e.g. "Claude Code") when suggesting corrections for typos. Previously,
typing "spawn claud" or "spawn Hetzne" would only fuzzy-match against
keys, missing close display name matches. The new findClosestKeyByNameOrKey
function picks the best match across both, and suggestions now always
show the display name for clarity (e.g. "Did you mean claude (Claude Code)?").

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 02:06:52 -08:00
A
7cf9d168d9
fix: Improve CLI UX with better error messages and consistent log levels (#387)
- 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>
2026-02-11 01:16:00 -08:00
A
18242a6741
fix: Show loading spinner for single-arg commands (spawn <agent>, spawn <cloud>) (#375)
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>
2026-02-11 00:32:25 -08:00
A
9fd35a77b7
feat: Add quick-start section to cloud and agent info views (#373)
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>
2026-02-11 00:13:15 -08:00
A
bb84cb073a
fix: Improve error messages with actionable troubleshooting guidance (#368)
- 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>
2026-02-10 23:45:20 -08:00
A
835ccc7522
fix: Improve CLI info pages with counts and type grouping (#364)
- Agent info (spawn <agent>) now shows "X of Y" cloud count and groups
  clouds by type (api, cli, sandbox) for easier scanning
- Cloud info (spawn <cloud>) now shows "X of Y" agent count, auth method,
  and lists missing agents when there are 5 or fewer
- Cloud listing (spawn clouds) groups providers by type with X/Y ratio
  counts instead of singular/plural text
- Remove unused TYPE_COLUMN_WIDTH constant
- Bump CLI version to 0.2.26

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-10 23:25:03 -08:00
A
adab8511f5
fix: Improve CLI info pages and error messages (#358)
- Show agent/cloud URLs in info pages (spawn <agent>, spawn <cloud>)
- Add setup instructions link to cloud info pages
- Suggest available clouds when --prompt is used without a cloud arg
- Fix help text alignment for spawn list

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-10 22:48:22 -08:00
A
9fc89d91f7
fix: Improve error messages and spinner feedback in CLI (#324)
- Spinner completion messages now show "done" state instead of repeating
  the in-progress message (e.g., "Loading manifest" instead of "Loading manifest...")
- Script failures show actionable troubleshooting (missing credentials,
  rate limits, dependencies) instead of generic "Script exited with code N"
- Ctrl+C (exit code 130) exits silently instead of showing an error
- Fuzzy matching for unknown agents/clouds now also searches display names,
  so "Hetzner" suggests "hetzner" even when the key doesn't fuzzy-match

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-10 19:00:56 -08:00
A
ab89ffb90d
fix: Improve compact list view clarity and help text formatting (#313)
- Rename "Missing" column to "Not available on" to avoid confusion
- Change "all clouds" to "-- all clouds supported" for full coverage agents
- Only show +/- grid legend in grid view (not compact view)
- Fix help text alignment for "spawn list" command

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-10 18:00:17 -08:00
A
832f3f8ec1
fix: Resolve display names and case-insensitive input in CLI (#306)
Users typing "spawn Claude" or "spawn Claude Code" now get resolved
to the correct key automatically instead of an "invalid characters"
error. Works for both agents and clouds in single-arg info and
two-arg run paths.

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-10 17:37:51 -08:00
A
e07d9ef5cd
fix: auto-correct swapped agent/cloud args and improve help text (#300)
- Auto-correct swapped arguments (e.g., `spawn sprite claude` now runs
  as `spawn claude sprite`) instead of just warning and exiting
- Document `ls` alias for `list` in help text
- Add SPAWN_NO_UPDATE_CHECK env var to troubleshooting section
- Bump version to 0.2.21

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-10 16:14:50 -08:00
A
e1c2df3b1b
fix: Use compact list view when matrix is too wide for terminal (#294)
The `spawn list` grid was 888 characters wide with 30 clouds, making it
completely unreadable in standard terminals (80-120 columns). Now detects
terminal width and automatically switches to a compact view showing each
agent with its cloud count and any missing clouds.

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-10 15:30:48 -08:00
A
2b1944ee1c
fix: Show cloud type and agent notes in info commands (#255)
cmdAgentInfo now displays the cloud type (api, cli, sandbox, etc.) next
to each cloud provider, helping users understand what kind of
infrastructure they're choosing. Also shows agent notes when present.

cmdCloudInfo now shows the cloud type beneath the description for
quick reference.

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-10 15:11:06 -08:00
A
16cabed6d8
feat: detect unknown flags and show actionable error (#250)
Previously, unknown flags like --json or --verbose were silently ignored
or misinterpreted as positional arguments (agent/cloud names), leading to
confusing error messages. Now the CLI detects unrecognized flags and shows
a clear error listing the supported flags.

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-10 14:12:20 -08:00
A
06091864af
fix: Show unified agent+cloud suggestions for unknown single-arg commands (#229)
Previously, `spawn hetzne` (typo of cloud name "hetzner") would show
"Unknown agent: hetzne" with no useful suggestion, because it only
searched agent names for typo matches. Now when a single argument
matches neither an agent nor a cloud, the error searches both pools
and shows "Did you mean hetzner (cloud)?" — guiding the user to the
right command.

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-10 12:49:44 -08:00
A
eeecdedef2
fix: Bundle dependencies in CLI build for proot-distro compatibility (#216)
The bun build command was failing on proot-distro ubuntu because it couldn't
resolve node_modules dependencies. Added --packages bundle flag to explicitly
bundle all dependencies into the output file.

Fixes #209

Agent: issue-responder

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 12:22:58 -08:00
A
d1ecbaf88c
feat: Add cloud info command (spawn <cloud>) for cloud-first discovery (#192)
Users who know their preferred cloud but not which agents are available
had no way to find out. Now `spawn hetzner` shows all agents available
on Hetzner, mirroring how `spawn claude` shows all clouds for Claude.

- Add cmdCloudInfo() showing cloud details + available agents
- handleDefaultCommand detects cloud names and routes to cloud info
- Update help text and clouds list footer to document the new command
- Bump CLI version to 0.2.15

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-10 08:54:24 -08:00
A
86dfbacab0
fix: Detect swapped agent/cloud arguments and fix count pluralization (#178)
When users type "spawn sprite claude" instead of "spawn claude sprite",
the CLI now detects the swap and suggests the correct order instead of
showing a confusing "Unknown agent" error. Also fixes grammar in
"spawn agents" and "spawn clouds" output (1 cloud vs 1 clouds).

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-10 07:42:25 -08:00
A
4133813879
fix: Add typo suggestions and --help flag handling for better CLI UX (#168)
- Add "Did you mean?" suggestions when agent/cloud names have typos
  (using Levenshtein distance, max 3 edits)
- Handle "spawn <agent> --help" to show agent info instead of failing
  with "invalid characters" error on the --help flag
- Handle "--help" after subcommands (spawn list --help, spawn agents --help)
  to show general help instead of silently ignoring the flag
- Bump CLI version to 0.2.13
- Add 15 tests for levenshtein and findClosestMatch functions

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-10 07:17:11 -08:00
Sprite
18b5aa4a32 fix: Remove curl|bash script validation that blocks spawn scripts
The spawn scripts themselves use curl|bash to install agents (e.g.
Claude Code). The validateScriptContent check was blocking our own
legitimate scripts. Removed curl|bash and wget|bash from the
dangerous patterns list since the scripts are already fetched from
our trusted GitHub repo.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 09:40:16 +00:00
Sprite
7c43b901a6 fix: Switch build target from node to bun to fix UTF-8 mojibake
Root cause: Bun has a known bug (oven-sh/bun#25767) where --target=node
causes UTF-8 string literals to be double-encoded as Latin-1, producing
mojibake (â instead of ◆/│/✔). Switching to --target=bun avoids this
encoding path entirely.

Also removes the ineffective stdout.write monkey-patch that was
attempting to work around this issue.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 09:36:28 +00:00
A
7100948136
test: Add unicode-detect tests and bump version to 0.2.11 (#164)
Add 16 tests for unicode-detect.ts which had zero coverage.
Tests verify ASCII/Unicode detection based on TERM, SSH,
and SPAWN_UNICODE/SPAWN_ASCII/SPAWN_NO_UNICODE env vars.
Also tests LANG setting and debug output behavior.

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-10 01:34:54 -08:00
Sprite
67051bfc48 fix: Monkey-patch stdout.write to force UTF-8 Buffer encoding
Explicitly convert string chunks to Buffer.from(chunk, 'utf8') before
writing to process.stdout. This fixes UTF-8 mojibake (â instead of ◆/│)
seen in some Bun + terminal combinations (e.g. Ghostty on macOS) where
process.stdout.write(string) doesn't encode as UTF-8 by default.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 09:25:58 +00:00
Sprite
553626e902 feat: Force UTF-8 encoding for Unicode output
Added explicit LANG=en_US.UTF-8 and stdout.setEncoding('utf8')
when Unicode mode is enabled. This should prevent UTF-8 mojibake
(â appearing instead of ◆) in terminals like Ghostty.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 09:17:53 +00:00
Sprite
ac1a197dfe debug: Add SPAWN_DEBUG flag to diagnose Unicode detection
Adds debug logging to unicode-detect.ts to help troubleshoot why
Unicode rendering isn't working in Ghostty terminal. When SPAWN_DEBUG=1
is set, the CLI will show:

- Current TERM value (e.g., xterm-ghostty)
- SSH environment variables (SSH_CONNECTION, SSH_CLIENT, SSH_TTY)
- Whether ASCII mode is being forced

This will help identify if SSH detection is incorrectly triggering
ASCII fallback for local Ghostty sessions.

Usage: SPAWN_DEBUG=1 spawn list

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 07:47:43 +00:00
Sprite
4f23fae38f feat: Enable Unicode rendering by default on local terminals
Reverses the overly conservative ASCII-only approach. Now defaults to
Unicode (beautiful spinners, checkmarks, symbols) on local macOS
Terminal, iTerm2, and modern Linux terminals, while still forcing
ASCII fallback for problematic environments:

- SSH sessions (encoding mismatches)
- Dumb terminals (TERM=dumb)
- Users can override with SPAWN_UNICODE=1 or SPAWN_NO_UNICODE=1

This fixes rendering issues while maintaining compatibility across
all environments.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 07:41:24 +00:00
Sprite
dff70afb4b fix: Force CI mode for complete Unicode disabling in CLI
- Set both TERM=linux and CI=true in unicode-detect.ts
- CI env var provides additional Unicode disabling for @clack/prompts
- Fix test imports to use package.json instead of deleted version.ts
- Bump to 0.2.6

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 07:35:20 +00:00
Sprite
875e9adb6b chore: Bump version to 0.2.5 and add version bump policy
- Bumped CLI version from 0.2.4 to 0.2.5
- Added rule to CLAUDE.md: ANY change to cli/ requires a version bump
- Uses semantic versioning (patch for fixes, minor for features, major for breaking)
- Auto-update ensures users get latest version immediately

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 07:24:28 +00:00
Sprite
935d1f5fe9 chore: Bump version to 0.2.4
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 07:15:11 +00:00
Sprite
5962a00c15 chore: Bump version to 0.2.3
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 06:56:47 +00:00
Sprite
13b601239d chore: Bump version to 0.2.2
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 06:53:20 +00:00
Sprite
01042fab5a chore: Bump version to 0.2.1
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 06:49:49 +00:00
Sprite
c4d99daaab feat: Bump version to 0.2.0 and implement auto-update on run
Changes:
- Bumped version from 0.1.0 to 0.2.0
- Changed update-check mechanism to auto-install updates instead of just notifying
- checkForUpdates() now blocks and runs install.sh automatically when update is available
- Added executor wrapper for testability of execSync calls
- Updated all tests to mock executor.execSync instead of child_process.execSync
- Auto-update runs on every spawn invocation (24-hour cache prevents excessive checks)
- On update failure, shows error message but continues with original command

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 06:48:19 +00:00
Sprite
76c427f71e chore: Update dependencies to latest versions
- Update @clack/prompts from ^0.10.0 to ^1.0.0
- Update @types/bun from ^1.2.0 to ^1.3.8
- All tests pass with updated dependencies
2026-02-08 04:41:24 +00:00
Sprite
272812233e refactor: Remove vitest completely, use bun test exclusively
- Remove vitest and @vitest/ui from devDependencies
- Update test scripts to use 'bun test'
- Delete vitest.config.ts (no longer needed)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 04:29:54 +00:00
Sprite
073251362f test: add unit tests for CLI TypeScript implementation
Added comprehensive test suite for cli/ TypeScript code:
- 37 tests covering manifest.ts, commands.ts, and integration scenarios
- Tests for manifest loading, caching, network fallback, and validation
- Tests for all CLI commands (list, agents, clouds, run, help, etc.)
- Integration tests for end-to-end workflows
- ~900 lines of test code covering ~635 lines of source

Test infrastructure:
- Added vitest as test runner for fast execution
- Created isolated test environment with mocked cache directories
- Mocked network calls to avoid external dependencies
- Test coverage for critical paths: caching, offline mode, error handling

All tests passing with proper isolation and cleanup.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-08 00:52:12 +00:00
L
4087deb14e
Drop nounset (set -u) flag — incompatible with env var checks (#27)
The autonomous refactoring added `set -euo pipefail` but the scripts
check optional env vars with `[[ -n "$VAR" ]]` which is a fatal error
under nounset when the var isn't set (e.g. SPRITE_NAME, OPENROUTER_API_KEY).

Fix: downgrade to `set -eo pipefail` across all 42 affected files.

Co-authored-by: Sprite <noreply@sprite.dev>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-07 16:22:04 -08:00