Break down _get_subnet_id() (101 lines) and create_server() (87 lines)
into smaller, single-responsibility functions:
- _create_vcn(): VCN creation (19 lines)
- _setup_vcn_networking(): Internet gateway, route table, security list (47 lines)
- _create_subnet(): Subnet creation with AD lookup (25 lines)
- _get_subnet_id(): Now just finds or orchestrates creation (22 lines)
- _get_instance_public_ip(): VNIC lookup and IP extraction (27 lines)
- create_server(): Now delegates IP retrieval (59 lines)
Agent: complexity-hunter
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
- 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>
The compareVersions function decides whether auto-update runs, but had
no direct test coverage. Tests cover: basic comparisons, precedence
ordering (major > minor > patch), missing/extra segments, zero and
boundary versions, non-numeric input handling, parseSemver helper,
realistic spawn version scenarios, and full checkForUpdates integration
with edge-case version strings.
Agent: test-engineer
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
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>
The unicode-detect module only modifies TERM, never LANG. Two tests
incorrectly expected LANG to be set to en_US.UTF-8 - fixed to match
actual module behavior.
Agent: team-lead
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
- `spawn update` now performs auto-update instead of printing curl command
- `--prompt` without both agent and cloud now errors instead of being silently dropped
- Update banner box uses dynamic padding to align correctly with any version length
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>
- Extract resolvePrompt() from main() in cli/src/index.ts (98 -> 62 lines)
Separates prompt flag parsing/file-reading from command dispatch
- Extract _validate_oauth_server_args() and _generate_oauth_html() from
start_oauth_server() in shared/common.sh (81 -> 52 lines)
Separates validation/HTML generation from server startup
- Bump CLI version to 0.2.11
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>
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>
- Use --model sonnet (faster, cheaper, sufficient for gap-filling)
- Add timeout 3600s (1h) on claude commands to prevent hangs
- Reduce RUN_TIMEOUT_MS to 75min (safety net above the 1h timeout)
- Previous run hung for 3+ hours with zero output on Opus
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>
- Changed update banner to use +, -, | instead of Unicode box characters
- Replaced arrow (→) with ASCII arrow (->)
- Changed p.cancel() to plain console.error to avoid Unicode bullet
- Ensures clean rendering on all terminals regardless of Unicode support
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Removed CHECK_INTERVAL and cache-based update checking
- Now fetches latest version on every spawn invocation
- 5-second timeout keeps it fast
- Simplified tests to match new behavior (8 tests instead of 12)
- Users who don't want update checks can set SPAWN_NO_UPDATE_CHECK=1
This ensures users always get the latest version immediately when available.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Changed unicode detection to default to ASCII mode (TERM=linux)
- Users can opt-in to unicode with SPAWN_UNICODE=1
- Auto-detects SSH sessions and forces ASCII (common rendering issues)
- Fixes bullet point display issues in interactive selectors
To enable unicode: export SPAWN_UNICODE=1
To force ASCII: export SPAWN_ASCII=1 (or SPAWN_NO_UNICODE=1)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Removed src/version.ts file
- Updated src/commands.ts, src/index.ts, and src/update-check.ts to import version from package.json
- Using JSON import assertion: `import pkg from "../package.json" with { type: "json" }`
- Eliminates need to maintain version in two places
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>
Implements a non-intrusive update notification system that:
- Checks for new versions once per day
- Shows a styled notification when updates are available
- Stores check results in cache to minimize network requests
- Can be disabled with SPAWN_NO_UPDATE_CHECK=1
Implementation:
- New update-check.ts module with background version checking
- Comprehensive test suite (16 tests) covering all scenarios
- Integrated into main CLI entry point
- Updated documentation in README.md
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The 663-line bash CLI (spawn.sh) has drifted from the TypeScript CLI,
missing --prompt, security validation, download fallback, and other
features. Rather than maintaining two implementations, the installer
now auto-installs bun (~5 seconds) when it's not present, ensuring
every user gets the full-featured TypeScript CLI.
- Remove cli/spawn.sh (663 lines)
- Simplify install.sh: remove npm method, add bun auto-install
- Extract build_and_install() helper to deduplicate build logic
- Update cli/README.md and CLAUDE.md to reflect bun-only strategy
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement Open Interpreter deployment on Vast.ai GPU instances.
Sources vastai/lib/common.sh, installs open-interpreter via pip,
configures OpenRouter via OPENAI_BASE_URL override, and launches
interactive session.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement gptme agent script for Oracle Cloud Infrastructure.
Installs gptme via pip, verifies installation, prompts for model
selection, and launches interactive gptme session with OpenRouter.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement Open Interpreter agent deployment on Oracle Cloud
Infrastructure. Installs via pip, configures OpenRouter API
integration via OPENAI_BASE_URL proxy.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement gptme deployment on Vast.ai GPU instances.
Installs gptme via pip, includes model selection prompt,
injects OpenRouter credentials.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Implement Goose (Block's AI coding agent) deployment on Vast.ai GPU instances.
Sources vastai/lib/common.sh, installs Goose via official installer,
configures OpenRouter as provider, and launches interactive session.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Documents the dual-mode cycle system (issue vs refactor), concurrency
model, worktree isolation, and guidance for modifying the service.
Also adds trigger service files to the file structure convention.
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement Codex CLI agent deployment on Oracle Cloud Infrastructure.
Installs @openai/codex via npm, configures OpenRouter API integration
via OPENAI_BASE_URL proxy.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement Kilo Code agent deployment on Vast.ai. Installs via npm
and configures OpenRouter provider type with API key.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Implement Kilo Code agent deployment on Oracle Cloud Infrastructure.
Sets KILO_PROVIDER_TYPE=openrouter and KILO_OPEN_ROUTER_API_KEY env vars.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Implement Cline agent script for Oracle Cloud Infrastructure.
Installs cline via npm, configures OpenRouter API keys,
and launches interactive cline session.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Issue triggers now spawn lightweight 2-agent runs (15-min timeout) in
isolated worktrees, while refactor cycles continue independently with
the full 6-agent team (30-min timeout). Duplicate issue runs are
rejected with 409.
- trigger-server.ts: pass SPAWN_ISSUE/SPAWN_REASON env vars to script,
add issue dedup (409), include issue in health/trigger responses
- refactor.sh: dual-mode (issue vs refactor) with isolated worktrees,
mode-specific prompts and timeouts, scoped cleanup
- start-refactor.sh: set MAX_CONCURRENT=3 (gitignored, local only)
- refactor.yml: handle 409 alongside existing 429
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement NanoClaw agent deployment on Oracle Cloud Infrastructure.
Installs tsx and clones nanoclaw repo, configures .env with Anthropic
API key proxied through OpenRouter, launches WhatsApp QR auth flow.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement Plandex agent deployment on Vast.ai. Installs via official
install script and verifies installation before launching.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Implement NanoClaw (WhatsApp AI agent) deployment on Vast.ai GPU instances.
Sources vastai/lib/common.sh, installs tsx and clones nanoclaw repo,
creates .env with Anthropic API key, and launches with npm run dev.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement Amazon Q CLI agent script for Oracle Cloud Infrastructure.
Installs Amazon Q via official installer, configures OpenRouter API keys,
and launches interactive q chat session.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement OpenClaw agent deployment on Oracle Cloud Infrastructure.
Uses OCI CLI for provisioning, installs openclaw via bun, configures
OpenRouter API integration with gateway+TUI launch.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement OpenClaw deployment on Vast.ai GPU instances.
Sources vastai/lib/common.sh, installs openclaw via bun,
configures OpenRouter API with model selection, starts
gateway in background and launches TUI.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement OpenCode agent deployment on Vast.ai. Uses opencode_install_cmd
from shared/common.sh for installation and injects OpenRouter API key.
Agent: gap-filler
Co-authored-by: B <6723574+louisgv@users.noreply.github.com>