# Secure AI Coding Sandboxes Disposable, isolated Linux VMs for running Claude Code with `--dangerously-skip-permissions`. One command creates a fully provisioned environment. Blow it away and recreate it in minutes. The VM is a real Linux machine with its own filesystem, network, and process space — complete isolation from your host with easy access for development. | Platform | Script | Isolation Level | |----------|--------|-----------------| | **macOS** | `setup_env.sh` (OrbStack) | Full VM isolation | | **Windows** | `setup_env_windows.ps1` (Hyper-V) | Full VM isolation | ## Why This Exists Running `claude --dangerously-skip-permissions` on your host machine means Claude can execute arbitrary commands, install packages, modify system files, and access everything on your disk. That's powerful for autonomous coding but risky on a machine with your SSH keys, credentials, and personal files. These scripts create throwaway VMs where Claude can run unrestricted: - **Isolated filesystem** — Claude can't touch your host files, keys, or configs - **Isolated network** — services run on their own IP, no port conflicts with your host - **Disposable** — delete and recreate in one command - **Multiple VMs** — run separate sandboxes per project with shared git credentials - **Full access from host** — edit files in your editor, browse databases, view running apps ## Quick Start (macOS) ```bash # Create a sandbox, SSH in, run Claude unrestricted ./setup_env.sh my-project ssh my-project@orb claude --dangerously-skip-permissions ``` If anything goes wrong: `orb delete my-project && ./setup_env.sh my-project` ### macOS Setup ```bash # Create and provision a VM (one command from macOS) ./setup_env.sh my-sandbox ``` On first run, you'll be prompted for git commit author name and email. These are saved to `config.env` and reused for all future VMs. You'll also get an interactive checklist to select which components to install. If you select VNC, you'll be prompted for a VNC password (this is never stored and must be entered each time). ```bash # Create additional VMs — reuses config.env, shows component picker ./setup_env.sh my-other-project ./setup_env.sh elixir-playground ``` When run manually inside a VM, you're prompted for each component individually: ```bash # Inside a VM — interactive, prompts per component ./setup_env.sh # Inside a VM — accept all without prompting ./setup_env.sh -y ./setup_env.sh --yes ``` ### macOS Requirements - macOS with Apple Silicon (ARM64) - [OrbStack](https://orbstack.dev) installed (`brew install orbstack`) ## Quick Start (Windows) ```powershell # Run as Administrator .\setup_env_windows.ps1 -VMName my-project # Connect via SSH (after provisioning) ssh -i $env:USERPROFILE\.ssh\id_ed25519_my-project dev@my-project.local # Run Claude unrestricted claude --dangerously-skip-permissions ``` If anything goes wrong: `Remove-VM -Name my-project -Force` then run the script again. ### Windows Setup ```powershell # Create and provision a VM (run as Administrator) .\setup_env_windows.ps1 -VMName my-sandbox # Customize resources .\setup_env_windows.ps1 -VMName my-sandbox -MemoryGB 16 -DiskGB 100 -CPUs 8 # Skip optional components .\setup_env_windows.ps1 -VMName my-sandbox -SkipVNC -SkipOllama ``` On first run, you'll be prompted for: - Git commit author name and email (saved to `config.env`) - VM user password (min 8 chars, not stored) - VNC password if VNC is enabled (min 8 chars, not stored) ### Windows Requirements - Windows 10/11 Pro, Enterprise, or Education (Hyper-V not available on Home) - Hyper-V enabled: `Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All` - Administrator privileges - One of: Windows ADK, WSL with genisoimage, or Windows 10+ (IMAPI2 fallback) ### Why Hyper-V (not WSL2)? WSL2 is convenient but provides weaker isolation: - Shares kernel with all WSL2 instances - Host filesystem mounted by default - Can launch Windows executables from Linux - Network traffic bypasses Windows firewall Hyper-V provides **maximum security**: - Separate kernel per VM - Complete filesystem isolation - Own network stack - No Windows integration by default ## What Gets Installed All components are optional — deselect what you don't need in the interactive picker. | Tool | Version | Purpose | |------|---------|---------| | mise | latest | Version manager for runtimes | | Node.js | LTS | JavaScript runtime | | Erlang | latest | BEAM VM | | Elixir | latest | Elixir language | | Chromium | system | Browser automation target | | Playwright | latest | Browser testing framework | | PostgreSQL | system default | Database | | Ollama | latest | Local LLM inference | | Claude Code | latest | AI coding assistant (Anthropic) | | OpenCode | latest | Open-source AI coding assistant (multi-provider) | | Tidewave | latest | Elixir/Phoenix MCP server for AI tools | | yq | latest | YAML processor | | watchexec | latest | File watcher (via cargo) | | TigerVNC + XFCE | system | VNC access for browser login flows | ## Connecting from macOS ### SSH ```bash # Shell into the VM (no key setup required) ssh my-sandbox@orb # Run a command directly ssh my-sandbox@orb -- ls ~/projects # Run Claude unrestricted ssh my-sandbox@orb -- claude --dangerously-skip-permissions ``` OrbStack handles SSH key configuration automatically. ### Editing Files Your editor connects to the VM over SSH. You edit files as if they were local — full LSP support, syntax highlighting, file tree, integrated terminal. **Zed:** 1. `Cmd+Shift+P` -> "Open Remote Folder" 2. Enter: `my-sandbox@orb:~/projects` **VS Code / Cursor:** 1. Install the "Remote - SSH" extension 2. `Cmd+Shift+P` -> "Remote-SSH: Connect to Host" 3. Enter: `my-sandbox@orb` 4. Open folder: `~/projects` **Finder (direct filesystem access):** ``` /Volumes/OrbStack/my-sandbox/home// ``` ### Viewing Running Apps Services running in the VM are accessible from your Mac via `.orb.local`: ```bash # Phoenix/Rails/Next.js dev server running on port 4000 inside the VM open http://my-sandbox.orb.local:4000 # Or use port forwarding if the app only binds to localhost ssh -L 4000:localhost:4000 my-sandbox@orb ``` PostgreSQL, Redis, or any service listening on the VM's interfaces is reachable at `my-sandbox.orb.local:` from your Mac — no extra configuration. ## VNC (Browser Access) For tasks requiring a visible browser (e.g., Claude Code OAuth login): ```bash # Start VNC server inside the VM ssh my-sandbox@orb -- vnc-start # Connect from macOS (opens Screen Sharing.app) open vnc://my-sandbox.orb.local:5901 # Stop when done (saves resources) ssh my-sandbox@orb -- vnc-stop ``` ### macOS Screen Sharing (built-in) ```bash open vnc://my-sandbox.orb.local:5901 ``` Enter your VNC password when prompted. ### RealVNC Viewer 1. Download from https://www.realvnc.com/en/connect/download/viewer/ 2. Enter address: `my-sandbox.orb.local:5901` 3. When prompted for credentials, enter your VNC password (username can be left blank) ### TigerVNC Viewer ```bash # Install via Homebrew brew install tiger-vnc # Connect vncviewer my-sandbox.orb.local:5901 ``` Enter your VNC password when prompted. ### Connection details for any VNC client - **Host**: `my-sandbox.orb.local` - **Port**: `5901` (display `:1`) - **Password**: the VNC password from `config.env` - **Resolution**: 1280x800 (configurable in `~/bin/vnc-start`) ## PostgreSQL A superuser matching your Linux username and a `dev` database are created automatically. **Auth model:** - Local socket (`psql dev`): peer auth (OS username must match PG role) - Localhost TCP (127.0.0.1): scram-sha-256 (password required) - Host network (192.168.0.0/16, i.e., from macOS): scram-sha-256 ### From inside the VM ```bash psql dev # Connect to dev database psql -l # List databases createdb myapp_dev # Create a new database ``` ### From macOS ```bash # Direct (requires: brew install libpq) psql -h my-sandbox.orb.local -U -d dev ``` ### Connection strings ``` # Elixir/Phoenix postgres://@my-sandbox.orb.local/myapp_dev # Generic host=my-sandbox.orb.local port=5432 dbname=dev user= ``` ### DataGrip 1. New Data Source -> PostgreSQL 2. **SSH/SSL** tab: Check "Use SSH tunnel", Host: `my-sandbox@orb`, Auth: Key pair 3. **General** tab: Host: `localhost`, Port: `5432`, User: your VM username, Database: `dev`, No password 4. Test Connection -> Apply ### DBeaver 1. New Database Connection -> PostgreSQL 2. **SSH** tab: Check "Use SSH Tunnel", Host: `my-sandbox.orb.local`, Port: `22`, Auth: Public Key 3. **Main** tab: Host: `localhost`, Port: `5432`, Database: `dev`, Username: your VM username, no password 4. Test Connection -> Finish ### Creating additional databases ```bash # From inside the VM createdb myapp_dev createdb myapp_test # From macOS ssh my-sandbox@orb -- createdb myapp_dev ``` ## Claude Code Plugins The script installs these plugins at user scope: **Anthropic marketplace** (`anthropics/claude-code`): - code-review, code-simplifier, feature-dev, pr-review-toolkit, security-guidance, frontend-design **Superpowers marketplace** (`obra/superpowers`): - double-shot-latte, elements-of-style, superpowers, superpowers-chrome, superpowers-lab **MCP Servers**: - `playwright` - Browser automation and screenshots - `superpowers-chrome` - Direct Chrome/Chromium control (headless) ## Configuration All tools are configured to use the latest versions by default. Erlang and Elixir versions can be customized in `setup_env.sh`: ```bash ERLANG_VERSION="latest" # or pin to specific version like "28.3.1" ELIXIR_VERSION="latest" # or pin to specific version like "1.19.5-otp-28" ``` ### Shared credentials Git credentials (name, email) are stored in `config.env` (gitignored). VNC passwords are never stored and must be entered each time you create a VM with VNC enabled. To reset git credentials: ```bash rm config.env ./setup_env.sh my-sandbox # will prompt again ``` Or copy the example and edit: ```bash cp config.env.example config.env # Edit config.env with your values ``` ## Managing VMs ```bash # List all VMs orb list # Delete a VM (instant cleanup) orb delete my-sandbox # Stop a VM (preserves state, frees resources) orb stop my-sandbox # Start a stopped VM orb start my-sandbox # Nuclear option — delete and recreate orb delete my-sandbox && ./setup_env.sh my-sandbox ``` ## Idempotency The VM provisioning script is safe to run multiple times. It checks for existing installations before re-installing and avoids appending duplicate configuration lines. ## Logs Each provisioning run creates a log file at `/tmp/setup_env_.log` inside the VM with detailed output from package installations and any errors. Log files are created with mode 600 (owner-only access). ## Security The script includes several security hardening measures: - **Input validation**: VM names, VNC passwords, and git credentials are validated against strict patterns - **No credential storage**: VNC passwords are prompted each time and never written to disk - **Safe credential passing**: Values are base64-encoded when passed to the VM to prevent shell injection - **Config file security**: `config.env` is created with mode 600 and parsed safely (not sourced) - **Secure temp files**: Uses `mktemp` with restrictive permissions for all temporary files - **Host filesystem isolation**: macOS home directory access is disabled inside the VM - **PostgreSQL hardening**: Uses peer auth for local sockets, scram-sha-256 for network connections