# claude-profile engagement modes ## Status **Built and tested via dryrun. NOT yet exercised in a real `claude` launch.** The feature ships as part of `scripts/claude-profile` (rewritten this session from 104 to ~280 lines). Spec is at `specs/claude-profile.spec.md`. All 37 dryrun assertions pass via `tests/test-claude-profile.sh`. Full test suite (`tests/run-all.sh`) is green: 8 of 8 test files passing. ## What was built | Component | Path | |---|---| | Spec | `specs/claude-profile.spec.md` | | Picker bash | `scripts/claude-profile` | | 5 mode files | `data/claude-profile/modes/{chat,quick,deep,hybrid,orch}.md` | | Preset example | `data/claude-profile/presets.yaml.example` | | Test script | `tests/test-claude-profile.sh` | The five modes: | Mode | Driver model | Async | For | |---|---|---|---| | `chat` | Haiku (`claude-haiku-4-5-20251001`) | no | No project, conversation only | | `quick` | Sonnet (`claude-sonnet-4-6`) | no | Single small focused job | | `deep` | Sonnet | yes | Hard design/debugging, plan + spec enforced, Opus via named workflows | | `hybrid` | Haiku | yes | Cheap driver, escalates to Opus/Sonnet subagents on demand | | `orch` | Sonnet | yes | Decompose work, dispatch container agents, auto-fires `/loop 2m /orchestrate` | ## What is NOT done 1. **Not symlinked into `~/sbin`.** The new script lives at `~/dev/claude/small-scripts/scripts/claude-profile` but is not yet on PATH. To install: ```bash ln -sf "$HOME/dev/claude/small-scripts/scripts/claude-profile" "$HOME/sbin/claude-profile" ``` 2. **Not exercised against real `claude`.** Dryrun confirms the resolved values; an actual launch (e.g. `claude-profile oreillyit --mode quick` or `--mode chat`) is the first thing the next session should try. 3. **Presets file not installed.** Example template is at `data/claude-profile/presets.yaml.example`. To use presets, copy to `~/.claude-oreillyit/presets.yaml` and edit. 4. **CLAUDE.md does not yet read `active-mode.env`.** When a real launch happens with `--project `, the existing CLAUDE.md project picker will still appear and the user has to confirm the same project. This is the first follow-up listed below. ## How the runtime contract works 1. `claude-profile` resolves the profile, mode, and (for some modes) follow-up answers. 2. Writes `$CLAUDE_CONFIG_DIR/active-mode.env` with all resolved values (machine-readable, key=value). 3. Writes `$CLAUDE_CONFIG_DIR/last-mode` with the mode name (used as picker default next time). 4. Reads the mode file's body (everything after the YAML frontmatter), appends it to the context-load output, and passes the combined string via `--append-system-prompt`. 5. Resolves the mode's `driver` field through a hardcoded mapping table to a full Claude model ID. 6. Executes `claude --model "" --append-system-prompt "" "${pass-through-args[@]}"`. The mode file's prose body is what tells the driver model how to behave (escalation rules, plan-mode triggers, async policy, status-line format, on-`/clear` behaviour). The frontmatter is parsed by bash for the launcher's own decision-making. ## Driver mapping (lives in the script as a constant) | Frontmatter `driver` | `--model` argument | |---|---| | `haiku` | `claude-haiku-4-5-20251001` | | `sonnet` | `claude-sonnet-4-6` | | `opus` | `claude-opus-4-6` | | `opus-1m` | `claude-opus-4-6[1m]` | When new model versions ship, update the `DRIVER_MAP` associative array near the top of `scripts/claude-profile`. ## Next session — recommended order 1. **Install the symlink:** `ln -sf "$HOME/dev/claude/small-scripts/scripts/claude-profile" "$HOME/sbin/claude-profile"` 2. **Real-launch test:** `claude-profile oreillyit --mode chat` first (lowest blast radius — Haiku driver, no project, no async). Verify the mode body actually appears in the system prompt and the model behaves per the chat mode rules. 3. **Then `--mode quick`** with a real project to verify the Sonnet driver and the no-async constraints. 4. **Then `--mode deep`** to verify plan-mode auto-engagement and the named-workflow escalation table. 5. **If anything feels off,** `tests/test-claude-profile.sh` is the fast feedback loop — run it after any picker-bash changes. 6. **Once happy with v1,** start picking up follow-ups from `FUTURE.md` (see "Follow-ups" below). ## Follow-ups (sequenced) All in `FUTURE.md`. Suggested order: 1. **CLAUDE.md project picker integration** — read `CLAUDE_PROJECT` from `active-mode.env`, skip the duplicate picker. Quick win. 2. **Status-line script: render the mode tag** — the user explicitly asked for this; humans need to see the active mode at a glance. Lives in the claude-foundations repo, not small-scripts. 3. **`bg-model-call` wrapper** — referenced by the `deep` and `hybrid` modes but not yet built. Own small-scripts entry with its own spec and tests. 4. **`switch mode` skill** — mid-session re-pick. Lower priority; depends on whether mode switching turns out to be common in practice. 5. **MiniMax-driven inverted architecture** — biggest item, real research project. Token-budget sketch is the precondition before any code; if savings <30% it's not worth pursuing. ## Files touched this session - Created: `specs/claude-profile.spec.md`, `data/claude-profile/modes/{chat,quick,deep,hybrid,orch}.md`, `data/claude-profile/presets.yaml.example`, `tests/test-claude-profile.sh`, `context/claude-profile-modes.md` (this file) - Modified: `scripts/claude-profile` (rewritten), `README.md`, `CLAUDE.md`, `FUTURE.md` - Pruned: 4 reflected session logs from March (`memory/log/2026-03-17.*.md` and `2026-03-23.123551.md`) ## Key gotchas to remember - **`read -rp` under `set -e` exits silently if stdin is not a TTY.** Always guard interactive reads with `[[ -t 0 ]]` and provide a default. Without this, `--dryrun` hangs or silently exits when run from scripts. See `memory/gotchas-bash.md` for the broader pattern. - **`context-load` is on PATH via `~/sbin`, not a sibling of `claude-profile`.** The script uses `command -v context-load` first, with sibling fallback for testing isolation. - **Use full model IDs, not aliases.** The `claude-code-guide` agent only confirmed `sonnet`/`opus` aliases work; `haiku` is unverified. The mapping table uses full IDs throughout for safety and unambiguous version selection. - **`claude --model` is session-scoped.** Switching driver mid-session is impossible — it requires a relaunch. The `switch mode` follow-up works around this by writing a new `active-mode.env` for the next `/clear` to pick up.