rdev/history/v0.4.0.md
jordan 0960b17eb2 feat: Implement v0.2-v0.4 (workspaces, git, API)
v0.2 - Real Workspaces:
- Project-specific claudebox StatefulSets (pantheon, aeries)
- Init containers for git clone via SSH
- Deploy key secrets template
- Project ConfigMaps for CLAUDE.md

v0.3 - Git Integration:
- Dockerfile with rdev-bot git identity
- openssh-client for SSH operations
- Image version bump to v0.3.0

v0.4 - API Server:
- Go REST API with chi router
- Endpoints: /projects, /claude, /shell, /git, /events
- SSE streaming for real-time output
- OpenAPI docs via Scalar at /docs
- Kubernetes RBAC for pod exec
- Executor and project registry packages

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 21:07:00 -07:00

8.0 KiB

rdev v0.4.0 - API Server

Date: 2026-01-24 Status: Ready for deployment

Summary

Go REST API server for controlling claudebox pods. External clients (Discord bots, CLI tools, etc.) can now interact with Claude Code via HTTP endpoints with SSE streaming for real-time output.

What Was Built

Go API Server (rdev-api)

A chi-based HTTP server with:

  • Project discovery and status
  • Command execution (claude, shell, git)
  • SSE streaming for real-time output
  • OpenAPI documentation via Scalar

API Endpoints

Method Path Description
GET /health Health check
GET /ready Readiness check
GET /docs Scalar API documentation
GET /openapi.json OpenAPI 3.0 specification
GET /projects List available projects
GET /projects/{id} Get project details
POST /projects/{id}/claude Run Claude command
POST /projects/{id}/shell Run shell command
POST /projects/{id}/git Run git command
GET /projects/{id}/events SSE stream for output

Packages Created

cmd/rdev-api/
└── main.go              # Entry point, OpenAPI spec

pkg/api/
├── app.go               # HTTP server chassis
├── response.go          # JSON response helpers
└── openapi.go           # OpenAPI spec builder

internal/
├── handlers/
│   └── projects.go      # HTTP handlers + SSE streaming
├── executor/
│   └── executor.go      # kubectl exec wrapper
└── projects/
    └── registry.go      # Project discovery

Kubernetes Resources

  • Deployment: rdev-api - Single replica
  • Service: rdev-api - ClusterIP on port 8080
  • ServiceAccount: rdev-api
  • Role/RoleBinding: Permissions for pod exec

RBAC Permissions

rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get"]

Files Created

Dockerfile.api                         # API server image
cmd/rdev-api/main.go                   # Entry point
pkg/api/app.go                         # HTTP chassis
pkg/api/response.go                    # Response helpers
pkg/api/openapi.go                     # OpenAPI builder
internal/handlers/projects.go          # Handlers + SSE
internal/executor/executor.go          # kubectl exec
internal/projects/registry.go          # Project registry
deployments/k8s/base/rdev-api.yaml     # Deployment + Service
deployments/k8s/base/rbac.yaml         # RBAC
go.mod, go.sum                         # Go modules

Dependencies

github.com/go-chi/chi/v5         # HTTP router
github.com/bdpiprava/scalar-go   # API documentation

Deployment Instructions

1. Build Images

cd /path/to/rdev

# Build both claudebox and api images
./scripts/build-push.sh v0.4.0

# Or just the api
./scripts/build-push.sh v0.4.0 api

2. Complete Prerequisites

Ensure v0.2 and v0.3 are deployed:

  • Deploy keys configured for projects
  • Secrets updated with base64 private keys
  • claudebox image v0.3.0 with git config

3. Deploy

export KUBECONFIG=~/.kube/orchard9-k3sf.yaml
kubectl apply -k deployments/k8s/base

4. Verify

# Check API is running
kubectl get pods -n rdev -l app=rdev-api

# Port forward for testing
kubectl port-forward -n rdev svc/rdev-api 8080:8080

# Test health endpoint
curl http://localhost:8080/health

# Test projects list
curl http://localhost:8080/projects

# Test Claude command
curl -X POST http://localhost:8080/projects/pantheon/claude \
  -H "Content-Type: application/json" \
  -d '{"prompt": "what files are in this project?"}'

# View API docs
open http://localhost:8080/docs

Usage Examples

Run Claude Command

# Start command
curl -X POST http://rdev-api.rdev.svc:8080/projects/pantheon/claude \
  -H "Content-Type: application/json" \
  -d '{"prompt": "fix the bug in auth handler"}'

# Response
{
  "data": {
    "id": "cmd-pantheon-001",
    "project": "pantheon",
    "type": "claude",
    "status": "running",
    "stream_url": "/projects/pantheon/events?stream_id=cmd-pantheon-001"
  },
  "meta": {"request_id": "...", "timestamp": "..."}
}

Stream Output (SSE)

const events = new EventSource(
  'http://rdev-api.rdev.svc:8080/projects/pantheon/events?stream_id=cmd-pantheon-001'
);

events.addEventListener('output', (e) => {
  const data = JSON.parse(e.data);
  console.log(`[${data.stream}] ${data.line}`);
});

events.addEventListener('complete', (e) => {
  const data = JSON.parse(e.data);
  console.log(`Done: exit=${data.exit_code}, ${data.duration_ms}ms`);
  events.close();
});

Run Shell Command

curl -X POST http://rdev-api.rdev.svc:8080/projects/pantheon/shell \
  -H "Content-Type: application/json" \
  -d '{"command": "go test ./..."}'

Run Git Command

curl -X POST http://rdev-api.rdev.svc:8080/projects/pantheon/git \
  -H "Content-Type: application/json" \
  -d '{"args": ["status"]}'

Architecture

┌─────────────────────────────────────────────────────────────┐
│                       rdev namespace                         │
│                                                              │
│  ┌──────────────┐                                           │
│  │  rdev-api    │                                           │
│  │  (Go server) │                                           │
│  │              │                                           │
│  │  /projects   │  kubectl exec                             │
│  │  /claude     │─────────────────┐                         │
│  │  /shell      │                 │                         │
│  │  /git        │                 ▼                         │
│  │  /events     │  ┌──────────────────────────────────────┐ │
│  └──────────────┘  │         claudebox pods               │ │
│                    │                                      │ │
│                    │  ┌────────────────┐ ┌──────────────┐ │ │
│                    │  │claudebox-      │ │claudebox-    │ │ │
│                    │  │pantheon-0      │ │aeries-0      │ │ │
│                    │  │                │ │              │ │ │
│                    │  │ Claude Code    │ │ Claude Code  │ │ │
│                    │  │ /workspace     │ │ /workspace   │ │ │
│                    │  └────────────────┘ └──────────────┘ │ │
│                    └──────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

What's Next (v0.5)

Enhanced SSE streaming:

  • Output buffering and chunking
  • Connection management (heartbeats, reconnection)
  • Event filtering by stream_id
  • Better error handling

Troubleshooting

API returns 404 for project

  • Check project registry includes the project
  • Verify claudebox pod exists: kubectl get pods -n rdev

Commands fail with "permission denied"

  • Check RBAC is applied: kubectl get role rdev-api -n rdev
  • Verify ServiceAccount is bound: kubectl get rolebinding rdev-api -n rdev

SSE not receiving events

  • Ensure stream_id matches the command ID
  • Check for Connection: keep-alive in client
  • Verify no proxy is buffering responses