crush-sandbox
v0.13.0
Published
Docker sandbox for the Crush CLI with Git worktree support
Readme
Crush Sandbox
A lightweight bash wrapper that runs the Crush CLI in a Docker sandbox with Git worktree support. Perfect for AI-assisted development across multiple branches simultaneously, with per-workspace persistent caching for fast builds.
🚀 Quick Start
Prerequisites
- macOS (primary target)
- Docker Desktop installed and running
Installation
npm global install (recommended)
The recommended installation method uses npm to install crush-sandbox globally:
npm install -g crush-sandboxDirect script installation
Automatic installation:
curl -fsSL https://raw.githubusercontent.com/wireless25/crush-sandbox/main/docker-sandbox-crush | sudo tee /usr/local/bin/crush-sandbox > /dev/null
sudo chmod +x /usr/local/bin/crush-sandbox
ln -s /usr/local/bin/crush-sandbox /usr/local/bin/crushboxManual installation:
Download the script:
curl -fsSL https://raw.githubusercontent.com/wireless25/crush-sandbox/main/docker-sandbox-crush -o docker-sandbox-crushMake it executable:
chmod +x docker-sandbox-crushMove it to your PATH:
sudo mv docker-sandbox-crush /usr/local/bin/crush-sandbox
Install using the script itself:
If you've cloned the repository, you can use the built-in install command:
./docker-sandbox-crush installThis will:
- Validate Docker is available
- Install the script to
/usr/local/bin/crush-sandbox - Create a
crushboxalias symlink - Display version information for installed tools
Note: gitleaks Docker image will be pulled automatically on first use for credential scanning. No additional installation is required.
✨ Features
- Git worktree support - Work on multiple branches simultaneously without git conflicts
- Per-worktree container isolation: Each worktree (main + each worktree) gets its own container for crash isolation
- Shared cache volumes: All worktrees in same repository share a cache volume for fast installs
- Configurable resource limits: Tune memory, CPU, and process limits via environment variables
- Parallel container support: Run 3-5 containers safely on 32GB RAM systems
- Workspace path mounting: Your workspace is mounted at same absolute path inside container, makes debugging easier
- Persistent caches: npm and pnpm caches persist per repository for faster subsequent runs
- Automatic Crush CLI installation: Crush CLI is installed automatically on first use
- Git config injection: Your Git user.name and user.email are passed into the container
- Container reuse: Containers are stopped but not removed, enabling fast restarts
- Container shell: Use
--shellflag to get an interactive shell instead of Crush CLI - Configuration support: Automatically mounts and merges Crush configuration from host
- Programmatic mode: Send prompts directly via
-pflag or piped input for automation and CI/CD
🌳 Git Worktrees
Git worktrees allow you to check out multiple branches simultaneously in different directories.
Why Worktrees Matter for AI Development
Traditional git workflow forces you to switch branches (git checkout) to work on different features. This means:
- You can only work on one feature at a time
- Stashing or committing work-in-progress to switch contexts
- Crush CLI can only work on the current branch
- Slow context switching between features
With git worktrees:
- Work on multiple branches simultaneously - Each worktree is an isolated directory on a different branch
- No context switching - Jump between worktrees instantly, no stashing or committing needed
- Perfect for AI agents - Crush can generate code in one worktree while you review in another
- Isolated environments - Each worktree has its own docker container, sharing one cache volume with all containers in the same repository
Worktree Structure
my-project/ # Main workspace (e.g., main branch)
├── src/
├── .worktrees/ # Worktree directory
│ ├── feature-login/ # Worktree 1 (feature/login branch)
│ │ ├── src/
│ │ └── package.json
│ ├── fix-bug-123/ # Worktree 2 (bugfix/123 branch)
│ │ ├── src/
│ │ └── package.json
│ └── experiment-api/ # Worktree 3 (experiment/api branch)
│ ├── src/
│ └── package.json
└── package.jsonEach worktree is a separate Crush sandbox with its own isolated container (crash-safe) but shares the npm/pnpm cache volume with other worktrees in the same repository.
Crush Sandbox + Worktrees Workflow
- Create worktree:
crush-sandbox run --worktree feature-login - Work in isolation: Crush CLI runs in
my-project/.worktrees/feature-login/with its own container - Generate code: AI creates feature code in worktree
- Switch workspace:
cd ../fix-bug-123(instant, no git operations, each has its own container) - Review later: Come back to worktree anytime, work is preserved
- List containers:
crush-sandbox list-containersto see all workspace containers - Clean up:
crush-sandbox remove-worktree feature-loginwhen done (also removes its container) - Restart: Run a worktree sandbox later with
crush-sandbox run --worktree feature-login(existing worktree name restarts the container) orcd .worktrees/feature-loginandcrush-sandbox run
Comparison: Traditional vs Worktree
| Task | Traditional Git | With Worktrees |
|------|-----------------|----------------|
| Work on 2 features | Stash/commit, checkout branch | cd .worktrees/feature2 |
| AI code review | Push PR, review in same repo | Generate in worktree, review in main |
| Context switch | 30-60 seconds | <1 second |
| Uncommitted changes | Must stash or commit | Stay in worktree |
| Parallel testing | Difficult | Easy (each worktree has its own sandbox) |
Worktree Commands
Create a new worktree with auto-generated name:
crush-sandbox run --worktreeCreate worktree with custom name:
crush-sandbox run --worktree feature-loginList all worktrees:
crush-sandbox list-worktreesList all containers:
crush-sandbox list-containersThis shows all containers for the repository (main + all worktrees) with their status (running/stopped) and current workspace indicator.
Remove a worktree:
crush-sandbox remove-worktree feature-loginForce remove (with uncommitted changes):
crush-sandbox remove-worktree feature-login --force⚙️ Configuration
The Docker sandbox automatically provides Crush CLI configuration:
Configuration Sources
Host configuration (global defaults):
~/.config/crush/- Global Crush config (read-only mount)~/.local/share/crush/- Crush session data (read-only mount)
Workspace configuration (workspace-specific):
.crush.jsonorcrush.json(relative to workspace root)
If you maintain global Crush config with commands, skills, or settings, this will be mounted into the container. Any workspace-specific config will override these settings.
Config files in the workspace are mounted into the container with the rest of the code and take precedence over host config by default in Crush. Make sure to configure your skills
and commands accordingly. If you want to use global configured skills, add the /tmp/crush-config/merged/skills path to the skills option in the config (global on host or in workspace) to make Crush pick them up.
Session Data Mounting
Crush CLI session data (including authentication tokens, model preferences, and other runtime state) is mounted from your host machine into the container.
Important: Session data is mounted read-only from ~/.local/share/crush/ on your host. This means:
Configuration changes made inside the container are lost when the container stops
- Tokens and authentication must be completed on the host machine
- Model preferences and settings should be configured on the host
- The container only reads pre-authenticated session data
Recommended workflow:
- Run Crush CLI on the host machine first:
crush - Complete authentication and configure your preferences
- Run
crush-sandbox runto use your pre-configured session - Use
--no-host-configflag to skip host config/session mounting (requires re-authentication each session)
- Run Crush CLI on the host machine first:
Why read-only?
- Prevents the AI agent from modifying your authentication tokens
- Ensures session integrity and security
- Keeps configuration changes persistent on your host machine
Example to include skills from global host in the config:
{
"$schema": "https://charm.land/crush.json",
"options": {
"skills_paths": [
"~/.config/crush/skills",
"/tmp/crush-config/merged/skills"
]
}
}With this configuration, you can still use crush on your host machine with the same setup.
Configuration Merge Behavior
- Host configuration is copied to the container
- Workspace configuration is mounted with the workspace, overwriting host config (Crush default behavior)
- Host configuration is available at
/tmp/crush-config/mergedinside the container CRUSH_GLOBAL_CONFIGenvironment variable is set to this location
This means workspace-specific settings always override global defaults.
Security
- All configuration mounts are read-only (
:roflag) - The container cannot modify your host configuration files
Configuration Control Flags
You can control configuration behavior with these flags:
| Flag | Description |
|------|-------------|
| --no-host-config | Skip mounting host Crush config directory |
Examples:
# Skip host configuration
crush-sandbox run --no-host-config
# Or use alias:
crushbox run --no-host-configResource Configuration
Each container is configured with resource limits to ensure safe autonomous execution. These limits are designed for 3-5 containers in parallel on 32GB RAM systems.
Default Resource Limits:
- Memory: 4GB per container (with 4GB swap for spikes)
- CPU: 2 cores per container
- Process limit: 1024 processes (prevents fork bombs but enables build processes)
Why these limits?
- Prevents resource exhaustion attacks while maintaining usability
- Allows builds (Vite, Webpack, etc.) to run successfully
- Enables parallel development across multiple worktrees
- Protects your host system from runaway processes
Environment Variable Overrides
You can customize resource limits for your hardware or workload:
# Increase for heavy workloads on 32GB RAM (2-3 containers max)
export DOCKER_SANDBOX_MEMORY=8g
export DOCKER_SANDBOX_CPUS=4.0
export DOCKER_SANDBOX_NPROC=2000
# Use for a single session
DOCKER_SANDBOX_MEMORY=8g DOCKER_SANDBOX_CPUS=4.0 crush-sandbox runRecommended Configurations by RAM:
| System RAM | Memory/CPU per container | Safe parallel containers | Environment vars |
|------------|------------------------|------------------------|------------------|
| 16GB | 2GB / 1.5 CPUs | 2 containers | DOCKER_SANDBOX_MEMORY=2g DOCKER_SANDBOX_CPUS=1.5 |
| 32GB | 4GB / 2 CPUs | 3-5 containers | (defaults, no override needed) |
| 64GB+ | 8GB / 4 CPUs | 5-8 containers | DOCKER_SANDBOX_MEMORY=8g DOCKER_SANDBOX_CPUS=4.0 |
Parallel Container Safety:
When running multiple worktree containers in parallel:
- Total memory used = (containers × memory_limit)
- Swap provides headroom during builds (one container can spike to 2× limit)
- With defaults (4GB each), 5 containers = 20GB RAM + occasional swap usage
- Build processes are the main bottleneck - they rarely run in parallel across multiple worktrees
Example: Parallel Worktree Development
# Terminal 1: Main workspace
cd ~/projects/my-app
crush-sandbox run
# Terminal 2: Worktree 1
cd ~/projects/my-app
crush-sandbox run --worktree feature-auth
# Terminal 3: Worktree 2
cd ~/projects/my-app
crush-sandbox run --worktree feature-ui
# All three containers run independently with 4GB RAM each
# Total: ~12GB used, leaves 20GB for system + DockerConfiguration Directory Structure Example
~/.config/crush/ # Host configuration (global)
├── crush.json # Main Crush config
└── skills # Skills directory
└── commands # Commands directoryIf you have a crush.json or .crush.json already in the workspace root, this will take precedence over the .config/crush/ directory by Crush CLI's own behavior.
📖 Usage
Start Crush CLI in a sandbox
Navigate to your workspace directory and run:
crush-sandbox runOr use the alias:
crushbox runThis will:
- Create (or reuse) a sandbox container for your workspace
- Mount your workspace at the same absolute path
- Install Crush CLI if not already installed
- Install pnpm for package management
- Start the Crush CLI
Programmatic Mode
For automation and CI/CD pipelines, you can send prompts directly without interactive mode:
Using -p flag:
crush-sandbox run -p "Create a REST API with authentication"Using piped input:
cat "./ralph/prompt.md" | crush-sandbox runUsing heredocs:
crush-sandbox run -p "$(cat <<EOF
Create a login form with:
- Email field
- Password field
- Remember me checkbox
- Login button
EOF
)"With --quiet flag (suppresses container setup messages):
crush-sandbox run -p "Refactor code" --quietWith --model flag (select AI model):
crush-sandbox run -p "Create a REST API" --model "openai/gpt-4"With worktree:
crush-sandbox run --worktree feature-auth -p "Add OAuth login"With worktree and model:
crush-sandbox run --worktree feature-auth -p "Add OAuth login" --model "claude-3.5"Programmatic Mode Details
Detection: Programmatic mode is automatically enabled when:
-p "prompt"flag is provided (explicit prompt)- Stdin has piped input (e.g.,
echo "prompt" | crush-sandbox run)
Priority: If both -p flag and piped input are present, the -p value is used (explicit wins).
Empty prompts: Empty prompts pass through to Crush CLI without validation. Let Crush CLI handle the empty prompt.
Multi-line support: Works with:
-pflag with quoted strings (preserves newlines)- Heredocs with
-pflag - Piped multi-line input
Model selection: --model flag allows specifying which AI model to use (e.g., --model "openai/gpt-4", --model "claude-3.5"). See AGENTS.md for detailed examples.
Quiet mode: --quiet flag suppresses container setup messages in programmatic mode:
Crush CLI output is always visible. Error messages always appear even in quiet mode.
Flag conflicts: The --shell flag cannot be used with programmatic mode (-p flag or piped input).
Exit codes: Crush CLI exit codes propagate to script exit for automation scripts. Error messages are explicitly captured and reported, even when Crush CLI fails due to invalid model names. When --model is specified and Crush CLI fails, the script provides troubleshooting hints about potential model validation issues.
Start a debug shell
If you need to debug or run manual commands:
crush-sandbox run --shellOr with the alias:
crushbox run --shellThis gives you an interactive shell in the sandbox container instead of running Crush CLI.
Note: The --shell flag cannot be used with -p flag or piped input (programmatic mode).
Clean up the sandbox
To remove the container and cache volume for the current workspace:
crush-sandbox cleanOr with the alias:
crushbox cleanAdd --force to skip prompts and clean all containers + cache:
crush-sandbox clean --forceShow version
crush-sandbox --versionCommand Options
| Option | Description |
|--------|-------------|
| -p "prompt" | Send prompt directly to Crush CLI (programmatic mode) |
| --model "model" | Specify AI model for programmatic mode (e.g., --model "openai/gpt-4") |
| --quiet | Suppress container setup messages in programmatic mode |
| --shell | Start interactive shell instead of Crush CLI (for debugging) |
| --worktree [name] | Create a worktree with optional name |
| --branch-name [name] | Specify branch name for worktree (requires --worktree) |
| --no-host-config | Skip mounting host Crush config directory |
| --cred-scan | Enable credential scanning before starting container |
| --force | Skip confirmation prompts (use with clean and remove-worktree) |
| --version | Show version information |
Update to latest version
crush-sandbox updateThis will:
- Check for the latest version on GitHub
- Compare with your current version
- Prompt for confirmation if a newer version is available
- Download and replace the script automatically
- Validate the downloaded script before installing
Get help
crush-sandbox help🔒 Security
Security Overview
The docker-sandbox-crush tool implements several security controls to make AI-assisted development safe(er). However, the tool requires you to follow certain security practices to ensure safe operation.
Crush asks for your permission before performing any operation, but if you use --yolo mode or use it programmatically with crush run in a ralph loop, you must be aware of the security implications.
Read-Write Workspace Access
The Crush agent inside the container has full read-write access to your workspace files. This is intentional and necessary for the agent to:
- Read and modify source code files
- Run build commands and tests
- Create new files and directories
- Install packages and dependencies
- Execute git operations
Security Implications:
- Trust the AI agent: The agent can modify any file in your workspace
- Credential exposure risk: Never store secrets (API keys, passwords, tokens) in your workspace files
- Review all changes: Always review agent-generated changes
- Use version control: Git provides a safety net - you can revert any unwanted changes
Best Practices:
- Store credentials in:
- Environment variables
- Secret management tools
- CI/CD pipeline secrets (GitHub Actions Secrets, GitLab CI Variables)
.envfiles that are gitignored
- Never commit credentials to git
- Use
.gitignoreto exclude files with secrets - Rotate credentials if they were ever committed accidentally
Git Branch Protection for Production
When planning to use --yolo mode or use it programmatically with crush run, you should configure git branch protection to prevent direct pushes to production branches. This ensures:
- All agent-generated code goes through a pull request process
- Code review is required before merging
- CI/CD checks must pass before merging
- Unauthorized direct commits are blocked
What the Agent Can and Cannot Do
Capabilities
The Crush agent inside the sandbox container can:
✅ Read and write workspace files
- Full access to all files in the mounted workspace
- Can create, modify, delete any file
- Can execute any command within the workspace
✅ Run commands and scripts
- Execute build commands (npm build, cargo build, etc.)
- Run tests (npm test, pytest, etc.)
- Install packages (npm install, pip install, etc.)
✅ Make git operations
- Create commits
- Create branches
- Stage files
- Push to remote repositories
✅ Access network resources
- Download dependencies from npm, PyPI, etc.
- Make HTTP requests (if in code)
- Clone other git repositories
Limitations
The Crush agent cannot:
❌ Access files outside the workspace
- Container is limited to mounted workspace directory
- Cannot access your home directory (except workspace subdirectories)
- Cannot access system files or other projects
❌ Run with elevated privileges
- Container runs as non-root user
- Cannot install system packages globally
- Cannot modify Docker host
❌ Escalate privileges
- Docker capabilities are dropped (except CHOWN and DAC_OVERRIDE)
- Cannot gain root access
- Cannot modify container configuration
❌ Access host resources directly
- No direct access to host network
- No access to host filesystem beyond workspace
- Cannot interact with other containers
Security Controls in Place
The tool implements these security controls:
Resource limits - Prevents resource exhaustion attacks:
- Memory limited to 4GB per container (configurable via
DOCKER_SANDBOX_MEMORY) - CPU limited to 2 cores per container (configurable via
DOCKER_SANDBOX_CPUS) - Process count limited to 1000 PIDs (configurable via
DOCKER_SANDBOX_NPROC) - Designed for 3-5 containers in parallel on 32GB RAM systems
- Swap allows temporary memory spikes during builds
- Memory limited to 4GB per container (configurable via
Non-root user - Limits attack surface:
- Container runs as your UID/GID
- Cannot perform privileged operations
Capability dropping - Reduces Linux capabilities:
- All capabilities dropped by default
- CHOWN and DAC_OVERRIDE added back (required for cache and workspace access)
Credential scanning - Warns about exposed secrets:
- Scans workspace with gitleaks before starting
- gitleaks is automatically installed when you run
crush-sandbox run --cred-scan - Prompts you to continue or abort if credentials detected
- Can be bypassed with
--no-cred-scanflag (use with caution)
Workspace isolation - Prevents cross-project contamination:
- Each workspace has its own container
- Caches are per-workspace
- No shared state between workspaces
🔧 How It Works
Workspace Isolation
Each workspace directory (main or worktree) gets its own:
- Container: Named
crush-sandbox-<repo-hash>(main) orcrush-sandbox-<repo-hash>-<worktree-name>(worktree) - Cache volume: Named
crush-cache-<repo-hash>for persistent package manager caches (shared across all worktrees in same repository)
This means:
- Each worktree has crash isolation (stopping one doesn't affect others)
- All worktrees in same repository share npm/pnpm cache for fast installs
- Different repositories have completely isolated sandbox environments
Container Lifecycle
- Create: Container is created from
node:22-bookwormbase image - Configure: Workspace and cache volumes are mounted, environment variables are set
- Start: Container is started
- Use: Crush CLI or shell runs inside the container
- Stop: Container is stopped when you exit (kept for reuse)
Containers are not removed automatically, so subsequent starts are instant.
Cache Persistence
The cache volume stores:
- npm cache:
/workspace-cache/npm - pnpm store:
/workspace-cache/pnpm/store - pnpm cache:
/workspace-cache/pnpm/cache
This means:
- Packages downloaded once stay cached
- Switching workspaces switches cache volumes
- Faster installs after the first run
Automatic Tool Installation
On container startup:
- Crush CLI: Installed via
npm install -g @charmland/crush(cached after first install) - pnpm: Installed via
npm install -g pnpm(uses npm cache)
Installation happens automatically and silently on every container start, with fast-path checks to skip re-installation.
📋 Examples
Worktree Examples
Example 1: Feature Development Workflow
# Navigate to your project
cd ~/projects/my-app
# Create worktree for new feature
crush-sandbox run --worktree feature-auth
# Inside Crush CLI, generate authentication code
> Crush: Implement JWT authentication
[AI generates auth system in .worktrees/feature-auth/]
# Switch back to main workspace
cd ~/projects/my-app
# Continue working on main branch
git pull origin main
# Later, review the worktree
cd .worktrees/feature-auth
git diff main # See all changes from worktree
# When satisfied, merge to main
git checkout main
git merge feature-auth
crush-sandbox remove-worktree feature-authExample 2: Parallel Development
# Main workspace: stable branch
cd ~/projects/my-app
# Worktree 1: User profile feature
crush-sandbox run --worktree feature-profile
# AI generates user profile code
# Worktree 2: API refactoring
cd ~/projects/my-app
crush-sandbox run --worktree refactor-api
# AI refactors API endpoints
# Worktree 3: Bugfix
cd ~/projects/my-app
crush-sandbox run --worktree fix-auth-bug
# AI fixes authentication bug
# List all worktrees
crush-sandbox list-worktrees
# Worktrees:
# - /Users/user/projects/my-app/.worktrees/feature-profile
# Branch: feature/profile
# - /Users/user/projects/my-app/.worktrees/refactor-api (current)
# Branch: refactor/api
# - /Users/user/projects/my-app/.worktrees/fix-auth-bug
# Branch: fix/auth-bug
# Switch between worktrees instantly (no git checkout needed)
cd ../feature-profile
cd ../fix-auth-bugExample 3: Bugfix vs Feature Isolation
# Main workspace on stable branch (production code)
cd ~/projects/my-app
git checkout main
# Worktree for urgent bugfix (isolated from feature work)
crush-sandbox run --worktree fix-critical-bug
> Crush: Fix the production authentication bug
[AI generates bugfix in isolation]
# Meanwhile, main workspace remains stable
# No risk of accidentally including untested changes
# Test bugfix in its own sandbox
cd .worktrees/fix-critical-bug
npm test # Run tests in bugfix environment
# Merge only when ready
git checkout main
git merge fix-critical-bug
crush-sandbox remove-worktree fix-critical-bugExample 4: AI-Assisted PR Workflow
# Worktree for Crush-generated PR
cd ~/projects/my-app
crush-sandbox run --worktree pr-add-dashboard
# Crush generates complete feature
> Crush: Add admin dashboard with charts and analytics
[AI creates entire feature in worktree]
# Stay in main workspace to review
cd ~/projects/my-app
# Compare worktree to main
git diff main .worktrees/pr-add-dashboard/
# Test worktree changes
cd .worktrees/pr-add-dashboard
crush-sandbox run --shell # Debug in worktree sandbox
npm test # Run tests
# Review and merge
cd ~/projects/my-app
git checkout -b add-dashboard
git merge pr-add-dashboard
git push origin add-dashboard
crush-sandbox remove-worktree pr-add-dashboardProgrammatic Mode Examples
Simple one-liners
# Generate a component
crush-sandbox run -p "Create a React button component with hover states"
# Add a feature
echo "Add dark mode support" | crush-sandbox run
# Fix a bug
crush-sandbox run -p "Fix the authentication redirect loop"CI/CD Pipeline Integration
#!/bin/bash
# CI/CD pipeline script
# Run automated code generation
crush-sandbox run -p "Add unit tests for user authentication" --quiet
# Run tests
npm test
# If tests pass, commit and push
git add .
git commit -m "Add auth unit tests"
git push origin mainMulti-command automation
# Generate multiple components in sequence
for component in Button Input Modal; do
crush-sandbox run -p "Create a React ${component} component" --quiet
doneAdvanced piping examples
# Multi-line piped input
echo -e "Fix login bug\nAdd validation\nUpdate tests" | crush-sandbox run
# Heredoc piped input
crush-sandbox run <<EOF
Create a login form with:
- Email field
- Password field
- Remember me checkbox
- Login button
EOF
# Quiet mode with piping
echo "Refactor code" | crush-sandbox run --quietWith worktrees
# Generate code in worktree for review
crush-sandbox run --worktree feature-ui -p "Redesign the user profile page" --quiet
# Review in main workspace
cd ../
# Compare changes
git diff main .worktrees/feature-ui/Error handling
# --shell not allowed with -p
crush-sandbox run --shell -p "test"
# Error: --shell flag cannot be used with -p or piped input
# --shell not allowed with piped input
echo "test" | crush-sandbox run --shell
# Error: --shell flag cannot be used with -p or piped input
# Empty prompt passes through
echo "" | crush-sandbox run
# Executes: crush run "" (Crush CLI handles empty prompt)Basic Usage Examples
Typical workflow
# Navigate to your project
cd ~/projects/my-app
# Start Crush CLI in sandbox
crush-sandbox run
# Or use alias:
# crushbox run
# ... work with Crush CLI ...
# When done, Crush CLI exits and container stops
# Next time, container is reused (instant start)Using with different workspaces
cd ~/projects/project-a
crush-sandbox run # Uses crush-sandbox-<hash-a>
cd ~/projects/project-b
crush-sandbox run # Uses crush-sandbox-<hash-b>Each workspace has its own isolated environment.
Debugging setup issues
# Get a shell to check installation
crush-sandbox run --shell
# Or:
crushbox run --shell
# Inside the container:
which crush # Check if Crush CLI is installed
pnpm --version # Check pnpm version
npm --version # Check npm version🐛 Troubleshooting
"docker daemon is not running or not accessible"
Problem: Docker Desktop is not running.
Solution: Start Docker Desktop and wait for it to be ready. Verify with:
docker info"Git user.name and user.email not configured"
Problem: Git user configuration is missing.
Solution: This is a warning, not an error. Add to ~/.gitconfig if Crush CLI needs git operations:
git config --global user.name "Your Name"
git config --global user.email "[email protected]"Build fails with "not enough threads" or "too many open files"
Problem: Vite, Webpack, or other build tools fail due to resource limits.
Solution: Increase the process limit via environment variable:
export DOCKER_SANDBOX_NPROC=2000
crush-sandbox runOr for a one-time fix:
DOCKER_SANDBOX_NPROC=2000 crush-sandbox runBackground: The default limit (1000 processes) protects against fork bombs but allows most builds. Some aggressive build tools (Vite with many plugins, parallel TypeScript compilation) may need higher limits. Increase to 1500-2000 for complex projects.
Build fails with "memory limit exceeded" or OOM
Problem: Large build processes run out of memory.
Solution: Increase memory limit via environment variable:
# For 16GB RAM system
export DOCKER_SANDBOX_MEMORY=6g
# For 32GB RAM system
export DOCKER_SANDBOX_MEMORY=8g
crush-sandbox runSwap is automatically set to same value as memory, allowing temporary spikes during builds.
System becomes slow with multiple containers
Problem: Running 3-5 worktree containers slows down your Mac.
Solution: You've exceeded safe parallel container limits for your hardware:
For 16GB RAM:
# Limit to 2 containers with reduced resources
export DOCKER_SANDBOX_MEMORY=2g
export DOCKER_SANDBOX_CPUS=1.5
export DOCKER_SANDBOX_NPROC=800For 32GB RAM (defaults are fine, but ensure you're not building in parallel):
- Builds in multiple worktrees simultaneously can overload the system
- Stop idle containers:
crush-sandbox clean(choose option 1) - Only build in active worktree, use others for file editing
Check current resource usage:
# See all containers and their status
crush-sandbox list-containers
# See Docker stats
docker statsCrush CLI not working in container
Problem: Crush CLI installation failed.
Solution: Run with --shell flag to debug:
crush-sandbox run --shell
# Then manually install:
npm install -g @charmland/crushCache not persisting
Problem: Packages are re-downloaded every time.
Solution: Verify cache volume exists:
docker volume ls | grep crush-cacheCheck if volume is mounted:
docker inspect <container-name> | grep Mounts"Cannot write to /usr/local/bin" during install
Problem: No write permissions to /usr/local/bin.
Solution: Run with sudo:
sudo ./docker-sandbox-crush installOr choose a different installation directory in your PATH.
Container name changes unexpectedly
Problem: Different containers for the same project.
Solution: Ensure you're in the same workspace directory. Container names are based on the current working directory (pwd).
"Not in a git repository" when using --worktree
Problem: Tried to use worktree features outside a git repository.
Solution: Worktrees only work in git repositories. Initialize git first:
git initWorktree directory not found
Problem: Container starts but worktree path doesn't exist.
Solution: Check .worktrees/ directory in git root:
ls -la .worktrees/If missing, create a new worktree:
crush-sandbox run --worktree my-featureCannot remove worktree with uncommitted changes
Problem: Worktree has uncommitted changes and remove-worktree fails.
Solution: Use --force flag:
crush-sandbox remove-worktree my-feature --forceOr commit/stash changes first:
cd .worktrees/my-feature
git add .
git commit -m "Save work"
cd ..
crush-sandbox remove-worktree my-featureContainer/volume mismatch with worktree
Problem: Container uses root workspace name instead of worktree name.
Solution: This is expected behavior! Containers and caches are named based on the root git workspace, not the current worktree path. All worktrees in the same project share the same container and cache. This is intentional - it allows fast switching between worktrees without recreating containers.
Branch conflicts when creating worktree
Problem: Git error "Branch already checked out elsewhere" when creating worktree.
Solution: The branch is already checked out in another worktree or the main workspace. Either:
- Use a different branch:
crush-sandbox run --worktree feature2 other-branch - Switch main workspace to a different branch first
- Remove the worktree that has the branch:
crush-sandbox remove-worktree other-worktree
📝 License
This project is licensed under the MIT License - see the LICENSE file for details.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
🙋 Support
If you encounter issues or have questions:
- Check the Troubleshooting section above
- Search existing GitHub Issues
- Open a new issue with details
🔗 Related
- Crush CLI - The AI-powered CLI assistant
- Docker Desktop for Mac - Container runtime
Made with ❤️ for developers who love isolated environments
