mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-04-28 03:49:31 +00:00
Three issues broke the OAuth callback server on macOS: 1. echo -e doesn't work in bash 3.x — \r\n appears as literal text in the HTTP response, browser gets malformed headers. Fix: pre-write response with printf to a file before the subshell. 2. local variables inside ( ... ) & subshell — undefined behavior in bash 3.x since subshells aren't function scope. Fix: use plain variables in subshells. 3. ((elapsed++)) when elapsed=0 evaluates to falsy — set -e kills the script on the first iteration of the timeout loop. Fix: use elapsed=$((elapsed + 1)) instead. Also simplified nc_listen detection to only check for BusyBox (the -p flag check could misfire on macOS nc). Applied to all 10 lib/common.sh files. Co-authored-by: Sprite <noreply@sprite.dev> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
167 lines
7.3 KiB
Markdown
167 lines
7.3 KiB
Markdown
# Spawn
|
|
|
|
Spawn is a matrix of **agents x clouds**. Every script provisions a cloud server, installs an agent, injects OpenRouter credentials, and drops the user into an interactive session.
|
|
|
|
## The Matrix
|
|
|
|
`manifest.json` is the source of truth. It tracks:
|
|
- **agents** — coding agents / AI tools (Claude Code, OpenClaw, NanoClaw, ...)
|
|
- **clouds** — cloud providers to run them on (Sprite, Hetzner, ...)
|
|
- **matrix** — which `cloud/agent` combinations are `"implemented"` vs `"missing"`
|
|
|
|
## How to Improve Spawn
|
|
|
|
When run via `./improve.sh`, your job is to pick ONE of these tasks and execute it:
|
|
|
|
### 1. Fill a missing matrix entry
|
|
|
|
Look at `manifest.json` → `matrix` for any `"missing"` entry. To implement it:
|
|
|
|
- Find the **cloud's** `lib/common.sh` — it has all the provider-specific primitives (create server, run command, upload file, interactive session)
|
|
- Find the **agent's** existing script on another cloud — it shows the install steps, config files, env vars, and launch command
|
|
- Combine them: use the cloud's primitives to execute the agent's setup steps
|
|
- The script goes at `{cloud}/{agent}.sh`
|
|
|
|
**Pattern for every script:**
|
|
```
|
|
1. Source {cloud}/lib/common.sh (local or remote fallback)
|
|
2. Authenticate with cloud provider
|
|
3. Provision server/VM
|
|
4. Wait for readiness
|
|
5. Install the agent
|
|
6. Get OpenRouter API key (env var or OAuth)
|
|
7. Inject env vars into shell config
|
|
8. Write agent-specific config files
|
|
9. Launch interactive session
|
|
```
|
|
|
|
**OpenRouter injection is mandatory.** Every agent script MUST:
|
|
- Set `OPENROUTER_API_KEY` in the shell environment
|
|
- Set provider-specific env vars (e.g., `ANTHROPIC_BASE_URL=https://openrouter.ai/api`)
|
|
- These come from the agent's `env` field in `manifest.json`
|
|
|
|
### 2. Add a new agent
|
|
|
|
Research coding agents, AI CLI tools, or AI-powered dev tools. To add one:
|
|
|
|
1. Add an entry to `manifest.json` → `agents` with: name, description, url, install command, launch command, and env vars needed for OpenRouter
|
|
2. Add `"missing"` entries to the matrix for every existing cloud
|
|
3. Implement the script for at least one cloud
|
|
4. Update `README.md`
|
|
|
|
**Where to find new agents:**
|
|
- GitHub trending in AI/coding categories
|
|
- OpenRouter's ecosystem
|
|
- HuggingFace agent frameworks
|
|
- CLI tools that accept `ANTHROPIC_API_KEY` or `OPENAI_API_KEY` (these work with OpenRouter via base URL override)
|
|
|
|
### 3. Add a new cloud provider
|
|
|
|
Research cloud providers with API-based provisioning. To add one:
|
|
|
|
1. Create `{cloud}/lib/common.sh` with the provider's primitives:
|
|
- Auth/token management (env var → config file → prompt)
|
|
- Server creation (API call or CLI)
|
|
- SSH/exec connectivity
|
|
- File upload
|
|
- Interactive session
|
|
- Server destruction
|
|
2. Add an entry to `manifest.json` → `clouds`
|
|
3. Add `"missing"` entries to the matrix for every existing agent
|
|
4. Implement at least one agent script
|
|
5. Update `README.md`
|
|
|
|
**Good candidate clouds** have:
|
|
- REST API or simple CLI for provisioning
|
|
- SSH access to the created server
|
|
- Cloud-init or similar userdata support
|
|
- Pay-per-hour pricing (so users can destroy after use)
|
|
|
|
### 4. Extend tests
|
|
|
|
`test/run.sh` contains the test harness. When adding a new cloud or agent:
|
|
- Add mock functions for the cloud's CLI/API calls
|
|
- Add per-script assertions matching the agent's setup steps
|
|
- Run `bash test/run.sh` to verify
|
|
|
|
## File Structure Convention
|
|
|
|
```
|
|
spawn/
|
|
cli/
|
|
spawn.sh # Main CLI binary (interactive picker, matrix viewer, launcher)
|
|
install.sh # One-liner installer (downloads spawn.sh to ~/.local/bin)
|
|
{cloud}/
|
|
lib/common.sh # Cloud-specific shared functions
|
|
{agent}.sh # One script per agent
|
|
manifest.json # The matrix (source of truth)
|
|
improve.sh # Run this to trigger one improvement cycle
|
|
test/run.sh # Test harness
|
|
README.md # User-facing docs
|
|
```
|
|
|
|
## CLI (`cli/`)
|
|
|
|
The `spawn` CLI is a pure-bash binary that provides a unified entry point for the matrix.
|
|
|
|
- **`cli/spawn.sh`** — Main binary. Fetches manifest.json from GitHub (cached for 1hr at `~/.cache/spawn/`), parses it with `jq` or `python3` fallback, and provides: interactive picker (`spawn`), direct launch (`spawn <agent> <cloud>`), agent info (`spawn <agent>`), matrix table (`spawn list`), and self-update (`spawn update`). Installed to `~/.local/bin/spawn`.
|
|
- **`cli/install.sh`** — One-liner installer. Downloads `spawn.sh` to `~/.local/bin/spawn`, sets executable bit, and prints PATH instructions if needed. Override install dir with `SPAWN_INSTALL_DIR` env var.
|
|
|
|
## Script Conventions
|
|
|
|
- `#!/bin/bash` + `set -e`
|
|
- Source `lib/common.sh` with local-first, remote-fallback pattern
|
|
- Use `OPENROUTER_API_KEY` env var to skip OAuth when set
|
|
- All env vars documented in README.md under the relevant section
|
|
- Remote fallback URL: `https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/{path}`
|
|
- Scripts must be runnable via: `bash <(curl -fsSL https://openrouter.ai/lab/spawn/{cloud}/{agent}.sh)`
|
|
|
|
## After Each Change
|
|
|
|
1. Update `manifest.json` matrix status to `"implemented"`
|
|
2. Update `README.md` with usage instructions
|
|
3. Run `bash -n {file}` to syntax-check your scripts
|
|
4. Commit with a descriptive message
|
|
|
|
## Agent Team Roles
|
|
|
|
When running as part of an agent team (`./improve.sh`), teammates are assigned specific roles:
|
|
|
|
### Gap Filler
|
|
You're assigned a specific `{cloud}/{agent}` entry to implement. Steps:
|
|
1. Read `{cloud}/lib/common.sh` — understand the cloud's primitives
|
|
2. Read an existing `{agent}.sh` on another cloud — understand the install steps
|
|
3. Write `{cloud}/{agent}.sh` combining the two
|
|
4. Update `manifest.json` matrix entry to `"implemented"`
|
|
5. Add usage entry to `README.md` under the cloud's section
|
|
6. `bash -n` syntax check
|
|
7. Commit your changes only (don't touch other teammates' files)
|
|
|
|
### Agent Scout
|
|
Research and add ONE new AI coding agent. Requirements:
|
|
- Must be installable via a single command (`npm install -g`, `pip install`, `curl | bash`, etc.)
|
|
- Must accept API keys via environment variables (`OPENAI_API_KEY`, `OPENROUTER_API_KEY`, `ANTHROPIC_API_KEY`, etc.)
|
|
- OpenRouter compatibility: either native `OPENROUTER_API_KEY` support, or `OPENAI_BASE_URL=https://openrouter.ai/api/v1` override
|
|
- Add to `manifest.json` → `agents` with full metadata including `env` field
|
|
- Add `"missing"` entries in the matrix for ALL existing clouds
|
|
- Implement on at least 2 clouds to prove the pattern
|
|
- Update `README.md`
|
|
|
|
### Cloud Scout
|
|
Research and add ONE new cloud provider. Requirements:
|
|
- REST API or CLI for provisioning VMs/instances
|
|
- SSH access to created servers
|
|
- Cloud-init, userdata, or startup-script support
|
|
- Pay-per-hour pricing
|
|
- Create `{cloud}/lib/common.sh` with ALL primitives (see existing clouds for the pattern)
|
|
- Add to `manifest.json` → `clouds`
|
|
- Add `"missing"` entries for ALL existing agents
|
|
- Implement at least 2 agents to prove the lib works
|
|
- Update `README.md`
|
|
|
|
### Coordination Rules
|
|
- **Never edit the same file as another teammate** — coordinate via the shared task list
|
|
- **manifest.json conflicts**: only ONE teammate should update manifest.json at a time. If you're a Gap Filler, update just your entry. If you're a Scout, add your block and your matrix entries.
|
|
- **README.md**: append your section, don't rewrite others' sections
|
|
- **Commit early**: commit your work as soon as it's done so other teammates can see it
|
|
- **Self-claim**: when you finish your assigned task, check the task list for the next unblocked item
|