# 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

```bash
# 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

```bash
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

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

### 5. Verify

```bash
# 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

```bash
# 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
