Goal: Pull shell configurations, aliases, and customizations from a GitHub dotfiles repo for personalized dev environments.
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
Status: Core implementation COMPLETE (2026-01-23)
Requirements:
- Add
DOTFILES_REPOenvironment 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/dotfilesflag - 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.tomlfor pulling external deps (chezmoi handles this natively)
# ~/.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# 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...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
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 CodeTDD 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>Goal: zsh with Oh My Zsh and Powerlevel10k working in GUI terminal
Requirements:
- Install zsh
- Install Oh My Zsh for the
abcuser (webtop default user) - Install Powerlevel10k theme
- Copy our configs: zshrc, p10k.zsh, zshenv
- Set zsh as default shell for
abcuser - 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 -fGoal: 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 -fGoal: 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 -fGoal: 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 -fGoal: 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 -fGoal: 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 -fGoal: 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 commandsGoal: 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 0Goal: Complete README and inline docs
Requirements:
- README.md covers all features
- Command examples for each subcommand
- Troubleshooting section
- Architecture overview
- Contributing guidelines (future enhancement)
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
Goal: Control CPU/memory per sandbox
box new heavy-task --cpu=4 --memory=8g
box new lightweight --cpu=1 --memory=1gRequirements:
- Add
--cpuflag tobox new - Add
--memoryflag tobox new - Store limits in container labels
- Show limits in
box lsoutput
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 backupRequirements:
- Export volume to tarball
- Import tarball to new volume
- Optional: S3/GCS remote storage
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 statusGoal: Point-in-time snapshots for rollback
box snapshot myapp "before refactor"
box snapshots myapp # List snapshots
box restore myapp --snapshot="before refactor"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
- 6379box new mydb --template=custom| 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 |
- SSH: 2200-2299
- Web: 3000-3999
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)