Architecture, overview, homelab build plan, agent handbook, ADRs, and agent operating rules. All sensitive operational details sanitized (real IPs, hostnames, client names replaced with generic placeholders). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.2 KiB
ADR-001 — CLI Tool Persistence Pattern
Status: Accepted
Context
The AgentLab devcontainer uses Docker named volumes for config/auth persistence and bind mounts for the repo. Any tool installed manually into the container filesystem (e.g. via npm install -g) is lost on docker compose down && up because the writable container layer is discarded.
This caused Codex to fail silently after a container restart. The codex-config named volume correctly preserved ~/.codex/ (auth, config), but the binary was never added to bootstrap.sh. The result: auth survived, binary didn't, tool appeared broken.
Claude Code survived because its installer was added to bootstrap.sh at setup time. Codex was not.
Decision
Every CLI tool that must survive container rebuilds requires two things — both are mandatory, neither is sufficient alone:
| Part | What | Where |
|---|---|---|
| 1. Named volume | Persists auth/config (~/.TOOLNAME/) |
compose.yml |
| 2. Bootstrap step | Installs the binary idempotently | bootstrap.sh |
Missing either part = tool is half-set-up and will silently break on next rebuild.
Tool manifest
| Tool | Binary | Named volume | Bootstrap step |
|---|---|---|---|
| Claude Code | claude |
claude-config → ~/.claude |
✓ |
| Codex CLI | codex |
codex-config → ~/.codex |
✓ |
| Gemini CLI | gemini |
gemini-config → ~/.gemini |
✓ |
Consequences
bootstrap.shis the single executable source of truth for binary installation.compose.ymlis the single source of truth for named volumes.- Any agent setting up a new CLI tool MUST update both files AND this ADR before the setup is considered complete.
What does NOT need a bootstrap step
Tools installed in the Dockerfile (RUN instruction) are baked into the image and survive all rebuilds without a bootstrap step. Only tools installed at runtime (post-container-start) need a bootstrap step.
Adding a new tool — checklist
- Add named volume to
compose.yml(TOOLNAME-config → ~/.TOOLNAME) - Add idempotent install step to
bootstrap.sh - Add entry to the tool manifest table above
- Update
docs/bootstrap.mdwith the new tool - Run
bootstrap.shto verify the install succeeds