115 lines
5 KiB
Markdown
115 lines
5 KiB
Markdown
---
|
|
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 `<project>/.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. `<CANONICAL_ROOT>/.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 <binary>` — overrides `cmd` from config
|
|
- `--mount-home <subdir>` — appends to `mount_home` array
|
|
- `--path-add <dir>` — 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 `<CWD-root>/.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 `<CWD>/.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
|