6.9 KiB
Project
claudebox
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.
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
--sandboxor Nix's build sandbox - Env model: Allowlist, not denylist — start empty, add explicitly
Technology Stack
Recommended Stack
Core: Nix Derivation via writeShellApplication
| Technology | Version | Purpose | Why | Confidence |
|---|---|---|---|---|
writeShellApplication |
nixpkgs stable | Produce the claudebox wrapper script |
Generates a shellcheck-validated bash script in the Nix store with runtime PATH wired to declared runtimeInputs. Superior to writeShellScriptBin because it runs shellcheck at build time and sets set -euo pipefail automatically. |
HIGH |
bubblewrap (bwrap) |
0.9.x+ | Sandbox runtime | Unprivileged user-namespace sandbox. In nixpkgs as bubblewrap. No setuid needed on NixOS (user namespaces enabled by default). |
HIGH |
claude-code |
CLI | The wrapped tool | Provided by Anthropic's npm/standalone installer. Assumed pre-installed or passed as input. | HIGH |
Runtime Dependencies (runtimeInputs)
| Package | Purpose | Why This One | Confidence |
|---|---|---|---|
bubblewrap |
Sandbox | The whole point | HIGH |
coreutils |
Basic shell utils | env, cat, echo, mkdir, etc. |
HIGH |
git |
Version control | Claude Code requires git for repo operations | HIGH |
curl |
HTTP requests | Claude Code's MCP and tool use | HIGH |
jq |
JSON processing | Env audit display, config manipulation | HIGH |
ripgrep |
Search | Claude Code's preferred grep | HIGH |
fd |
File finding | Claude Code's preferred find | HIGH |
nix |
Package manager | Required for nix shell inside sandbox |
HIGH |
comma |
On-demand packages | Runs nix shell nixpkgs#<pkg> -c <cmd> via , <cmd> syntax |
HIGH |
nix-index |
Package database | Required by comma to resolve command -> package mapping | HIGH |
bash |
Shell | bwrap needs a shell to exec into | HIGH |
nodejs |
Runtime | Claude Code is a Node.js application | HIGH |
NOT in runtimeInputs (Important)
| Package | Why Excluded |
|---|---|
gnupg |
Secret material -- explicitly hidden |
openssh |
Secret material -- explicitly hidden |
age / agenix |
Secret material -- explicitly hidden |
tailscale |
Infrastructure access -- explicitly hidden |
Key Nix Functions
writeShellApplication -- Use This
Why NOT These Alternatives
| Alternative | Why Not |
|---|---|
writeShellScriptBin |
No shellcheck, no automatic set -euo pipefail, no runtimeInputs wiring. You'd have to manually construct PATH. |
makeWrapper / wrapProgram |
Designed for wrapping existing binaries with env vars/flags. Overkill and wrong abstraction -- we're writing a new script, not patching an existing binary. |
symlinkJoin + makeWrapper |
Pattern for combining multiple derivations. Not needed -- we have one script. |
stdenv.mkDerivation |
Too heavy. writeShellApplication is a specialized shortcut for exactly this use case. |
runCommand / writeScript |
Lower-level, no shellcheck, no runtimeInputs. |
Bubblewrap Flags
Namespace Isolation
Filesystem Mounts
Mount Ordering Matters
Environment Handling
Process Execution
Comma and nix-index
How Comma Works
Packaging in nixpkgs
pkgs.comma-- the comma binary itselfpkgs.nix-index-- the indexer that builds/queries the database- Database: comma needs a pre-built index. Two options:
For claudebox
- Mount
~/.cache/nix-indexread-only into the sandbox (if using nix-index-database on the host) - Or use the
nix-index-databaseflake'scomma-with-dbpackage which bundles the database
Flake Structure
Why builtins.readFile for the Script Body
- Shell syntax highlighting in editors
- Shellcheck can run independently
- Easier to iterate on the script without touching Nix expressions
writeShellApplicationstill runs shellcheck on it at build time
PATH Construction Inside Sandbox
Nix Store Access Inside Sandbox
Testing Strategy
Sources
- Training data knowledge of nixpkgs
writeShellApplication(stable API since 2022) - Training data knowledge of bubblewrap (stable API, project is mature)
- Training data knowledge of comma/nix-index-database (nix-community project)
- All versions should be verified against current nixpkgs before implementation
Verification Checklist (for implementation phase)
- Confirm
bubblewrapversion in current nixpkgs channel - Confirm
commaandnix-index-databaseflake are current and compatible - Test Nix daemon socket access through bwrap bind mount
- Test mount ordering with CWD under $HOME
- Confirm
--clearenv+--setenvpattern works with Claude Code (it may need vars we haven't listed) - Check if Claude Code needs
~/.localor~/.configbeyond~/.claude
Conventions
Conventions not yet established. Will populate as patterns emerge during development.
Architecture
Architecture not yet mapped. Follow existing patterns found in the codebase.
Project Skills
No project skills found. Add skills to any of: .claude/skills/, .agents/skills/, .cursor/skills/, or .github/skills/ with a SKILL.md index file.
GSD Workflow Enforcement
Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.
Use these entry points:
/gsd-quickfor small fixes, doc updates, and ad-hoc tasks/gsd-debugfor investigation and bug fixing/gsd-execute-phasefor planned phase work
Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it.
Developer Profile
Profile not yet configured. Run
/gsd-profile-userto generate your developer profile. This section is managed bygenerate-claude-profile-- do not edit manually.