Files
small-scripts/context/claude-profile-modes.md
Paul O'Reilly 143b32597e Add claude-profile engagement mode picker with statusline and session-start integration
- claude-profile: phase 1-3 picker (profile, mode, launch) with preset support,
  dryrun, WezTerm theming, and --append-system-prompt mode body injection
- 5 mode files (chat/quick/deep/hybrid/orch) with YAML frontmatter + prose body;
  new escalates_to field drives statusline →Opus arrow for deep and hybrid
- statusline.sh reads CLAUDE_CONFIG_DIR/active-mode.env to show
  [Sonnet→Opus] deep · topic format when launched via claude-profile
- Root CLAUDE.md session-start: auto-selects project from cwd or CLAUDE_PROJECT
  in active-mode.env, skipping the interactive picker when context is clear
- Spec, tests (37 assertions, 9 test files, all passing), context docs, and
  preset example included

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 00:36:38 +12:00

92 lines
6.4 KiB
Markdown

# 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 <name>`, 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 "<full-model-id>" --append-system-prompt "<combined>" "${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.