Note: Also read README.md for user-facing features, command usage, and Git authentication setup.
AgentBox is a simplified replacement for ClaudeBox. The user was maintaining patches to ClaudeBox but wanted to stop due to complexity. Key motivations:
- ClaudeBox has 1000+ users but too many features the user doesn't need
- Complex slot system and Bash 3.2 compatibility requirements made it hard to maintain
- Python profile in ClaudeBox was buggy
- User wanted automatic behavior without prompts
-
Ephemeral Containers: Containers use
--rmflag and are destroyed on exit. This differs from ClaudeBox's persistent slot-based containers. -
Hash-Based Naming: Container names use SHA256 hash of project directory path (first 12 chars) to ensure uniqueness and avoid conflicts.
-
Bind Over Volume: Claude CLI and OpenCode use bind mounts to host directories.
-
SSH Implementation: Currently mounts
~/.agentbox/ssh/directory directly (not true SSH agent forwarding). Future improvement could use Docker's--sshflag for better security. -
UID/GID Handling: Dockerfile builds with host user's UID/GID passed as build args to minimize permission issues, but some remain (see ZSH history issue).
Dockerfile: Multi-stage build with all language toolchains. UsesUSER agent(UID 1000)entrypoint.sh: Minimal - only sets PATH and creates Python venvsagentbox: Main logic - rebuild detection, container lifecycle, mount management
Automatic rebuilds are triggered by:
- File changes: SHA256 hash of Dockerfile + entrypoint.sh stored as Docker image label. Compares on each run.
- Time-based: If image is older than 48 hours, rebuild automatically to get latest tool versions (Claude Code/OpenCode).
This ensures tools stay updated without manual intervention or version checking overhead.
- Detect container runtime (Docker or Podman)
- Compare hashes → rebuild if needed (on rebuild: build new image, auto-prune dangling images)
- Run ephemeral container with all mounts
- Container removed automatically on exit
AgentBox supports both Docker and Podman via automatic detection:
Detection Logic:
- Check if
dockercommand exists AND daemon is running (docker infosucceeds) - Fall back to
podmanif Docker check fails - Error if neither is available
Runtime Variable: Set once at startup in main(), used throughout via $RUNTIME variable substitution.
Compatibility: All Docker commands used are Podman-compatible:
build,run,inspect,image prune- identical syntax- All flags (
--rm,-it,-v,--env, etc.) - fully compatible - SELinux
:zflag - supported by both runtimes - Labels system - identical implementation
Docker Preference: Docker is tried first because:
- Larger user base (more tested)
- Daemon check ensures it's actually running
- Podman users typically understand they're using a Docker alternative
Podman-Specific Handling:
--userns=keep-idflag added for Podman rootless mode to maintain UID/GID mapping between host and container- Without this flag, Podman's user namespace mapping causes ownership mismatches on mounted volumes
- This flag is not supported by Docker, so it's only added when using Podman
After each successful rebuild, $RUNTIME image prune -f --filter "label=agentbox.version" removes dangling agentbox images. This prevents accumulation over time without manual intervention.
$PROJECT_DIR # Project directory (mounted at full host path)
<additional_dirs> # Additional directories via --add-dir (also mounted at full host paths)
/home/agent/.ssh # SSH keys from ~/.agentbox/ssh/
/home/agent/.gitconfig # Git config (read-only)
/home/agent/.npm # NPM cache
/home/agent/.cache/pip # Pip cache
/home/agent/.m2 # Maven cache
/home/agent/.gradle # Gradle cache
/home/agent/.shell_history # History directory (HISTFILE env var points to zsh_history inside)
/home/agent/.claude # Claude config
/home/agent/.config/opencode # OpenCode config
/home/agent/.local/share/opencode # OpenCode auth- Basic functionality verified (help command, shell mode)
- Full Docker build/run cycle needs real environment testing
- Multi-project isolation designed but not stress-tested
- SSH operations need testing with actual Git repositories
- True SSH Agent Forwarding: Replace key mounting with Docker's
--sshflag - Build Cache Optimization: Better layer ordering for faster rebuilds
- Permission Fixes: Solve ZSH history permission issue properly
- Debug Mode: Add verbose logging for troubleshooting
- Config File: Support
.agentboxrcfor user preferences - WSL2 Optimizations: Specific handling for WSL2 environments
- Root Cause: Ink framework's TTY handling in containers
- Attempted Fixes: Terminal size handling, TTY allocation modes
- Status: Unfixable without Claude CLI framework changes
- Root Cause: Host file ownership (host UID) vs container user (UID 1000)
- Attempted Fixes: Various permission strategies, all had side effects
- Status: Cosmetic issue, functionality works
Current image is large (~2GB) due to multiple language toolchains. Could optimize with:
- Multi-stage builds with slimmer final stage
- Optional language support via build args
- Better layer caching strategies
- Simplicity First: Resist feature creep. The value is in being simpler than ClaudeBox.
- Automatic Behavior: Users shouldn't need to think about container management.
- No Prompts: Everything should work without user interaction (except initial SSH setup).
- Fail Gracefully: Clear error messages, automatic recovery where possible.
The agentbox script has these key functions:
detect_runtime(): Detect available container runtime (Docker or Podman)check_runtime(): Verify a container runtime is availablecalculate_hash(): SHA256 hash for change detectionneeds_rebuild(): Compare hashes with image labelbuild_image(): Docker build with proper argsmount_additional_dirs(): Mount extra directories with intuitive folder names (e.g., /foo, /bar)validate_dir_path(): Validate directory paths (traversal check, system dirs, existence, duplicates)run_container(): Main container execution logic with all mounts and command executionssh_setup(): Initialize ~/.agentbox/ssh/ directory
-
Never use
-iflag: Git commands likegit rebase -iwon't work in non-interactive container context -
Path Hashing: Container names use first 12 chars of SHA256(project_path) - collision risk is negligible
-
Container Naming:
agentbox-<hash>pattern ensures per-project container isolation (separate caches and history, but shared tool authentication) -
Shell Mode: When using
shellcommand, execution goes through zsh even for bash (ensures environment is loaded) -
Admin Mode:
--adminflag doesn't actually grant sudo (would need Dockerfile changes) - currently just shows a message
- Core files: 3 (Dockerfile, entrypoint.sh, agentbox)
- Documentation: 2 (README.md, DEVELOPMENT_NOTES.md)
- Other: .gitignore, LICENSE, CLAUDE.md
- Total: ~8 files (vs ClaudeBox's 20+)