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>
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>
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>
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>
- 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>
- 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>
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>
- 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>
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>
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>