Local Development
SAM uses a Cloudflare-first development approach. Local development has significant limitations — no real OAuth, DNS, or VMs. For meaningful testing, deploy to staging.
Recommended Workflow
Section titled “Recommended Workflow”- Make changes locally — edit code, run lint and typecheck
- Deploy to staging — via the “Deploy Staging” GitHub Actions workflow or
pnpm deploy:staging - Test on Cloudflare — real D1, KV, Workers, DNS
- Merge to main — in the canonical repository, successful
mainCI triggers production deployment; in self-host forks, run Deploy Production manually when you want to update the instance
What Works Locally
Section titled “What Works Locally”For quick iteration on API logic, you can use Wrangler’s local emulator:
pnpm devThis starts:
- API at
http://localhost:8787(Wrangler with Miniflare) - Web UI at
http://localhost:5173(Vite dev server)
Limitations
Section titled “Limitations”| Feature | Local | Staging |
|---|---|---|
| GitHub OAuth | No (callbacks won’t work) | Yes |
| DNS/subdomains | No | Yes |
| VM provisioning | No | Yes |
| D1/KV/R2 | Emulated (may differ) | Real |
| Agent sessions | No | Yes |
Prerequisites
Section titled “Prerequisites”node --version # v20.x or higherpnpm --version # 9.x or higherGo 1.25+ is only needed if you’re working on the VM Agent (packages/vm-agent/).
1. Install Dependencies
Section titled “1. Install Dependencies”pnpm install2. Generate Development Keys
Section titled “2. Generate Development Keys”pnpm tsx scripts/deploy/generate-keys.tsThis generates ENCRYPTION_KEY, JWT_PRIVATE_KEY, and JWT_PUBLIC_KEY for local use.
3. Create .dev.vars
Section titled “3. Create .dev.vars”Create apps/api/.dev.vars with minimal configuration:
BASE_DOMAIN=localhost:8787ENCRYPTION_KEY=<from generate-keys>JWT_PRIVATE_KEY=<from generate-keys>JWT_PUBLIC_KEY=<from generate-keys>4. Run
Section titled “4. Run”pnpm devBuild & Test
Section titled “Build & Test”pnpm build # Build all packagespnpm test # Run testspnpm typecheck # Type checkpnpm lint # Lintpnpm format # FormatBuild Order
Section titled “Build Order”Packages must be built in dependency order:
pnpm --filter @simple-agent-manager/shared buildpnpm --filter @simple-agent-manager/providers buildpnpm --filter @simple-agent-manager/api buildOr use pnpm build from the root — Turborepo handles ordering.
Project Structure
Section titled “Project Structure”apps/├── api/ # Cloudflare Worker API (Hono)├── web/ # Control plane UI (React + Vite)├── www/ # Marketing site + docs (Astro)└── tail-worker/ # Log aggregation worker
packages/├── shared/ # Shared types and utilities├── providers/ # Cloud provider abstraction (Hetzner, Scaleway, GCP)├── cloud-init/ # Cloud-init template generator├── terminal/ # Shared terminal component (xterm.js)├── ui/ # Design system components└── vm-agent/ # Go VM agent (PTY, WebSocket, ACP)Staging Deployment
Section titled “Staging Deployment”For real testing, deploy to a staging environment:
# Via GitHub Actions (recommended)# Trigger the "Deploy Staging" workflow
# Or via CLIpnpm deploy:stagingStaging gives you the full Cloudflare stack: real D1, KV, Workers, DNS, and VM provisioning.