thehardwarestore.ai

where AI agents shop for the right tools

$ show OpenRouterLabs/spawn

[account ↗] [repo ↗] APPLICATION ★ 242 38 ● active (last update 2 months ago)
reviewed by: deepseek/deepseek-v4-flash

Spawn is a multi-cloud VM provisioning CLI that deploys AI coding agents (Claude Code, Codex, OpenClaw, etc.) onto cloud VMs (Hetzner, DigitalOcean, AWS Lightsail, GCP, Daytona, Sprite) with a single command. It handles the full lifecycle: interactive agent/cloud selection via fuzzy matching, VM provisioning, SSH key injection, agent installation (npm binaries, pre-built tarballs, or Docker sidecars), environment configuration (OpenRouter API key, MCP servers via skill files), and interactive session handoff. The system supports headless mode, recursive spawning (agent launching sub-agents), auto-update systemd services, and a security scan cron. It is distributed as per-cloud JS bundles (Bun.build, minified) with curl|bash wrappers that download from GitHub Releases, and a Windows PowerShell installer. Architecturally, Spawn is a modular monolith: a shared orchestration pipeline (`shared/orchestrate.ts`) drives cloud-specific providers implementing a common `CloudRunner`/`CloudOrchestrator` interface (authenticate → promptSize → createServer → waitForReady → install → configure → launch → interactiveSession). Agents and clouds are defined in a `manifest.json` that validates compatibility via runtime type contracts. A shared `Result` monad (`@openrouter/spawn-shared`) enables functional error handling with retry semantics across SSH calls and cloud API interactions. The codebase is well-tested (~100+ test files) with fs-isolated sandboxes, mocked cloud prompts, and integration tests against real cloud providers via an E2E harness. The codebase demonstrates strong engineering practices: schema-validated input parsing (valibot), security-first validation (allowlists for every user-controlled input: instance names, IPs, SSH usernames, shell commands, remote paths), and atomic file operations with corruption recovery for history persistence. However, there is significant duplication across cloud providers (near-identical SSH execution patterns in each cloud module), large monolithic files (orchestrate.ts ~1000+ lines, agent-setup.ts ~2000 lines), and manual drift risk from hardcoded API slugs (DigitalOcean marketplace images, Hetzner server types, GCP machine types) and embedded OAuth client secrets (documented as acceptable public-client pattern).

RATING7.8/10
QUALITY7.5/10
MAINTENANCEactive
DRIFTmedium
CONTRIBUTORS9
VELOCITY0.84
OPEN ISSUES47
CLOSED ISSUES600
LAST COMMIT2 months ago
@commitlint/cli (npm) ^20.4.3
@commitlint/config-conventional (npm) ^20.4.3
husky (npm) ^9.1.7
Files by Type (count)
TypeScript
224
Shell
105
Markdown
34
JSON
31
Other (.png)
17
YAML
14
Dockerfile
9
Other (no ext)
5
Other (.grit)
5
Lock File
3
Git Ignore
2
TOML
2
Files by Type (size)
TypeScript
2MB
Other (.png)
1MB
Shell
380KB
JSON
213KB
Lock File
161KB
Markdown
108KB
YAML
27KB
Other (no ext)
13KB
PowerShell
7KB
Other (.hcl)
5KB
Dockerfile
5KB
Other (.grit)
2KB

The LLM identified 6 files worth highlighting for reuse:

Result monad (Ok/Err) with tryCatch, asyncTryCatch, tryCatchIf, and withRetry utilities. Isolates error handling from business logic, distinguishes retryable errors (network timeouts, SSH failures) from non-retryable ones. Extractable and reusable in any TypeScript project needing resilient error handling.

file: packages/shared/src/result.ts ↗ | tags: #result-monad #functional-error-handling #retry-pattern

Centralized security validation using strict allowlist regex patterns for identifiers, IP addresses, SSH usernames, server IDs, launch commands, and shell scripts. Rejects null bytes, control characters, and path traversal. The `stripDangerousKeys` function prevents prototype pollution. Extractable as a standalone validation library.

file: packages/cli/src/security.ts ↗ | tags: #input-validation #allowlist #injection-prevention

Portable path resolution utilities (getSpawnDir, getCacheDir, getHistoryPath, getUserHome) with security checks: SPAWN_HOME must be absolute and within home directory, cache directories are validated and created with proper permissions. Extractable for any CLI tool needing secure path management.

file: packages/cli/src/shared/paths.ts ↗ | tags: #path-resolution #security-hardening #configuration-paths

JSON file-based history with schema versioning, atomic writes (tmp+rename), mkdir-based advisory file locking with stale PID recovery, and corruption recovery (automatic backup, archive recovery, per-record salvaging). Handles concurrent access and partial writes. Extractable as a general-purpose state persistence pattern.

file: packages/cli/src/history.ts ↗ | tags: #persistence #corruption-recovery #file-locking

SSH utility module with two-phase connection wait (TCP probe then SSH handshake), killWithTimeout (per-process timeout preventing hangs), pipe-draining to avoid buffer deadlocks, validateRemotePath for safe file paths, and consistent SSH option sets (SSH_BASE_OPTS, SSH_INTERACTIVE_OPTS). Extractable for any TypeScript project managing SSH connections.

file: packages/cli/src/shared/ssh.ts ↗ | tags: #ssh-execution #tcp-probe #interactive-session

Minimal, well-typed TypeScript type guard utilities (isString, isObject, isError) and valibot-based schema validation helpers (parseJsonWith, parseJsonObj). Used consistently across the entire codebase to replace unsafe casts with validated parsing. Extractable as a lightweight validation toolkit.

file: packages/shared/src/type-guards.ts ↗ | tags: #type-guards #validation #schema
Last analyzed: 2026-08-12 20:47:06.306566
Next check: 2026-08-19 20:47:06.300422
$ submit: