diff --git a/cli/README.md b/cli/README.md new file mode 100644 index 00000000..eaaa9364 --- /dev/null +++ b/cli/README.md @@ -0,0 +1,366 @@ +# Spawn CLI + +The spawn CLI is a command-line tool for launching AI coding agents on cloud providers, pre-configured with OpenRouter. + +## Overview + +The spawn CLI provides a unified interface to: +- Launch any supported AI agent (Claude Code, Aider, etc.) on any supported cloud provider +- Interactively browse available agents and clouds +- View the agent × cloud compatibility matrix +- Self-update to the latest version + +## Architecture + +### Three-Tier Installation Strategy + +The CLI uses a progressive fallback installation strategy to maximize compatibility: + +``` +┌─────────────────────────────────────────────────────────┐ +│ Method 1: Bun (Preferred) │ +│ - Fastest execution (native TypeScript runtime) │ +│ - Full TypeScript support with minimal overhead │ +│ - Falls back to compiled binary if global install fails │ +└─────────────────────────────────────────────────────────┘ + ↓ (if bun not found) +┌─────────────────────────────────────────────────────────┐ +│ Method 2: npm │ +│ - Standard Node.js package manager │ +│ - Transpiles TypeScript to JavaScript at install time │ +│ - Requires Node.js runtime │ +└─────────────────────────────────────────────────────────┘ + ↓ (if npm not found) +┌─────────────────────────────────────────────────────────┐ +│ Method 3: Bash Fallback │ +│ - Pure bash implementation (spawn.sh) │ +│ - Zero runtime dependencies except curl + jq/python3 │ +│ - Functional subset of TypeScript CLI │ +└─────────────────────────────────────────────────────────┘ +``` + +**Why this pattern?** +- **Universal compatibility**: Works on any system with bash and curl +- **Optimal performance**: Uses the fastest available runtime (bun > node > bash) +- **Zero friction**: No prerequisite installation required for basic usage +- **Graceful degradation**: Each tier provides full functionality with varying performance characteristics + +### Directory Structure + +``` +cli/ +├── src/ +│ ├── index.ts # Entry point (routes commands to handlers) +│ ├── commands.ts # All command implementations +│ ├── manifest.ts # Manifest fetching and caching logic +│ └── version.ts # Version constant +├── install.sh # Multi-tier installer script +├── spawn.sh # Bash fallback CLI (full implementation) +├── package.json # npm package metadata +└── tsconfig.json # TypeScript configuration +``` + +### TypeScript Implementation + +The TypeScript CLI (`src/*.ts`) provides: + +- **Interactive mode**: Terminal UI with prompts for selecting agents and clouds +- **Manifest caching**: Local cache with TTL to minimize network requests +- **Progress indicators**: Spinners and colored output for better UX +- **Error handling**: Structured error messages and exit codes + +**Key dependencies:** +- `@clack/prompts` — Interactive terminal prompts +- `picocolors` — Terminal color support + +### Bash Fallback Implementation + +The bash CLI (`spawn.sh`) is a standalone script that: + +- Implements the same commands as the TypeScript version +- Uses `jq` or `python3` for JSON parsing (auto-detects which is available) +- Provides a numbered menu picker for interactive mode +- Maintains local manifest cache with TTL +- Supports all core commands: `list`, `agents`, `clouds`, `run`, `improve`, `update` + +**Why maintain both implementations?** +- **Portability**: Bash version works on minimal systems (CI containers, embedded Linux, etc.) +- **Bootstrap**: Used by installer when bun/npm aren't available +- **Reference**: Demonstrates that the protocol is runtime-agnostic + +## Installation + +### Quick Install + +```bash +curl -fsSL https://raw.githubusercontent.com/OpenRouterTeam/spawn/main/cli/install.sh | bash +``` + +The installer will: +1. Check for `bun` → install via `bun install -g` if found +2. Check for `npm` → install via `npm install -g` if found +3. Fallback → download `spawn.sh` to `$HOME/.local/bin` if neither found + +### Environment Variables + +- `SPAWN_INSTALL_DIR` — Override install directory (default: `$HOME/.local/bin` for fallback method) + +### Manual Installation (Development) + +```bash +cd cli +bun install +bun link +``` + +Or build a standalone binary: + +```bash +bun run compile # Creates ./spawn executable +``` + +## Usage + +### Interactive Mode + +```bash +spawn +``` + +Launches an interactive picker to select an agent and cloud provider. + +### Direct Launch + +```bash +spawn +``` + +Examples: +```bash +spawn claude sprite # Launch Claude Code on Sprite +spawn aider hetzner # Launch Aider on Hetzner Cloud +``` + +### Agent Information + +```bash +spawn +``` + +Show which cloud providers support the specified agent. + +Example: +```bash +spawn claude +# Output: +# Claude Code — AI coding agent from Anthropic +# +# Available clouds: +# Sprite spawn claude sprite +# Hetzner Cloud spawn claude hetzner +``` + +### List All Combinations + +```bash +spawn list +``` + +Display the full agent × cloud compatibility matrix. + +### List Agents + +```bash +spawn agents +``` + +Show all available agents with descriptions. + +### List Cloud Providers + +```bash +spawn clouds +``` + +Show all available cloud providers with descriptions. + +### Improve Command + +```bash +spawn improve [--loop] +``` + +Clone (or update) the spawn repository and run the `improve.sh` script, which uses Claude to autonomously add missing matrix entries or new agents/clouds. + +### Update CLI + +```bash +spawn update +``` + +- **TypeScript version**: Displays update instructions (re-run installer) +- **Bash version**: Self-updates by downloading the latest `spawn.sh` + +### Version + +```bash +spawn version +``` + +Display the current CLI version. + +## Development + +### Prerequisites + +- Bun 1.0+ (or Node.js 18+ with npm) +- TypeScript 5.0+ + +### Running Locally + +```bash +bun run dev # Run TypeScript CLI directly +bun run build # Build to cli.js +bun run compile # Compile to standalone binary +``` + +### Testing + +```bash +# Test TypeScript version +bun run dev list +bun run dev agents +bun run dev claude sprite + +# Test bash version +bash spawn.sh list +bash spawn.sh agents +bash spawn.sh claude sprite +``` + +### Code Organization + +**`src/index.ts`** +- Command-line argument parsing +- Routes to appropriate command handler +- Minimal logic (just dispatching) + +**`src/commands.ts`** +- All command implementations +- Interactive picker UI +- Script execution logic +- Help text + +**`src/manifest.ts`** +- Manifest fetching from GitHub +- Local caching with TTL +- Offline fallback to stale cache +- Typed manifest structure + +**`src/version.ts`** +- Single source of truth for version number +- Imported by both TypeScript and bash implementations + +### Adding a New Command + +1. Add command handler in `src/commands.ts`: + ```typescript + export async function cmdMyCommand() { + const manifest = await loadManifest(); + // ... implementation + } + ``` + +2. Add routing in `src/index.ts`: + ```typescript + case "mycommand": + await cmdMyCommand(); + break; + ``` + +3. Update help text in `src/commands.ts` → `cmdHelp()` + +4. (Optional) Add equivalent implementation to `spawn.sh` for bash fallback + +## Design Rationale + +### Why TypeScript? + +- **Type safety**: Manifest structure is type-checked at compile time +- **Modern async/await**: Clean, readable asynchronous code +- **Rich ecosystem**: Access to high-quality CLI libraries (`@clack/prompts`, etc.) +- **Single codebase**: Same code runs on bun, node, or as a compiled binary + +### Why Bash Fallback? + +- **Universality**: Bash is available on virtually all Unix-like systems +- **Zero dependencies**: Only requires `curl` and `jq`/`python3` (one of which is usually installed) +- **CI/CD friendly**: Works in minimal Docker containers, GitHub Actions, etc. +- **Educational**: Demonstrates the protocol can be implemented in any language + +### Why Bun → npm → Bash Tiering? + +- **Performance gradient**: Bun is fastest, npm is widely available, bash always works +- **User experience**: Bun users get instant execution, others get working tool +- **Distribution**: Can be installed via package manager or curl | bash +- **Maintenance**: Single TypeScript codebase serves bun and npm, bash is separate but synchronized + +## Manifest Caching + +Both implementations cache the manifest locally to reduce network requests: + +- **Cache location**: `$XDG_CACHE_HOME/spawn/manifest.json` (or `~/.cache/spawn/manifest.json`) +- **TTL**: 1 hour (3600 seconds) +- **Offline fallback**: If fetch fails, uses stale cache if available +- **Invalidation**: `spawn update` clears the cache + +## Script Execution Flow + +When you run `spawn `: + +1. **Load manifest**: Fetch from GitHub or use cached version +2. **Validate combination**: Check that `matrix["/"]` is `"implemented"` +3. **Download script**: Fetch `https://openrouter.ai/lab/spawn//.sh` + - Fallback to GitHub raw URL if OpenRouter CDN fails +4. **Execute**: Pipe script to `bash -c` with inherited stdio +5. **Interactive handoff**: User interacts directly with the spawned agent + +## Contributing + +### Before Submitting Changes + +1. Test both TypeScript and bash versions: + ```bash + bun run dev --help + bash spawn.sh --help + ``` + +2. Ensure version numbers are synchronized: + - `src/version.ts` → `VERSION` + - `spawn.sh` → `SPAWN_VERSION` + - `package.json` → `version` + +3. Update this README if you add new commands or change behavior + +4. Run the installer locally to verify the three-tier strategy works: + ```bash + # Test with bun + bash install.sh + + # Test without bun (rename temporarily) + mv $(which bun) $(which bun).bak + bash install.sh + mv $(which bun).bak $(which bun) + ``` + +### Release Checklist + +1. Bump version in all three locations (see above) +2. Update CHANGELOG (if exists) +3. Test installer on clean system +4. Tag release: `git tag -a cli-vX.Y.Z -m "Release vX.Y.Z"` +5. Push tag: `git push --tags` + +## License + +See repository root for license information.