Skip to content

Latest commit

 

History

History
572 lines (437 loc) · 15.7 KB

File metadata and controls

572 lines (437 loc) · 15.7 KB

spark-sandbox - TODOs

Dotfiles Integration

Goal: Pull shell configurations, aliases, and customizations from a GitHub dotfiles repo for personalized dev environments.

Research & Design

Modern dotfiles practices to implement:

  • Use chezmoi or yadm for dotfiles management - Using chezmoi
  • Support multiple dotfile sources (user's repo, org defaults, local overrides) - future enhancement
  • Integrate with Oh My Posh for cross-shell prompt theming - future enhancement
  • Template-based configs with machine-specific variables - chezmoi supports this natively
  • Secret management (API keys, tokens) via 1Password CLI, Bitwarden, or encrypted files - future enhancement

Implementation

Status: Core implementation COMPLETE (2026-01-23)

Requirements:

  • Add DOTFILES_REPO environment variable support (e.g., ghcr.io/user/dotfiles)
  • Auto-clone dotfiles repo on first container start (entrypoint.sh)
  • Support both HTTPS and SSH clone methods
  • Install chezmoi in base images for dotfiles management
  • Add box new --dotfiles=github.com/user/dotfiles flag
  • Create default spark-sandbox dotfiles repo with:
    • Oh My Posh themes (works in zsh, bash, fish, powershell)
    • Cross-platform aliases (using shell-agnostic syntax)
    • Git aliases and config
    • Tool-specific configs (tmux, neovim, etc.)
  • Support .chezmoiexternal.toml for pulling external deps (chezmoi handles this natively)

Integration Points

# ~/.config/spark-sandbox/config.yaml
dotfiles:
  repo: "github.com/myuser/dotfiles"
  branch: "main"
  manager: "chezmoi"  # or "yadm", "stow", "bare-git"
  auto_apply: true
# CLI support
box new myapp --dotfiles=github.com/user/dotfiles
box dotfiles apply myapp   # Re-apply dotfiles
box dotfiles edit myapp    # Edit dotfiles in sandbox

TDD Tests

# Test: Dotfiles flag works
box new dotfiles-test --dotfiles=github.com/spark-sandbox/dotfiles
box exec dotfiles-test cat ~/.config/chezmoi/chezmoi.toml
# Expected: Shows chezmoi config pointing to repo

# Test: Oh My Posh theme applied
box exec dotfiles-test oh-my-posh --version
# Expected: Version number

# Test: Custom aliases available
box exec dotfiles-test type ll
# Expected: ll is aliased to...

Custom Desktop Image

Create Dockerfile.desktop extending webtop with our full dev environment, matching the capabilities of our base/agent images but with a full KDE GUI.

Status: Stages 1-4 COMPLETE (2026-01-22). Desktop image builds and includes:

  • ✓ zsh + Oh My Zsh + Powerlevel10k (via init script on first run)
  • ✓ Go 1.23.5, Node 24.x, Python 3.12, Rust 1.93
  • ✓ Claude Code 2.1.17
  • ✓ All modern CLI tools (ripgrep, fd-find, lsd, zoxide, etc.)
  • ✓ GPU passthrough enabled

Stage 1: Base Desktop Build ✓ COMPLETE

Goal: Create Dockerfile.desktop that builds successfully

# Target structure
FROM lscr.io/linuxserver/webtop:ubuntu-kde
# Install our full dev stack
# Configure zsh as default shell
# Add Claude Code

TDD Test:

# Build succeeds
docker build -t spark-sandbox:desktop -f docker/Dockerfile.desktop docker/
echo $?  # Expected: 0

# Image exists
docker images | grep "spark-sandbox.*desktop"
# Expected: spark-sandbox desktop <hash> <size>

Stage 2: Shell Environment ✓ COMPLETE

Goal: zsh with Oh My Zsh and Powerlevel10k working in GUI terminal

Requirements:

  • Install zsh
  • Install Oh My Zsh for the abc user (webtop default user)
  • Install Powerlevel10k theme
  • Copy our configs: zshrc, p10k.zsh, zshenv
  • Set zsh as default shell for abc user
  • Configure Konsole/terminal to use zsh (optional - uses webtop default)

TDD Test:

box new desktop-test --template=desktop

# Test: Default shell is zsh
box exec desktop-test cat /etc/passwd | grep abc
# Expected: abc:x:1000:1000::/config:/bin/zsh

# Test: Oh My Zsh installed
box exec desktop-test ls /config/.oh-my-zsh
# Expected: Directory listing (not error)

# Test: Powerlevel10k installed
box exec desktop-test ls /config/.oh-my-zsh/custom/themes/powerlevel10k
# Expected: Directory listing

# Test: Our configs present
box exec desktop-test cat /config/.zshrc | grep powerlevel10k
# Expected: ZSH_THEME="powerlevel10k/powerlevel10k"

# Test: PATH configured
box exec desktop-test zsh -c 'echo $PATH' | grep -E "(go|node|cargo)"
# Expected: Paths containing go, node, cargo

box rm desktop-test -f

Stage 3: Development Tools ✓ COMPLETE

Goal: Full dev toolchain matching base image

Requirements:

  • Go (latest stable) - 1.23.5
  • Node.js via fnm (latest LTS) - v24.13.0
  • Python 3 with pip - 3.12.3 (via UV)
  • Rust via rustup - 1.93.0
  • Common tools: git, curl, wget, jq, tree, ripgrep, fd-find (fdfind on Ubuntu)

TDD Test:

box new desktop-test --template=desktop

# Test: Go installed
box exec desktop-test go version
# Expected: go version go1.x.x linux/arm64

# Test: Node installed
box exec desktop-test node --version
# Expected: v2x.x.x

# Test: Python installed
box exec desktop-test python3 --version
# Expected: Python 3.x.x

# Test: Rust installed
box exec desktop-test rustc --version
# Expected: rustc 1.x.x

# Test: Common tools
box exec desktop-test which git curl jq tree rg fd
# Expected: Paths for all tools

box rm desktop-test -f

Stage 4: Claude Code Integration ✓ COMPLETE

Goal: Claude Code CLI installed and working

Requirements:

  • Install Claude Code via npm - v2.1.17
  • Ensure claude command is in PATH
  • Test OAuth session mounting works (CLI updated for desktop template)

TDD Test:

box new desktop-test --template=desktop

# Test: Claude installed
box exec desktop-test which claude
# Expected: /path/to/claude

# Test: Claude runs
box exec desktop-test claude --version
# Expected: x.x.x (Claude Code)

# Test: Claude accessible from zsh
box exec desktop-test zsh -c 'claude --version'
# Expected: x.x.x (Claude Code)

box rm desktop-test -f

Stage 5: GUI Applications (OPTIONAL - Future Enhancement)

Goal: Essential GUI apps for development

Note: Webtop comes with pre-installed apps (Firefox, Kate editor). This stage is for adding VS Code.

Requirements:

  • VS Code or code-server (browser-based) - optional, Kate works fine
  • Configure Konsole terminal defaults (zsh, font, colors) - uses webtop defaults
  • File manager configured for dev work - Dolphin included
  • Optional: Firefox/Chromium for web testing - Firefox included

TDD Test:

box new desktop-test --template=desktop

# Test: VS Code/code-server available
box exec desktop-test which code || box exec desktop-test which code-server
# Expected: Path to editor

# Test: Konsole config exists
box exec desktop-test ls /config/.local/share/konsole/
# Expected: Profile config files

box rm desktop-test -f

Stage 6: GPU Passthrough ✓ COMPLETE (Auto-enabled)

Goal: Hardware acceleration works for GUI

GPU passthrough is auto-enabled for desktop template in manager.go

Requirements:

  • NVIDIA GPU passthrough configured (--gpus all in container config)
  • OpenGL/Vulkan working in container (requires manual test)
  • GPU visible in desktop environment (requires manual test)

TDD Test:

box new desktop-test --template=desktop

# Test: GPU visible
box exec desktop-test nvidia-smi
# Expected: GPU info table

# Test: OpenGL works
box exec desktop-test glxinfo | head -5
# Expected: OpenGL vendor/renderer info

box rm desktop-test -f

Stage 7: Full Integration

Goal: Complete desktop experience via Tailscale Funnel

TDD Test:

# Create desktop sandbox
box new mydesktop --template=desktop

# Expose via Tailscale
box expose mydesktop 3000

# Verify funnel active
tailscale funnel status
# Expected: Shows https://spark.burbot-hops.ts.net proxying to localhost

# Manual test in browser:
# 1. Open https://spark.burbot-hops.ts.net
# 2. KDE desktop loads
# 3. Open Konsole - zsh with p10k prompt
# 4. Run: claude --version - works
# 5. Run: go version, node -v, python3 -V - all work

# Cleanup
tailscale funnel off
box rm mydesktop -f

Polish

Shell Completions ✓ COMPLETE

Goal: Tab completion for box command in all major shells

Requirements:

  • Generate bash completions - box completion bash
  • Generate zsh completions - box completion zsh
  • Generate fish completions - box completion fish
  • Generate powershell completions - box completion powershell
  • Add install instructions to README (see box completion --help)
  • Auto-install during make install (optional - future enhancement)

Implementation:

// Cobra has built-in completion generation
// cmd/box/main.go or internal/cli/root.go

rootCmd.AddCommand(&cobra.Command{
    Use:   "completion [bash|zsh|fish]",
    Short: "Generate shell completions",
    // ...
})

TDD Test:

# Test: Completion command exists
box completion --help
# Expected: Usage info

# Test: Generate bash completion
box completion bash > /tmp/box.bash
cat /tmp/box.bash | head -5
# Expected: Bash completion script

# Test: Generate zsh completion
box completion zsh > /tmp/box.zsh
cat /tmp/box.zsh | head -5
# Expected: Zsh completion script

# Test: Completions work (manual)
source /tmp/box.bash
box <TAB><TAB>
# Expected: Shows available commands

Integration Test Script ✓ COMPLETE

Goal: Automated test suite for CI/CD

File: scripts/integration-test.sh - Run with ./scripts/integration-test.sh

All tests passing:

  • Docker images (base, agent, web, desktop)
  • CLI and completions
  • Container lifecycle (create, list, stop, start, remove)
  • Exec and persistence
  • All templates (base, agent, web, desktop)
  • Port allocation
#!/bin/bash
set -euo pipefail

RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'

pass() { echo -e "${GREEN}$1${NC}"; }
fail() { echo -e "${RED}$1${NC}"; exit 1; }

echo "=== spark-sandbox Integration Tests ==="
echo ""

# Test: Docker images exist
echo "Checking Docker images..."
docker images | grep -q "spark-sandbox.*base" && pass "Base image exists" || fail "Base image missing"
docker images | grep -q "spark-sandbox.*agent" && pass "Agent image exists" || fail "Agent image missing"
docker images | grep -q "spark-sandbox.*web" && pass "Web image exists" || fail "Web image missing"

# Test: CLI works
echo ""
echo "Checking CLI..."
box --version >/dev/null 2>&1 && pass "CLI runs" || fail "CLI broken"

# Test: Container lifecycle
echo ""
echo "Testing container lifecycle..."
box new integration-test >/dev/null 2>&1 && pass "Create sandbox" || fail "Create failed"
box ls | grep -q integration-test && pass "List sandbox" || fail "List failed"
box stop integration-test >/dev/null 2>&1 && pass "Stop sandbox" || fail "Stop failed"
box start integration-test >/dev/null 2>&1 && pass "Start sandbox" || fail "Start failed"
box rm integration-test -f >/dev/null 2>&1 && pass "Remove sandbox" || fail "Remove failed"

# Test: SSH connectivity
echo ""
echo "Testing SSH..."
box new ssh-test >/dev/null 2>&1
SHELL_OUT=$(box ssh ssh-test -c 'echo $SHELL' 2>/dev/null)
[[ "$SHELL_OUT" == *"/bin/zsh"* ]] && pass "SSH works, zsh shell" || fail "SSH failed"
box rm ssh-test -f >/dev/null 2>&1

# Test: Exec command
echo ""
echo "Testing exec..."
box new exec-test >/dev/null 2>&1
USER_OUT=$(box exec exec-test whoami 2>/dev/null)
[[ "$USER_OUT" == *"dev"* ]] && pass "Exec works, correct user" || fail "Exec failed"
box rm exec-test -f >/dev/null 2>&1

# Test: Data persistence
echo ""
echo "Testing persistence..."
box new persist-test >/dev/null 2>&1
box exec persist-test touch /home/dev/test.txt >/dev/null 2>&1
box stop persist-test >/dev/null 2>&1
box start persist-test >/dev/null 2>&1
box exec persist-test ls /home/dev/test.txt >/dev/null 2>&1 && pass "Data persists" || fail "Persistence failed"
box rm persist-test -f >/dev/null 2>&1

# Test: Templates
echo ""
echo "Testing templates..."
box new agent-test --template=agent >/dev/null 2>&1
box exec agent-test which claude >/dev/null 2>&1 && pass "Agent template has Claude" || fail "Agent template broken"
box rm agent-test -f >/dev/null 2>&1

box new web-test --template=web >/dev/null 2>&1
box exec web-test which vite >/dev/null 2>&1 && pass "Web template has Vite" || fail "Web template broken"
box rm web-test -f >/dev/null 2>&1

echo ""
echo -e "${GREEN}=== All tests passed! ===${NC}"

TDD Test:

# Make executable
chmod +x scripts/integration-test.sh

# Run tests
./scripts/integration-test.sh
# Expected: All green checkmarks, exit code 0

Documentation ✓ COMPLETE

Goal: Complete README and inline docs

Requirements:

  • README.md covers all features
  • Command examples for each subcommand
  • Troubleshooting section
  • Architecture overview
  • Contributing guidelines (future enhancement)

Error Handling ✓ COMPLETE

Goal: User-friendly error messages

Requirements:

  • Docker not running → clear message with fix
  • Image not built → suggest box build <template>
  • Port conflict → show how to free ports
  • Tailscale not installed → installation instructions
  • Sandbox not found → suggest creating or listing
  • SSH/Claude/Docker not found → installation instructions

Future Enhancements

Resource Limits

Goal: Control CPU/memory per sandbox

box new heavy-task --cpu=4 --memory=8g
box new lightweight --cpu=1 --memory=1g

Requirements:

  • Add --cpu flag to box new
  • Add --memory flag to box new
  • Store limits in container labels
  • Show limits in box ls output

Backup/Restore

Goal: Save and restore sandbox state

box backup myapp                    # Creates myapp-2024-01-22.tar.gz
box restore myapp-2024-01-22.tar.gz # Restores to new sandbox
box backup myapp --to=s3://bucket/  # Remote backup

Requirements:

  • Export volume to tarball
  • Import tarball to new volume
  • Optional: S3/GCS remote storage

Multi-Sandbox Operations

Goal: Batch operations on sandboxes

box stop --all              # Stop all running sandboxes
box rm --all -f             # Remove all sandboxes
box ls --json               # JSON output for scripting
box ls --filter=running     # Filter by status

Sandbox Snapshots

Goal: Point-in-time snapshots for rollback

box snapshot myapp "before refactor"
box snapshots myapp                    # List snapshots
box restore myapp --snapshot="before refactor"

Template Customization

Goal: User-defined templates

# ~/.config/spark-sandbox/templates/custom.yaml
name: custom
base: spark-sandbox:base
packages:
  apt:
    - postgresql-client
    - redis-tools
  npm:
    - prisma
environment:
  DATABASE_URL: postgres://localhost/dev
ports:
  - 5432
  - 6379
box new mydb --template=custom

Quick Reference

Current Images

Image Size Features
spark-sandbox:base 2.56GB Go, Node, Python, Rust, zsh, chezmoi
spark-sandbox:agent 2.91GB Base + Claude Code, tree, pandoc
spark-sandbox:web 2.94GB Base + TypeScript, Vite, ESLint
spark-sandbox:desktop 6.25GB KDE GUI + full dev stack + Claude + GPU + chezmoi

Port Ranges

  • SSH: 2200-2299
  • Web: 3000-3999

Key Files

docker/
├── Dockerfile.base      # ✓ Complete (includes chezmoi)
├── Dockerfile.agent     # ✓ Complete
├── Dockerfile.web       # ✓ Complete
├── Dockerfile.desktop   # ✓ Complete (includes chezmoi)
├── config/
│   ├── zshrc           # ✓ Complete
│   ├── zshenv          # ✓ Complete
│   └── p10k.zsh        # ✓ Complete
└── scripts/
    ├── entrypoint.sh   # ✓ Complete (dotfiles support)
    └── desktop-init.sh # ✓ Complete (dotfiles support)