From 454be67d570e7f98c6e85264e0a6a2ae64ae59e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20M=C3=BChl?= Date: Thu, 9 Apr 2026 09:52:14 +0200 Subject: [PATCH] docs: initialize project --- .planning/PROJECT.md | 80 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 .planning/PROJECT.md diff --git a/.planning/PROJECT.md b/.planning/PROJECT.md new file mode 100644 index 0000000..a783bd5 --- /dev/null +++ b/.planning/PROJECT.md @@ -0,0 +1,80 @@ +# 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. + +## Core Value + +Secrets never enter the Claude Code environment. If a secret is accessible inside the sandbox, it's a bug. + +## Requirements + +### Validated + +(None yet — ship to validate) + +### Active + +- [ ] Wrapper script that execs `claude --dangerously-skip-permissions` inside a bwrap sandbox +- [ ] Environment allowlist: start with empty env, explicitly pass only known-safe vars (HOME, PATH, TERM, EDITOR, LANG, etc.) +- [ ] Pre-launch env audit: before running, list all env vars being passed in so the user can review for secrets. Proceed on confirmation, abort on rejection +- [ ] `--yes` / `-y` flag to skip the env audit and launch immediately +- [ ] Filesystem isolation: only CWD mounted read-write, plus `~/.claudebox` mapped to `~/.claude` inside the sandbox +- [ ] Secret paths hidden: `~/.ssh`, `~/.gnupg`, `~/.config/gcloud`, `~/.aws`, Tailscale state, age keys — none of these visible inside the sandbox +- [ ] Minimal PATH: Nix store paths only — coreutils, git, curl, jq, ripgrep, fd, nix, comma +- [ ] Claude can self-install tools via `nix shell` or `, ` (comma) inside the sandbox +- [ ] Default prompt/instructions injected so Claude knows how to use nix/comma to get dev tools +- [ ] Works on endurance (NixOS desktop) + +### Out of Scope + +- Network isolation — trusting Claude Code's built-in proxy for domain allowlisting +- NixOS module form — this is a wrapper script derivation, not a services/programs module +- Configurable per-project profiles — v1 is one tool set, profiles come later +- Shareability — personal tool first, not designed for others yet + +## Context + +- Target machine: endurance (NixOS desktop) +- Claude Code already has bubblewrap sandboxing (`--sandbox`) but it doesn't control env vars or secret file visibility — that's claudebox's job +- bwrap is in nixpkgs, so the derivation uses `writeShellApplication` wrapping a bwrap invocation +- `~/.claudebox/` is the persistent config directory that gets bind-mounted as `~/.claude` inside the sandbox, keeping real `~/.claude` outside +- comma (`,`) is a tool that runs `nix shell nixpkgs# -c ` — lets Claude pull in any tool on demand without pre-declaring it +- The Nix store needs to be mounted read-only inside the sandbox for nix/comma to work + +## 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 | — Pending | +| Env allowlist over denylist | Denylist misses unknown vars; allowlist is secure by default | — Pending | +| comma for tool access | Claude can pull any tool on demand without pre-declaring PATH entries | — Pending | +| --dangerously-skip-permissions always | The bwrap sandbox IS the permission layer — Claude's prompts are redundant | — Pending | +| Pre-launch env audit | User reviews exactly what enters the sandbox, catches leaks before they happen | — Pending | + +## 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-09 after initialization*