Commit graph

479 commits

Author SHA1 Message Date
A
af1c366dd5
test: add coverage for showInfoOrError routing in index.ts (#295)
Adds 25 tests for the previously untested showInfoOrError function which
handles single-argument CLI routing (agent info, cloud info, unknown
command with fuzzy suggestions). Tests cover valid agents, valid clouds,
unknown names, fuzzy match suggestions, help flag routing, and edge 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-10 15:32:06 -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
4f23276338
refactor: reduce complexity in Fly, Koyeb, and Railway providers (#293)
- Split _fly_create_and_start_machine (70 lines) into _fly_create_machine
  and _fly_wait_for_machine_start for single-responsibility
- Replace ensure_koyeb_token (38 lines) with ensure_api_token_with_provider
- Replace ensure_railway_token (37 lines) with ensure_api_token_with_provider
- Remove _save_koyeb_token and _save_railway_token (handled by shared helper)

Net reduction: ~80 lines of duplicated code

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-10 15:30:32 -08:00
A
2c54300be2
feat: Add kilocode on FluidStack (#292)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:28:47 -08:00
A
ceba1437b1
feat: Add kilocode on GitHub Codespaces (#291)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:28:29 -08:00
A
4945693aa6
feat: Add plandex on FluidStack (#290)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:28:15 -08:00
A
306322faff
feat: Add plandex on GitHub Codespaces (#289)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:28:00 -08:00
A
a873d26a67
feat: Add opencode on FluidStack (#288)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:27:47 -08:00
A
22a4d6baee
feat: Add opencode on GitHub Codespaces (#287)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:27:33 -08:00
A
004aafaca0
feat: Add Cherry Servers cloud provider with openclaw and goose (#286)
Add Cherry Servers as a new cloud provider with:
- REST API-based server provisioning
- SSH key management via API
- Full root access to cloud VPS instances
- Hourly billing with no commitments

Implementation includes:
- cherry/lib/common.sh with Cherry Servers API primitives
- cherry/openclaw.sh for OpenClaw deployment
- cherry/goose.sh for Goose deployment
- cherry/README.md with authentication and usage docs
- manifest.json updates (cloud entry + 14 matrix entries)

Agent: cloud-scout

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 15:27:23 -08:00
A
7aaf55ddb5
feat: Add cline on FluidStack (#285)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:27:17 -08:00
A
6f25b6740f
feat: Add cline on GitHub Codespaces (#284)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:27:02 -08:00
A
7b54d9e22d
feat: Add amazonq on FluidStack (#283)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:26:50 -08:00
A
0346e972e5
feat: Add amazonq on GitHub Codespaces (#281)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:26:21 -08:00
A
f46d8d0b5d
feat: Add plandex on Northflank (#282)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:26:13 -08:00
A
f4b2b6e906
feat: Add gemini on FluidStack (#280)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:26:05 -08:00
A
502ff1e7a8
feat: Add Plandex on Render (#278)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:25:51 -08:00
A
f708e8d4e7
feat: Add gemini on GitHub Codespaces (#277)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:25:45 -08:00
A
7eae9d76c3
feat: Add opencode on Northflank (#276)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:25:34 -08:00
A
04cb12fa4a
feat: Add interpreter on FluidStack (#275)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:25:28 -08:00
A
70cca1a0ae
feat: Add OpenCode on Render (#274)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:25:20 -08:00
A
b7f0c4444f
feat: Add interpreter on GitHub Codespaces (#273)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:25:19 -08:00
A
02884cbd44
feat: Add codex on FluidStack (#272)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:25:02 -08:00
A
637aa401e6
feat: Add kilocode on Northflank (#271)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:24:53 -08:00
A
f1374a112a
feat: Add codex on GitHub Codespaces (#270)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:24:52 -08:00
A
68ba980e37
feat: Add Kilo Code on Render (#269)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:24:49 -08:00
A
05797f487c
feat: Add goose on GitHub Codespaces (#268)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:24:25 -08:00
A
7c371b6736
feat: Add goose on FluidStack (#267)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:24:19 -08:00
A
1d3073ed6b
feat: Add gptme on Render (#266)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:24:13 -08:00
A
e93858d5b3
feat: Add plandex on Railway (#265)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:24:08 -08:00
A
51b45f9db0
feat: Add nanoclaw on GitHub Codespaces (#263)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:23:47 -08:00
A
00f1bfe862
feat: Add nanoclaw on FluidStack (#262)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:23:39 -08:00
A
9fa80b9253
feat: Add Cline on Render (#261)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:23:32 -08:00
A
100bcc60fd
feat: Add opencode on Railway (#260)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:23:26 -08:00
A
9ac200f9e3
feat: Add openclaw on GitHub Codespaces (#258)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:23:03 -08:00
A
e198c0a8dc
feat: Add openclaw on FluidStack (#259)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:22:55 -08:00
A
23fa0d2630
feat: Add Amazon Q CLI on Render (#257)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:22:49 -08:00
A
4774e523cb
feat: Add kilocode on Railway (#256)
Agent: gap-filler

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 15:22:44 -08:00
B
2061c3d22d docs: Sync README matrix with manifest.json
Agent: team-lead
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 23:19:58 +00:00
B
85e7e7b9f5 docs: Document streaming architecture and Sprite lifecycle in SKILL.md
Add sections covering:
- Output streaming behavior and why it keeps Sprites alive
- Bun idleTimeout gotcha (10s default, server.timeout(req, 0) fix)
- HTTP/1.1 requirement for long-lived chunked responses
- Updated workflow template with streaming curl flags
- New troubleshooting entries for curl errors 92, 18, and Sprite pause

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 23:18:56 +00:00
B
d4b8e5025a fix: Disable Bun idle timeout for streaming requests via server.timeout(req, 0)
Per Bun docs, server.timeout(req, 0) disables the idle timeout
entirely for a specific request. This is the proper API for long-lived
streaming connections — no more fighting the 255s cap.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 23:16:35 +00: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
2b9005f0a5
test: Add 420 bash -n syntax validation tests for all shell scripts (#254)
Runs `bash -n` on every shell script in the repo:
- shared/common.sh (core library)
- All 21 cloud lib/common.sh files
- All 264+ implemented agent scripts

This is the automated equivalent of the CLAUDE.md rule:
"Run bash -n on every changed .sh file before committing."

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-10 15:10:43 -08:00
A
29b6a0e7b9
refactor: simplify CLI command dispatch with lookup tables (#253)
Extract duplicated agent/cloud lookup logic into showInfoOrError() and
replace repetitive switch cases with dispatch tables, reducing main()
from 85 to 65 lines and handleDefaultCommand() from 52 to 16 lines.

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-10 15:10:04 -08:00
B
f2ef7623fb fix: Set Bun idleTimeout to 255s and heartbeat to 15s
Bun.serve defaults to 10s idleTimeout, which kills the streaming
connection before the heartbeat even fires during Claude's startup
silence. Set to 255s (max allowed) and tighten heartbeat to 15s.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 22:56:15 +00:00
B
200b6dc5b2 fix: Force HTTP/1.1 for streaming to avoid HTTP/2 stream errors
HTTP/2 has strict stream lifecycle management that doesn't play well
with long-lived chunked responses — curl exits with error 92
(stream not closed cleanly: INTERNAL_ERROR). HTTP/1.1 handles
persistent streaming connections natively.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 22:51:35 +00:00
A
f39ffd6e24
fix: Prevent shell/Python injection in Codespaces, Render, and FluidStack (#252)
GitHub Codespaces scripts embedded API keys directly into heredocs sent
over SSH, allowing single-quote breakout for command injection. Fixed by
adding upload_file/run_server/inject_env_vars helpers to Codespaces lib
and using safe temp-file-upload pattern (matching Railway/Render).

Render claude.sh and openclaw.sh built JSON config via unescaped heredocs.
Fixed by using shared setup_claude_code_config/setup_openclaw_config
helpers which properly json_escape values.

FluidStack had triple-quote injection in SSH key registration (pub_key
embedded in Python triple-quotes) and missing single-quote validation in
create_server env var checks. Fixed by reading values via stdin/argv
instead of string interpolation, and added single-quote to validation.

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>
2026-02-10 14:14:41 -08:00
A
281ea2a74f
test: Add 43 tests for display command output (cmdAgentInfo, cmdList, cmdAgents, cmdClouds, cmdHelp, cmdUpdate) (#251)
Cover previously untested happy paths for user-facing display commands:
- cmdAgentInfo: agent details, available clouds, no-clouds fallback, many clouds
- cmdList: matrix table rendering, implemented counts, edge cases
- cmdAgents: agent listing with cloud counts, singular/plural, descriptions
- cmdClouds: cloud listing with agent counts, singular/plural, descriptions
- cmdHelp: all sections (USAGE, EXAMPLES, AUTHENTICATION, TROUBLESHOOTING, INSTALL)
- cmdUpdate: version match, fetch failure, non-ok response

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-10 14:12:31 -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
2635ba22a1
refactor: Decompose create_server in UpCloud and AWS Lightsail (#249)
Extract helper functions to reduce complexity:
- UpCloud: Extract _build_upcloud_server_body() from create_server (Python JSON body builder)
- AWS Lightsail: Extract _wait_for_lightsail_instance() from create_server (polling loop)

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-10 14:11:54 -08:00