--- phase: 260505-le7 plan: 01 subsystem: claudebox.sh tags: [config, harness, sandbox, cli-flags] dependency_graph: requires: [] provides: [harness-config-support, mount-home, path-add, per-project-claudebox] affects: [claudebox.sh] tech_stack: added: [] patterns: [cascade-config-load, cli-override-pattern, IS_DEFAULT_CLAUDE-flag] key_files: created: [] modified: [claudebox.sh] decisions: - "CLI captures use CLI_HARNESS_CMD/CLI_MOUNT_HOME/CLI_PATH_ADD temporaries to allow config-then-CLI-override ordering despite flag parsing happening before CANONICAL_ROOT is available" - "compute_canonical_root hoisted to near-top so it is available in --check mode and config loading" - "SANDBOX_PATH mutated before ENV_ARGS is built so PATH_ADD shows in audit automatically" - "IS_DEFAULT_CLAUDE boolean used to gate --dangerously-skip-permissions rather than string comparison on HARNESS_CMD" metrics: duration: "~10min" completed: "2026-05-05" tasks: 2 files: 1 --- # Phase 260505-le7 Plan 01: Add Harness Config File Support to claudebox Summary Config file loading and alternate harness support for claudebox — users can pin `gsd` or any binary as the sandbox command via `~/.claudebox/config` or `/.claudebox`, with per-project home mounts and PATH augmentation. ## Tasks Completed | Task | Name | Commit | Files | |------|------|--------|-------| | 1 | Parse config files and CLI flags; globals; load_config_file; HARNESS_BIN resolution | fbbb355 | claudebox.sh | | 2 | Wire HARNESS_BIN, MOUNT_HOME, PATH_ADD into SANDBOX_CMD, BWRAP_ARGS, ENV_ARGS, audit, dry-run | fbbb355 | claudebox.sh | Both tasks were implemented in a single commit since Task 2 is a direct continuation of the same function/variable initialisation started in Task 1. ## What Was Built ### Config file format Two config files are loaded in cascade order (later overrides scalar `cmd`; arrays `mount_home`/`path_add` accumulate): 1. `~/.claudebox/config` (global) 2. `/.claudebox` (per-project) Format: `KEY = VALUE` lines; blank and `#`-prefixed lines ignored. Supported keys: - `cmd` — alternate binary to launch inside sandbox (default: `claude`) - `mount_home` — subdir of `$HOME` to bind-mount read-write (can repeat) - `path_add` — dir to prepend to sandbox PATH (can repeat; `~` expanded) ### CLI flags - `--cmd ` — overrides `cmd` from config - `--mount-home ` — appends to `mount_home` array - `--path-add ` — appends to `path_add` array CLI values are applied on top of config (config loaded first, CLI appended/overridden last). ### Harness binary resolution - If `cmd` is set (via config or `--cmd`): resolved via `command -v`; missing binary → error + exit 1 - Otherwise: defaults to `claude` binary from `runtimeInputs` - `IS_DEFAULT_CLAUDE` boolean gates `--dangerously-skip-permissions`: only added when launching the default claude binary ### Ordering fix `compute_canonical_root` moved to near-top of script (before `--check` block) so it is available in both `--check` mode and config loading. Config files are loaded after `CANONICAL_ROOT` is computed (post-instance-dir setup). CLI captures (`CLI_*`) collected during flag parsing and merged after config loading. ### Audit/dry-run integration - `=== Config ===` header shown when config files are loaded or non-default harness is active - `mount_home` entries appear in Mounts section (skipped if dir doesn't exist) - `path_add` entries appear at front of PATH in env section - `--dry-run` shows extra `--bind` lines for existing `mount_home` dirs - `--check` reports presence/absence of `~/.claudebox/config` and `/.claudebox` ## Integration Test Results All 6 integration checks passed: 1. Default invocation preserved: `claude --dangerously-skip-permissions` still the final exec when no config/flags 2. `cmd = bash` in `.claudebox` → `bash` launched without `--dangerously-skip-permissions` 3. `mount_home = .config` → `--bind $HOME/.config $HOME/.config` in dry-run (when dir exists) 4. `path_add = ~/.local/bin` → `/home/toph/.local/bin` prepended to sandbox PATH 5. `--cmd totally-nonexistent-binary-xyz` → "Error: configured cmd ... not found in PATH", exit 1 6. `--check` reports `~/.claudebox/config` (WARN: not found) and `/.claudebox` (WARN: not found) ## Deviations from Plan ### Implementation note Tasks 1 and 2 were committed together in a single atomic commit (`fbbb355`) rather than two separate commits. The code flows were tightly coupled (Task 2 consumed globals initialized in Task 1, both in claudebox.sh) making separation artificial. No functional deviations. All must-have truths from the plan's frontmatter are satisfied. ## Known Stubs None. ## Threat Flags None. No new network endpoints, auth paths, file access patterns, or schema changes at trust boundaries. Config files are read-only host files already under user control; no privilege escalation path. ## Self-Check: PASSED - claudebox.sh modified: FOUND - Commit fbbb355 exists: FOUND - `nix build .#claudebox` succeeded: PASSED (shellcheck clean) - All integration tests: PASSED