diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
index 56e15d0..150a643 100644
--- a/.planning/ROADMAP.md
+++ b/.planning/ROADMAP.md
@@ -28,12 +28,11 @@ Decimal phases appear between their surrounding integers in numeric order.
3. Secret paths (~/.ssh, ~/.gnupg, ~/.aws, ~/.config/gcloud, age keys, /var/lib/tailscale) are not visible inside the sandbox
4. Claude can run `curl https://example.com`, `git status`, `, jq --help` (comma), and `nix shell nixpkgs#python3 -c python3 --version` inside the sandbox
5. Ctrl+C terminates the session cleanly; exit code from Claude passes through to the caller
-**Plans**: TBD
+**Plans:** 2 plans
Plans:
-- [ ] 01-01: TBD
-- [ ] 01-02: TBD
-- [ ] 01-03: TBD
+- [ ] 01-01-PLAN.md -- Create flake.nix and claudebox.sh with complete bwrap sandbox
+- [ ] 01-02-PLAN.md -- Build verification and manual sandbox smoke test
### Phase 2: Env Audit and CLI Polish
**Goal**: User can review exactly what enters the sandbox before launch, and has diagnostic tools for troubleshooting
@@ -68,6 +67,6 @@ Phases execute in numeric order: 1 -> 2 -> 3
| Phase | Plans Complete | Status | Completed |
|-------|----------------|--------|-----------|
-| 1. Minimal Viable Sandbox | 0/3 | Not started | - |
+| 1. Minimal Viable Sandbox | 0/2 | Planned | - |
| 2. Env Audit and CLI Polish | 0/1 | Not started | - |
| 3. Sandbox-Aware Prompting | 0/1 | Not started | - |
diff --git a/.planning/phases/01-minimal-viable-sandbox/01-01-PLAN.md b/.planning/phases/01-minimal-viable-sandbox/01-01-PLAN.md
new file mode 100644
index 0000000..2f90379
--- /dev/null
+++ b/.planning/phases/01-minimal-viable-sandbox/01-01-PLAN.md
@@ -0,0 +1,380 @@
+---
+phase: 01-minimal-viable-sandbox
+plan: 01
+type: execute
+wave: 1
+depends_on: []
+files_modified:
+ - flake.nix
+ - claudebox.sh
+autonomous: true
+requirements:
+ - SAND-01
+ - SAND-02
+ - SAND-03
+ - SAND-04
+ - SAND-05
+ - SAND-06
+ - SAND-07
+ - SAND-08
+ - SAND-09
+ - SAND-10
+ - SAND-11
+ - SAND-12
+ - SAND-13
+ - SAND-14
+ - SAND-15
+ - TOOL-01
+ - TOOL-02
+ - TOOL-03
+ - GIT-01
+ - GIT-02
+ - NIX-01
+ - NIX-02
+ - NIX-03
+ - UX-06
+
+must_haves:
+ truths:
+ - "Running `nix build` in the project root produces a working `claudebox` binary"
+ - "claudebox launches Claude Code inside bwrap with only allowlisted env vars"
+ - "Secret paths (~/.ssh, ~/.gnupg, ~/.aws, etc.) are not visible inside the sandbox"
+ - "Git works inside the sandbox with user identity from host"
+ - "comma and nix shell work inside the sandbox for on-demand tool installation"
+ - "Ctrl+C terminates the session cleanly; exit code passes through"
+ artifacts:
+ - path: "flake.nix"
+ provides: "Nix flake with claudebox as default package"
+ contains: "writeShellApplication"
+ - path: "claudebox.sh"
+ provides: "Shell script body with bwrap sandbox invocation"
+ contains: "exec bwrap"
+ key_links:
+ - from: "flake.nix"
+ to: "claudebox.sh"
+ via: "builtins.readFile ./claudebox.sh"
+ pattern: "builtins.readFile ./claudebox.sh"
+ - from: "claudebox.sh"
+ to: "bwrap"
+ via: "exec bwrap with --clearenv"
+ pattern: "exec bwrap.*--clearenv"
+ - from: "claudebox.sh"
+ to: "claude"
+ via: "CLAUDE_BIN resolved from host PATH before clearenv"
+ pattern: "CLAUDE_BIN=.*command -v claude"
+---
+
+
+Create the complete claudebox Nix flake and shell script that launches Claude Code inside a bubblewrap sandbox with full environment isolation, filesystem isolation, secret hiding, git support, and tool provisioning.
+
+Purpose: This is the entire deliverable for Phase 1 -- a working `claudebox` command.
+Output: `flake.nix` and `claudebox.sh` in the project root.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/STATE.md
+@.planning/phases/01-minimal-viable-sandbox/01-CONTEXT.md
+@.planning/phases/01-minimal-viable-sandbox/01-RESEARCH.md
+
+
+
+
+
+ Task 1: Create flake.nix with all inputs and writeShellApplication
+ flake.nix
+
+ .planning/phases/01-minimal-viable-sandbox/01-RESEARCH.md
+
+
+Create `flake.nix` in the project root with the following exact structure:
+
+```nix
+{
+ description = "claudebox - sandboxed Claude Code";
+
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+ nix-index-database = {
+ url = "github:nix-community/nix-index-database";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+ };
+
+ outputs = { self, nixpkgs, nix-index-database, ... }:
+ let
+ system = "x86_64-linux";
+ pkgs = nixpkgs.legacyPackages.${system};
+ comma-with-db = nix-index-database.packages.${system}.comma-with-db;
+ in {
+ packages.${system} = {
+ claudebox = pkgs.writeShellApplication {
+ name = "claudebox";
+ runtimeInputs = [
+ pkgs.bubblewrap
+ pkgs.coreutils
+ pkgs.git
+ pkgs.curl
+ pkgs.jq
+ pkgs.ripgrep
+ pkgs.fd
+ pkgs.nix
+ comma-with-db
+ pkgs.bash
+ pkgs.nodejs
+ ];
+ text = builtins.readFile ./claudebox.sh;
+ };
+ default = self.packages.${system}.claudebox;
+ };
+ };
+}
+```
+
+Key points per user decisions:
+- Per D-02: `comma-with-db` comes from the `nix-index-database` flake, using `packages.${system}.comma-with-db` (not legacyPackages).
+- Per NIX-01/NIX-02: Flake with pinned inputs. `nixpkgs.follows` ensures single nixpkgs instance.
+- Per NIX-03: `default` package alias so `nix run` and `nix profile install` work.
+- Per SAND-01/SAND-10: `writeShellApplication` produces the binary and wires runtimeInputs into PATH.
+- Claude Code is NOT in runtimeInputs -- it's discovered from host PATH at runtime (see Research Pattern 5).
+
+
+ grep -q 'writeShellApplication' flake.nix && grep -q 'comma-with-db' flake.nix && grep -q 'nix-index-database' flake.nix && grep -q 'builtins.readFile ./claudebox.sh' flake.nix && echo "PASS" || echo "FAIL"
+
+
+ - flake.nix contains `description = "claudebox - sandboxed Claude Code"`
+ - flake.nix contains `nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"`
+ - flake.nix contains `nix-index-database.packages.${system}.comma-with-db`
+ - flake.nix contains `name = "claudebox"`
+ - flake.nix contains `builtins.readFile ./claudebox.sh`
+ - flake.nix contains all 11 runtimeInputs: bubblewrap, coreutils, git, curl, jq, ripgrep, fd, nix, comma-with-db, bash, nodejs
+ - flake.nix contains `default = self.packages.${system}.claudebox`
+
+ flake.nix exists with correct flake structure, all runtime dependencies, and readFile of claudebox.sh
+
+
+
+ Task 2: Create claudebox.sh with complete bwrap sandbox logic
+ claudebox.sh
+
+ .planning/phases/01-minimal-viable-sandbox/01-RESEARCH.md
+ .planning/phases/01-minimal-viable-sandbox/01-CONTEXT.md
+
+
+Create `claudebox.sh` in the project root. This is the shell script body read by `writeShellApplication` (which adds `set -euo pipefail` and prepends runtimeInputs to PATH automatically). The script must implement the following sections in order:
+
+**Section 1: Resolve claude binary from host PATH (before clearenv strips it)**
+
+```bash
+CLAUDE_BIN=$(command -v claude) || {
+ echo "error: claude not found in PATH" >&2
+ echo "Install Claude Code first: https://docs.anthropic.com/en/docs/claude-code" >&2
+ exit 1
+}
+```
+
+**Section 2: Capture sandbox PATH**
+
+The runtimeInputs-constructed PATH is available as `$PATH` at this point. Capture it for passing into the sandbox:
+```bash
+SANDBOX_PATH="$PATH"
+```
+
+**Section 3: Record CWD**
+
+```bash
+CWD=$(pwd)
+```
+
+**Section 4: Ensure ~/.claudebox exists**
+
+```bash
+mkdir -p "$HOME/.claudebox"
+```
+
+**Section 5: Generate minimal .gitconfig (per D-05)**
+
+Read host git identity, write a temp .gitconfig, set up cleanup trap:
+```bash
+GIT_NAME=$(git config --global user.name 2>/dev/null || echo "Claude User")
+GIT_EMAIL=$(git config --global user.email 2>/dev/null || echo "claude@localhost")
+
+GITCONFIG_TMP=$(mktemp)
+trap 'rm -f "$GITCONFIG_TMP"' EXIT
+
+cat > "$GITCONFIG_TMP" <
+
+ grep -q 'exec bwrap' claudebox.sh && grep -q 'clearenv' claudebox.sh && grep -q 'CLAUDE_BIN' claudebox.sh && grep -q 'CLAUDEBOX_EXTRA_ENV' claudebox.sh && grep -q 'GITCONFIG_TMP' claudebox.sh && grep -q 'dangerously-skip-permissions' claudebox.sh && echo "PASS" || echo "FAIL"
+
+
+ - claudebox.sh does NOT contain `#!/bin/bash` or `set -euo pipefail` (writeShellApplication adds these)
+ - claudebox.sh contains `CLAUDE_BIN=$(command -v claude)` with error handling on failure
+ - claudebox.sh contains `SANDBOX_PATH="$PATH"`
+ - claudebox.sh contains `mkdir -p "$HOME/.claudebox"`
+ - claudebox.sh contains git config reading: `git config --global user.name` and `git config --global user.email`
+ - claudebox.sh contains `GITCONFIG_TMP=$(mktemp)` and `trap 'rm -f "$GITCONFIG_TMP"' EXIT`
+ - claudebox.sh contains `safe.directory = *` in the generated gitconfig
+ - claudebox.sh contains ENV_ARGS array with --setenv for HOME, USER, PATH, SHELL, TMPDIR, XDG_RUNTIME_DIR, NIX_SSL_CERT_FILE, SSL_CERT_FILE
+ - claudebox.sh contains HOST_ALLOWLIST with TERM, EDITOR, LANG, LC_ALL, ANTHROPIC_API_KEY
+ - claudebox.sh contains CLAUDEBOX_EXTRA_ENV parsing with `IFS=',' read -ra EXTRAS`
+ - claudebox.sh contains `exec bwrap` with `--clearenv`
+ - claudebox.sh contains `--tmpfs /` before any other mount
+ - claudebox.sh contains `--ro-bind /nix/store /nix/store`
+ - claudebox.sh contains `--bind /nix/var/nix /nix/var/nix` (rw, not ro-bind)
+ - claudebox.sh contains `--ro-bind /etc/resolv.conf /etc/resolv.conf`
+ - claudebox.sh contains `--ro-bind /etc/ssl /etc/ssl` AND `--ro-bind /etc/static /etc/static`
+ - claudebox.sh contains `--ro-bind /etc/nix /etc/nix`
+ - claudebox.sh contains `--ro-bind /etc/passwd /etc/passwd` and `--ro-bind /etc/group /etc/group`
+ - claudebox.sh contains `--symlink` for `/usr/bin/env`
+ - claudebox.sh contains `--tmpfs "$HOME"` BEFORE the claudebox and CWD bind mounts
+ - claudebox.sh contains `--bind "$HOME/.claudebox" "$HOME/.claude"`
+ - claudebox.sh contains `--ro-bind "$GITCONFIG_TMP" "$HOME/.gitconfig"`
+ - claudebox.sh contains `--bind "$CWD" "$CWD"` and `--chdir "$CWD"`
+ - claudebox.sh contains `-- "$CLAUDE_BIN" --dangerously-skip-permissions "$@"` at the end
+ - claudebox.sh does NOT contain any mount of ~/.ssh, ~/.gnupg, ~/.aws, ~/.config/gcloud, or /var/lib/tailscale
+
+ claudebox.sh exists with complete bwrap invocation covering all SAND-*, TOOL-*, GIT-*, and UX-06 requirements
+
+
+
+
+
+## Trust Boundaries
+
+| Boundary | Description |
+|----------|-------------|
+| Host -> Sandbox | Environment variables cross from untrusted host env into sandbox via allowlist |
+| Host -> Sandbox | Filesystem paths cross via explicit bind mounts |
+| Sandbox -> Host | CWD is mounted read-write, so Claude can modify project files (intended) |
+
+## STRIDE Threat Register
+
+| Threat ID | Category | Component | Disposition | Mitigation Plan |
+|-----------|----------|-----------|-------------|-----------------|
+| T-01-01 | Information Disclosure | Environment variables | mitigate | `--clearenv` + explicit allowlist. Only SAND-03 vars pass through. CLAUDEBOX_EXTRA_ENV is user-opt-in. |
+| T-01-02 | Information Disclosure | Secret filesystem paths | mitigate | tmpfs root + tmpfs HOME. Only explicit bind mounts visible. ~/.ssh, ~/.gnupg, ~/.aws never mounted. Verify by absence in mount list. |
+| T-01-03 | Tampering | Host filesystem via CWD mount | accept | CWD is intentionally rw -- Claude needs to edit project files. Scope is limited to the single directory. |
+| T-01-04 | Information Disclosure | Git credential helpers | mitigate | Host ~/.gitconfig is NOT mounted. A minimal generated .gitconfig with only user.name, user.email, and safe.directory is used instead. No credential helper config enters sandbox. |
+| T-01-05 | Elevation of Privilege | Nix daemon socket access | accept | Daemon socket is rw to allow `nix shell`. The daemon runs as root on host but nix client operations are normal user operations. Nix daemon has its own access controls. |
+| T-01-06 | Information Disclosure | /etc/passwd, /etc/group | accept | Read-only mount of user database. Contains usernames/UIDs only, no password hashes (those are in /etc/shadow which is not mounted). Required for basic tool functionality. |
+| T-01-07 | Spoofing | CLAUDE_BIN resolution | accept | claude binary is resolved from host PATH before sandbox. If attacker controls host PATH, they already have full host access. Not a sandbox boundary issue. |
+
+
+
+After both tasks complete:
+1. `nix flake check` passes (or at least doesn't error on flake structure)
+2. `grep -c 'exec bwrap' claudebox.sh` returns 1
+3. `grep -c 'clearenv' claudebox.sh` returns 1
+4. No secret paths appear in claudebox.sh mounts: `grep -E '\.ssh|\.gnupg|\.aws|gcloud|tailscale' claudebox.sh` returns nothing
+
+
+
+- flake.nix and claudebox.sh exist in project root
+- flake.nix defines claudebox as default package with all 11 runtimeInputs
+- claudebox.sh implements complete bwrap sandbox with env allowlist, filesystem isolation, git identity, and tool provisioning
+- All 24 phase requirements (SAND-01 through SAND-15, TOOL-01 through TOOL-03, GIT-01, GIT-02, NIX-01 through NIX-03, UX-06) are addressed
+
+
+
diff --git a/.planning/phases/01-minimal-viable-sandbox/01-02-PLAN.md b/.planning/phases/01-minimal-viable-sandbox/01-02-PLAN.md
new file mode 100644
index 0000000..dc89aee
--- /dev/null
+++ b/.planning/phases/01-minimal-viable-sandbox/01-02-PLAN.md
@@ -0,0 +1,208 @@
+---
+phase: 01-minimal-viable-sandbox
+plan: 02
+type: execute
+wave: 2
+depends_on: ["01-01"]
+files_modified: []
+autonomous: false
+requirements:
+ - NIX-03
+ - SAND-02
+ - SAND-03
+ - SAND-04
+ - SAND-05
+ - SAND-06
+ - SAND-09
+ - SAND-10
+ - SAND-12
+ - SAND-13
+ - SAND-14
+ - TOOL-01
+ - TOOL-02
+
+must_haves:
+ truths:
+ - "`nix build` succeeds and produces a claudebox binary"
+ - "claudebox launches and env inside sandbox contains only allowlisted vars"
+ - "Secret paths are invisible inside the sandbox"
+ - "DNS and SSL work (curl https succeeds)"
+ - "comma and nix shell can install packages"
+ - "Exit code passes through from claude to caller"
+ artifacts: []
+ key_links:
+ - from: "nix build result"
+ to: "claudebox binary"
+ via: "result/bin/claudebox symlink"
+ pattern: "result/bin/claudebox"
+---
+
+
+Build the claudebox flake and verify the sandbox works end-to-end through automated smoke tests and manual verification.
+
+Purpose: Confirm the sandbox actually isolates secrets, passes through tools, and runs Claude Code successfully.
+Output: Verified working claudebox command.
+
+
+
+@$HOME/.claude/get-shit-done/workflows/execute-plan.md
+@$HOME/.claude/get-shit-done/templates/summary.md
+
+
+
+@.planning/PROJECT.md
+@.planning/ROADMAP.md
+@.planning/phases/01-minimal-viable-sandbox/01-CONTEXT.md
+@.planning/phases/01-minimal-viable-sandbox/01-01-SUMMARY.md
+@flake.nix
+@claudebox.sh
+
+
+
+
+
+ Task 1: Build flake and run automated smoke tests
+
+
+ flake.nix
+ claudebox.sh
+
+
+Run the following commands sequentially, fixing any issues that arise:
+
+**Step 1: Build the flake**
+```bash
+cd /home/toph/code/tools/claudebox
+nix build
+```
+If this fails, read the error and fix `flake.nix` or `claudebox.sh` as needed. Common issues:
+- shellcheck errors in claudebox.sh (fix the shell code)
+- Missing flake.lock (nix build will create it on first run)
+- Package name mismatches (verify against nixpkgs)
+
+**Step 2: Verify the binary exists**
+```bash
+ls -la result/bin/claudebox
+```
+
+**Step 3: Run a minimal bwrap test without Claude**
+To test the sandbox without needing Claude, run just the bwrap portion to verify mounts and env isolation. Extract the bwrap invocation concept and test key properties:
+
+```bash
+# Test that the built script at least starts (will fail at claude lookup if claude not in PATH, that's ok)
+# Instead, test bwrap directly using the same flags pattern:
+
+# Test 1: Verify --clearenv produces empty env
+result/bin/claudebox 2>&1 || true
+# If claude is found, it will launch. If not, we get the expected error.
+```
+
+Since claudebox requires `claude` in PATH and will exec into it, automated testing is limited. The key automated checks are:
+
+1. `nix build` succeeds (shellcheck passes, all deps resolve)
+2. `result/bin/claudebox` exists and is executable
+3. The script content in the Nix store passes basic sanity: `cat result/bin/claudebox` shows the wrapper with correct PATH setup
+
+Run:
+```bash
+# Check the built wrapper contains expected runtimeInputs in PATH
+cat result/bin/claudebox | head -20
+```
+
+If `nix build` fails due to shellcheck issues in claudebox.sh, fix them. Common shellcheck fixes:
+- SC2086: Double-quote variable expansions
+- SC2034: Unused variables (may need `# shellcheck disable=SC2034` if intentional)
+- SC2155: Declare and assign separately
+
+After build succeeds, if `claude` is available on the host PATH, run a quick sandbox test:
+```bash
+# Quick test: launch claudebox with --help to verify it starts and exits cleanly
+result/bin/claudebox --help 2>&1 | head -5 || true
+```
+This should show Claude Code's help output if everything is wired correctly, or show a meaningful error.
+
+
+ test -x /home/toph/code/tools/claudebox/result/bin/claudebox && echo "PASS: binary exists" || echo "FAIL: binary missing"
+
+
+ - `nix build` exits 0 (no shellcheck errors, all deps resolve)
+ - `result/bin/claudebox` exists and is executable
+ - `flake.lock` exists (created by first build)
+ - The built wrapper script in the Nix store contains runtimeInputs PATH entries (visible in `cat result/bin/claudebox`)
+
+ nix build succeeds and produces an executable claudebox binary
+
+
+
+ Task 2: Manual sandbox verification
+
+ Present the verification checklist below to the user and wait for their confirmation that each check passes.
+ Complete claudebox sandbox wrapping Claude Code with environment isolation, filesystem isolation, secret hiding, git support, and tool provisioning
+
+1. Launch claudebox from a project directory:
+ ```
+ cd ~/some-project
+ /home/toph/code/tools/claudebox/result/bin/claudebox
+ ```
+
+2. Inside the Claude session, verify environment isolation:
+ - Ask Claude to run `env | sort` -- should show ONLY allowlisted vars (HOME, PATH, TERM, USER, SHELL, TMPDIR, etc.)
+ - Confirm NO appearance of: SSH_AUTH_SOCK, AWS_PROFILE, GITHUB_TOKEN, or any secret vars
+
+3. Verify filesystem isolation:
+ - Ask Claude to run `ls ~/.ssh` -- should fail (directory not found)
+ - Ask Claude to run `ls ~/.gnupg` -- should fail
+ - Ask Claude to run `ls ~/.aws` -- should fail
+ - Ask Claude to run `ls ~/.claude` -- should succeed (mapped from ~/.claudebox)
+
+4. Verify tools work:
+ - Ask Claude to run `git status` -- should work in the project dir
+ - Ask Claude to run `curl -s https://example.com | head -5` -- should return HTML (DNS + SSL work)
+ - Ask Claude to run `, jq --help | head -3` -- should install and run jq via comma
+ - Ask Claude to run `rg --version` -- should show ripgrep version
+
+5. Exit Claude (Ctrl+C or /exit) and verify:
+ - The shell returns to your normal prompt
+ - `echo $?` shows the exit code from Claude (typically 0)
+
+
+ echo "CHECKPOINT: requires human verification"
+
+ User confirms all sandbox isolation and tool provisioning checks pass
+ Type "approved" if all checks pass, or describe any issues found
+
+
+
+
+
+## Trust Boundaries
+
+| Boundary | Description |
+|----------|-------------|
+| Build output -> Runtime | Nix build produces the sandbox script; verification confirms it behaves as designed |
+
+## STRIDE Threat Register
+
+| Threat ID | Category | Component | Disposition | Mitigation Plan |
+|-----------|----------|-----------|-------------|-----------------|
+| T-01-08 | Information Disclosure | Env leak in built binary | mitigate | Manual verification (Task 2 step 2) confirms only allowlisted vars appear in `env` output inside sandbox |
+| T-01-09 | Information Disclosure | Secret path accessible | mitigate | Manual verification (Task 2 step 3) confirms ~/.ssh, ~/.gnupg, ~/.aws are not visible |
+
+
+
+1. `nix build` exits 0
+2. Human confirms env isolation (only allowlisted vars visible)
+3. Human confirms filesystem isolation (secret paths invisible)
+4. Human confirms tools work (git, curl, comma, ripgrep)
+5. Human confirms clean exit behavior
+
+
+
+- claudebox builds from the Nix flake without errors
+- Human verifies the sandbox isolates secrets and provides working tools
+- Phase 1 success criteria from ROADMAP.md are met
+
+
+