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>
260 lines
8.0 KiB
Markdown
260 lines
8.0 KiB
Markdown
# 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
|
|
|
|
```yaml
|
|
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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
export KUBECONFIG=~/.kube/orchard9-k3sf.yaml
|
|
kubectl apply -k deployments/k8s/base
|
|
```
|
|
|
|
### 4. Verify
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```javascript
|
|
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
|
|
|
|
```bash
|
|
curl -X POST http://rdev-api.rdev.svc:8080/projects/pantheon/shell \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"command": "go test ./..."}'
|
|
```
|
|
|
|
### Run Git Command
|
|
|
|
```bash
|
|
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
|