Skip to content

raphaeltm/simple-agent-manager

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

12 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Simple Agent Manager

Simple Agent Manager (SAM) - Spin up AI coding environments on-demand. Zero cost when idle.

Quick Start β€’ Features β€’ Documentation β€’ Roadmap β€’ Contributing

License


Simple Agent Manager (SAM) is a serverless platform for creating ephemeral cloud development environments optimized for Claude Code. Point it at any GitHub repository and get a fully configured workspace with Claude Code pre-installedβ€”accessible from your browser in minutes.

Think GitHub Codespaces, but built for AI-assisted development and with automatic shutdown to eliminate surprise bills.

WARNING this thing is fully vibe coded, with some code review, but not a lot yet. It has not yet beeen tested, so you should not use it at the moment.

Why Simple Agent Manager?

GitHub Codespaces Simple Agent Manager
Cost $0.18–$0.36/hour ~$0.07–$0.15/hour
Idle shutdown Manual or 30min timeout Automatic with PTY activity tracking
Claude Code Manual setup required Pre-installed and optimized
Private repos Native GitHub support GitHub App integration
Control plane Managed Self-hosted (free tier)

Key Differentiators

  • 2-3x cheaper than hosted alternatives using Hetzner Cloud VMs
  • Smart idle detection β€” tracks terminal activity to prevent premature shutdown
  • Zero ongoing cost β€” VMs self-terminate, control plane runs on Cloudflare's free tier
  • Claude Code first β€” pre-installed, session persistence, MCP server support
  • Private repository support β€” secure GitHub App integration for your org

Features

  • Instant Workspaces β€” Create a cloud VM from any Git repository in minutes
  • Web Terminal β€” Access via browser-based xterm.js terminal with WebSocket connection
  • DevContainer Support β€” Automatically detects and uses your .devcontainer/devcontainer.json
  • Multiple VM Sizes β€” Small (2 vCPU/4GB), Medium (4 vCPU/8GB), Large (8 vCPU/16GB)
  • Automatic Cleanup β€” Idle workspaces shut down after configurable inactivity (default 30 minutes)
  • GitHub Integration β€” Works with both public and private repositories

Quick Start

Prerequisites

Installation

# Clone the repository
git clone https://github.com/YOUR_ORG/simple-agent-manager.git
cd simple-agent-manager

# Install dependencies
pnpm install

# Copy environment template
cp .env.example .env
# Edit .env with your API tokens and domain

Configuration (Local Development)

Create your .env file with the following.

Note: These GITHUB_* names are for local .env files only. For GitHub Actions deployment, use GH_* prefix in GitHub Environment secrets (e.g., GH_CLIENT_ID instead of GITHUB_CLIENT_ID). The deployment workflow maps between them automatically.

# Cloudflare (for DNS and hosting)
CF_API_TOKEN=your-cloudflare-api-token
CF_ZONE_ID=your-zone-id
CF_ACCOUNT_ID=your-account-id

# Domain for workspace URLs (e.g., workspaces.example.com)
BASE_DOMAIN=example.com

# GitHub OAuth (create at https://github.com/settings/developers)
GITHUB_CLIENT_ID=your-github-oauth-client-id
GITHUB_CLIENT_SECRET=your-github-oauth-client-secret

# GitHub App (create at https://github.com/settings/apps)
GITHUB_APP_ID=your-github-app-id
GITHUB_APP_PRIVATE_KEY=your-github-app-private-key-base64
GITHUB_APP_SLUG=your-github-app-slug

# JWT Keys (generate with: tsx scripts/deploy/generate-keys.ts)
JWT_PRIVATE_KEY=your-jwt-private-key-base64
JWT_PUBLIC_KEY=your-jwt-public-key-base64

# Encryption key for credential storage (32 bytes, base64)
ENCRYPTION_KEY=your-encryption-key-base64

Note: Run tsx scripts/deploy/generate-keys.ts to generate JWT and encryption keys. User Hetzner tokens are stored encrypted per-user, not as environment variables.

Development

# Start development servers (API + Web UI)
pnpm dev

# Run tests
pnpm test

# Type checking
pnpm typecheck

# Build for production
pnpm build

Deployment

Continuous Deployment: Merge to main automatically deploys to production.

Before your first deployment, configure the GitHub Environment:

  1. Go to Settings β†’ Environments β†’ New environment
  2. Create environment named production
  3. Add required variables and secrets (see CLAUDE.md for full list):
    • Variables: BASE_DOMAIN
    • Secrets: CF_API_TOKEN, CF_ACCOUNT_ID, CF_ZONE_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, PULUMI_CONFIG_PASSPHRASE, GH_CLIENT_ID, GH_CLIENT_SECRET, GH_APP_ID, GH_APP_PRIVATE_KEY, GH_APP_SLUG

Then push to main or manually trigger the Deploy workflow.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Your Browser                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Cloudflare Pages (UI)                         β”‚
β”‚                      React + Vite                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  Cloudflare Workers (API)                        β”‚
β”‚                     Hono + TypeScript                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Workspace   β”‚    GitHub    β”‚     DNS      β”‚  Cloud-Init  β”‚  β”‚
β”‚  β”‚   Service    β”‚   Service    β”‚   Service    β”‚  Generator   β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           β”‚                β”‚                β”‚
           β–Ό                β–Ό                β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  Hetzner   β”‚   β”‚   GitHub   β”‚   β”‚ Cloudflare β”‚
    β”‚   Cloud    β”‚   β”‚    API     β”‚   β”‚    DNS     β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
           β”‚
           β–Ό
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚            Hetzner Cloud VM                  β”‚
    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
    β”‚  β”‚  Docker + DevContainer               β”‚    β”‚
    β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚    β”‚
    β”‚  β”‚  β”‚         Your Code             β”‚  β”‚    β”‚
    β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚    β”‚
    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
    β”‚  β”‚  VM Agent (Go)                       β”‚    β”‚
    β”‚  β”‚  β€’ WebSocket terminal (xterm.js)    β”‚    β”‚
    β”‚  β”‚  β€’ JWT authentication               β”‚    β”‚
    β”‚  β”‚  β€’ Idle detection + auto-shutdown   β”‚    β”‚
    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Project Structure

apps/
β”œβ”€β”€ api/              # Cloudflare Worker API (Hono)
β”‚   └── src/
β”‚       β”œβ”€β”€ routes/       # API endpoints
β”‚       β”œβ”€β”€ services/     # Business logic
β”‚       └── db/           # Database schema and migrations
└── web/              # Control Plane UI (React + Vite)
    └── src/
        β”œβ”€β”€ pages/        # Dashboard views
        β”œβ”€β”€ components/   # UI components
        └── services/     # API client

packages/
β”œβ”€β”€ shared/           # Shared types and validation
β”œβ”€β”€ providers/        # Cloud provider abstraction
β”œβ”€β”€ cloud-init/       # VM cloud-init template generation
β”œβ”€β”€ terminal/         # Shared terminal component (xterm.js + WebSocket)
└── vm-agent/         # Go agent for WebSocket terminal + idle detection

scripts/
β”œβ”€β”€ vm/               # VM-side config templates (cloud-init.yaml, default-devcontainer.json)
└── deploy/           # Deployment utilities
    β”œβ”€β”€ generate-keys.ts    # Generate JWT and encryption keys
    β”œβ”€β”€ setup-github.ts     # GitHub App setup
    β”œβ”€β”€ setup-local-dev.ts  # Local development setup
    └── run-migrations.ts   # Database migrations

infra/                # Pulumi infrastructure as code
specs/                # Feature specifications
docs/                 # Documentation

API Reference

Authentication

Endpoint Method Description
/api/auth/* * BetterAuth authentication routes
/api/auth/me GET Get current user

Credentials

Endpoint Method Description
/api/credentials GET List credentials
/api/credentials POST Create/update credential
/api/credentials/:provider DELETE Delete credential

GitHub

Endpoint Method Description
/api/github/installations GET List GitHub App installations
/api/github/install-url GET Get GitHub App install URL
/api/github/repositories GET List accessible repositories
/api/github/webhook POST GitHub webhook handler
/api/github/callback GET GitHub App OAuth callback

Workspaces

Endpoint Method Description
/api/workspaces GET List user's workspaces
/api/workspaces POST Create a new workspace
/api/workspaces/:id GET Get workspace details
/api/workspaces/:id DELETE Delete workspace
/api/workspaces/:id/stop POST Stop workspace
/api/workspaces/:id/restart POST Restart workspace
/api/workspaces/:id/ready POST VM ready callback
/api/workspaces/:id/heartbeat POST VM heartbeat

Terminal

Endpoint Method Description
/api/terminal/token POST Get terminal access token
/.well-known/jwks.json GET JWKS for JWT verification

VM Agent

Endpoint Method Description
/api/agent/download GET Download VM agent binary (query: os, arch)
/api/agent/version GET Get current agent version
/api/agent/install-script GET Get VM agent install script

Bootstrap (VM Credential Delivery)

Endpoint Method Description
/api/bootstrap/:token POST Redeem one-time bootstrap token for credentials

Authentication is session-based via cookies (BetterAuth + GitHub OAuth).

Security

Secure Credential Delivery (Bootstrap Tokens)

VMs receive credentials securely using one-time bootstrap tokens:

  1. Workspace creation: API generates a one-time bootstrap token stored in KV with 5-minute TTL
  2. Cloud-init: VM receives only the bootstrap URL (no embedded secrets)
  3. VM startup: VM agent calls POST /api/bootstrap/:token to redeem credentials
  4. Token invalidation: Token is deleted immediately after first use

This ensures:

  • No sensitive tokens in cloud-init user data (visible in Hetzner console)
  • Single-use tokens prevent replay attacks
  • Short TTL limits exposure window

Workspace Access Control

All workspace operations validate ownership to prevent IDOR attacks:

  • Non-owners receive 404 Not Found (not 403 Forbidden) to prevent information disclosure
  • Workspace lists are filtered by authenticated user
  • Terminal WebSocket tokens are scoped to workspace owner

Use Cases

Instant Prototyping

Spin up a workspace to try a new library without polluting your local environment. Claude Code is ready to help you explore and implement.

# Create workspace via web UI or API
# Authentication is handled via GitHub OAuth session
curl -X POST https://api.example.com/api/workspaces \
  -H "Content-Type: application/json" \
  --cookie "session=..." \
  -d '{"name": "my-workspace", "repository": "user/repo", "installationId": "...", "vmSize": "medium"}'

Private Codebase Development

Connect your GitHub organization, create workspaces from private repositories, and let Claude help with refactoring while keeping everything in ephemeral environments.

Team Onboarding

New team members can spin up fully configured development environments in minutesβ€”no local setup required.

Roadmap

Phase Target Features
1. MVP Complete Core workspace management, GitHub OAuth, auto-shutdown
2. Browser Terminal Current Web terminal, VM agent, idle detection
3. Enhanced UX Q1 2026 Logs, SSH access, templates, persistent storage
4. Multi-Tenancy Q2 2026 Teams, usage quotas, billing
5. Enterprise Q3 2026 VPC, SSO, compliance, multi-region

See ROADMAP.md for details.

Tech Stack

Component Technology
API Runtime Cloudflare Workers
API Framework Hono
Web UI React + Vite
Cloud Provider Hetzner Cloud
DNS Cloudflare DNS
Data Storage Cloudflare D1 (database) + KV (sessions) + R2 (binaries)
Testing Vitest + Miniflare
Monorepo pnpm + Turborepo

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for guidelines.

# Setup development environment
pnpm install

# Run tests before submitting
pnpm test
pnpm typecheck

# Format code
pnpm format

Related Projects

  • DevPod β€” Client-only devcontainer management
  • Coder β€” Self-hosted cloud development environments
  • Daytona β€” Open source dev environment manager

License

MIT


Built with Hono on Cloudflare

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •