# claudebox ## What This Is A Nix derivation that produces a `claudebox` wrapper script for Claude Code. It runs Claude inside a bubblewrap sandbox with an allowlisted environment, explicit filesystem mounts, and a minimal PATH — keeping SSH keys, GPG/age secrets, cloud tokens, and Tailscale state completely invisible to the AI agent. Includes pre-launch env audit, diagnostic modes, and sandbox-aware prompting. ## Core Value Secrets never enter the Claude Code environment. If a secret is accessible inside the sandbox, it's a bug. ## Requirements ### Validated - ✓ Wrapper script that execs `claude --dangerously-skip-permissions` inside a bwrap sandbox — v1.0 - ✓ Environment allowlist: start with empty env, explicitly pass only known-safe vars — v1.0 - ✓ Pre-launch env audit: list all env vars being passed in for user review — v1.0 - ✓ `--yes` / `-y` flag to skip the env audit — v1.0 - ✓ Filesystem isolation: only CWD mounted read-write, plus `~/.claudebox` mapped to `~/.claude` — v1.0 - ✓ Secret paths hidden: `~/.ssh`, `~/.gnupg`, `~/.config/gcloud`, `~/.aws`, Tailscale state, age keys — v1.0 - ✓ Minimal PATH: Nix store paths only — coreutils, git, curl, jq, ripgrep, fd, nix, comma — v1.0 - ✓ Claude can self-install tools via `nix shell` or `, ` (comma) — v1.0 - ✓ Default SANDBOX.md injected so Claude knows its capabilities and constraints — v1.0 - ✓ Works on endurance (NixOS desktop) — v1.0 - ✓ `--check` flag for environment diagnostics — v1.0 - ✓ `--dry-run` flag to print bwrap command without executing — v1.0 ### Active - [ ] Host `~/.claude` auth files mounted read-only for subscription passthrough - [ ] Per-project instance directories (`~/.claudebox/instances//.claude/`) — conversation history scoped per project - [ ] Named profiles (`--profile foo` / `CLAUDEBOX_PROFILE=foo`) defining env vars, mounts, packages, network tier - [ ] Profile storage at `~/.claudebox/profiles/` - [ ] Nix devshell/package injection per profile - [ ] Tiered network isolation: full, internet-only (unshare-net + slirp4netns), none (offline) ### Out of Scope - NixOS module form — this is a wrapper script derivation, not a services/programs module - Shareability — personal tool first, not designed for others yet - Domain-level network allowlists — tiered isolation (full/internet-only/none) is sufficient for now ## Context Shipped v1.0 with 399 LOC (350 shell + 49 Nix). Tech stack: Nix flake (`writeShellApplication`) + bubblewrap + comma-with-db. Runs on NixOS (endurance) with readlink -f workaround for symlink chain resolution. Non-NixOS support added via conditional `/etc/static` mount. ## Constraints - **Stack**: Nix derivation + shell script — no Docker, no systemd, no external dependencies beyond nixpkgs - **Sandbox**: Own bwrap call — not delegating to Claude Code's `--sandbox` or Nix's build sandbox - **Env model**: Allowlist, not denylist — start empty, add explicitly ## Key Decisions | Decision | Rationale | Outcome | |----------|-----------|---------| | Own bwrap over Claude's --sandbox | Full control over mounts, env, namespaces | ✓ Good | | Env allowlist over denylist | Denylist misses unknown vars; allowlist is secure by default | ✓ Good | | comma for tool access | Claude can pull any tool on demand without pre-declaring PATH entries | ✓ Good | | --dangerously-skip-permissions always | The bwrap sandbox IS the permission layer — Claude's prompts are redundant | ✓ Good | | Pre-launch env audit | User reviews exactly what enters the sandbox, catches leaks before they happen | ✓ Good | | readlink -f for binary resolution | NixOS profile symlinks aren't visible inside bwrap; resolve to real store paths | ✓ Good | | Claude Code via nix-claude-code flake | ryoppippi/nix-claude-code, not host PATH | ✓ Good | | SANDBOX.md as separate file with @import | Keeps user CLAUDE.md clean, sandbox instructions always fresh | ✓ Good | ## Current Milestone: v2.0 Network Isolation & Profiles **Goal:** Add tiered network isolation, per-project instance isolation, named profiles, and host auth passthrough. **Target features:** - Host auth passthrough (read-only mount of auth files from `~/.claude`) - Per-project instance isolation (conversation history scoped per project automatically) - Named profiles with env vars, mounts, packages, and network tier - Nix devshell injection per profile - Tiered network: full, internet-only (no LAN/Tailscale), none (offline) ## Evolution This document evolves at phase transitions and milestone boundaries. **After each phase transition** (via `/gsd-transition`): 1. Requirements invalidated? → Move to Out of Scope with reason 2. Requirements validated? → Move to Validated with phase reference 3. New requirements emerged? → Add to Active 4. Decisions to log? → Add to Key Decisions 5. "What This Is" still accurate? → Update if drifted **After each milestone** (via `/gsd-complete-milestone`): 1. Full review of all sections 2. Core Value check — still the right priority? 3. Audit Out of Scope — reasons still valid? 4. Update Context with current state --- *Last updated: 2026-04-10 after v2.0 milestone started*