rdev/history/v0.2.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

5.6 KiB

rdev v0.2.0 - Real Workspaces

Date: 2026-01-24 Status: Ready for deployment (pending deploy keys)

Summary

Project-specific claudebox pods with real GitHub repository workspaces. Each project gets its own StatefulSet with an init container that clones the repo on first start.

What Was Built

Project-Specific StatefulSets

Two new claudebox deployments:

  • claudebox-pantheon - For the pantheon project
  • claudebox-aeries - For the aeries project

Each has:

  • Init container that clones repo via SSH
  • Persistent workspace (20Gi)
  • Persistent Claude config (1Gi)
  • SSH deploy keys for GitHub access
  • Project-specific CLAUDE.md via ConfigMap

Init Container Logic

# Setup SSH
mkdir -p /root/.ssh
cp /ssh-keys/id_ed25519 /root/.ssh/id_ed25519
chmod 600 /root/.ssh/id_ed25519

# Clone or fetch
if [ ! -d /workspace/.git ]; then
  git clone git@github.com:orchard9/${PROJECT}.git /workspace
else
  cd /workspace && git fetch origin
fi

Files Created

deployments/k8s/base/
├── claudebox-pantheon.yaml  # Pantheon StatefulSet
├── claudebox-aeries.yaml    # Aeries StatefulSet
├── pvc-pantheon.yaml        # Pantheon PVCs
├── pvc-aeries.yaml          # Aeries PVCs
├── configmaps.yaml          # Project CLAUDE.md files
└── secrets.yaml             # Deploy key secrets (template)

scripts/
└── generate-deploy-key.sh   # Deploy key generation helper

Kubernetes Resources

Resource Type Project
claudebox-pantheon StatefulSet pantheon
claudebox-aeries StatefulSet aeries
claudebox-pantheon-workspace PVC (20Gi) pantheon
claudebox-pantheon-claude-config PVC (1Gi) pantheon
claudebox-aeries-workspace PVC (20Gi) aeries
claudebox-aeries-claude-config PVC (1Gi) aeries
claudebox-pantheon-config ConfigMap pantheon
claudebox-aeries-config ConfigMap aeries
github-deploy-key-pantheon Secret pantheon
github-deploy-key-aeries Secret aeries

Deployment Instructions

1. Generate Deploy Keys

cd /path/to/rdev

# Generate key for pantheon
./scripts/generate-deploy-key.sh pantheon

# Generate key for aeries
./scripts/generate-deploy-key.sh aeries

2. Add Public Keys to GitHub

For each project:

  1. Go to https://github.com/orchard9/<project>/settings/keys
  2. Click "Add deploy key"
  3. Title: rdev-<project>
  4. Paste contents of <project>-deploy-key.pub
  5. Check "Allow write access" (needed for v0.3)

3. Update Secrets

Edit deployments/k8s/base/secrets.yaml:

  • Replace REPLACE_WITH_BASE64_ENCODED_PRIVATE_KEY with contents of <project>-deploy-key.b64

4. Deploy

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

5. Verify

# Check pods
kubectl get pods -n rdev
# Should show: claudebox-pantheon-0, claudebox-aeries-0

# Check init container logs
kubectl logs -n rdev claudebox-pantheon-0 -c git-clone

# Verify repo was cloned
kubectl exec -n rdev claudebox-pantheon-0 -- ls /workspace
kubectl exec -n rdev claudebox-pantheon-0 -- git -C /workspace status

# Authenticate Claude (first time only)
kubectl exec -it -n rdev claudebox-pantheon-0 -- claude

Key Decisions

1. Reuse claudebox image for init container

  • Same image has git installed
  • No need for separate alpine/git image
  • Simpler to maintain

2. SSH Deploy Keys vs HTTPS PAT

  • SSH deploy keys are per-repo (more secure)
  • Aligns with v0.3 requirements (push access)
  • GitHub deploy keys can have write access

3. ConfigMap for CLAUDE.md

  • Allows customizing Claude behavior per project
  • Mounted at /workspace/CLAUDE.md
  • Can be updated without rebuilding image

4. Keep generic claudebox from v0.1

  • Useful for testing/development
  • No project-specific config required
  • Can be used as template

Architecture

rdev namespace
├── claudebox-0 (v0.1 - generic)
│   └── /workspace (empty, for testing)
│
├── claudebox-pantheon-0 (v0.2)
│   ├── /workspace (pantheon repo)
│   ├── /root/.claude (Claude auth)
│   └── /root/.ssh (deploy key)
│
└── claudebox-aeries-0 (v0.2)
    ├── /workspace (aeries repo)
    ├── /root/.claude (Claude auth)
    └── /root/.ssh (deploy key)

What's Next (v0.3)

  1. Git config (user.name, user.email) for commits
  2. Test git push from inside pod
  3. Proper SSH key mounting for main container (currently init-only)

Commands Reference

# Set kubeconfig
export KUBECONFIG=~/.kube/orchard9-k3sf.yaml

# Deploy
kubectl apply -k deployments/k8s/base

# Check status
kubectl get pods -n rdev
kubectl get pvc -n rdev

# View init container logs
kubectl logs -n rdev claudebox-pantheon-0 -c git-clone

# Interactive Claude session
kubectl exec -it -n rdev claudebox-pantheon-0 -- claude

# Run Claude with prompt
kubectl exec -it -n rdev claudebox-pantheon-0 -- claude "what files are in this project?"

# Git status
kubectl exec -n rdev claudebox-pantheon-0 -- git -C /workspace status

# Shell access
kubectl exec -it -n rdev claudebox-pantheon-0 -- bash

Troubleshooting

Init container fails with "Permission denied (publickey)"

  • Verify deploy key is added to GitHub
  • Check secret has correct base64-encoded private key
  • Ensure known_hosts includes github.com

Workspace is empty after pod starts

  • Check init container logs: kubectl logs -n rdev <pod> -c git-clone
  • Verify SSH key permissions (should be 600)

Claude auth not persisting

  • Check PVC is bound: kubectl get pvc -n rdev
  • Verify claude-config volume is mounted at /root/.claude