End-of-session: statusline + session-start integration, docs update

- context: claude-profile-modes updated to reflect current state (statusline
  and session-start auto-select done; next step is real launch test)
- FUTURE.md: remove two completed items (status-line, CLAUDE.md picker)
- README: add missing scripts (check-skills, gen-secret, mp3-to-mp4,
  split-wezterm, sync-repos) to scripts table
- session log 2026-04-12.003747.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Paul O'Reilly
2026-04-12 00:40:17 +12:00
parent 143b32597e
commit 340c40392a
5 changed files with 62 additions and 93 deletions

View File

@@ -2,90 +2,42 @@
## Status
**Built and tested via dryrun. NOT yet exercised in a real `claude` launch.**
**Core features shipped and pushed (commit 143b325). 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's done
## What was built
| Component | Path |
| Component | State |
|---|---|
| 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`.
| Profile + mode picker (phases 1-3) | Done, 37 dryrun assertions passing |
| 5 mode files with `escalates_to` frontmatter | Done |
| `active-mode.env` written on every launch | Done (includes `CLAUDE_ESCALATES_TO`) |
| statusline.sh — `[Sonnet→Opus] deep · topic` format | Done (reads `CLAUDE_CONFIG_DIR/active-mode.env`) |
| Root CLAUDE.md — auto-select project from cwd or `CLAUDE_PROJECT` | Done |
| Preset support (`presets.yaml`) | Done (example at `data/claude-profile/presets.yaml.example`) |
## 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).
1. **Install the symlink** (if not already done):
```bash
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:
- Mode body appears in system prompt (CLAUDE.md announces the mode)
- Status bar shows `[Haiku] chat` format
- `~/.claude-oreillyit/active-mode.env` is written with correct values
3. **Auto-select test:** launch from inside a project dir (`cd ~/dev/claude/small-scripts && claude-profile oreillyit --mode quick`) — should skip the project picker and announce "Auto-selected project small-scripts"
4. **Then `--mode deep`** to verify plan-mode auto-engagement and the `[Sonnet→Opus] deep · topic` status bar format
5. **If anything's off**, `tests/test-claude-profile.sh` is the fast feedback loop
## Follow-ups (sequenced)
## Remaining follow-ups (from FUTURE.md)
All in `FUTURE.md`. Suggested order:
1. **`bg-model-call` wrapper** — `deep` and `hybrid` modes reference it but it doesn't exist yet. Own spec + script entry.
2. **`switch mode` skill** — mid-session re-pick writes new `active-mode.env` for the next `/clear`. Lower priority.
3. **MiniMax inverted architecture** — long research project; requires token-budget sketch first.
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.
## Key gotchas
## 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.
- **statusline.sh is not in any git repo** — lives at `~/.claude/status/statusline.sh`. Changes are live immediately; no commit needed.
- **Root `~/dev/claude/CLAUDE.md` is also not git-tracked** — changes there are also immediately live.
- **`CLAUDE_CONFIG_DIR` must be exported** by claude-profile before `exec claude`. The statusline hook inherits it from the claude process environment.
- **`read -rp` under `set -e` exits silently if stdin is not a TTY.** The picker guards all interactive reads with `[[ -t 0 ]]`. See `memory/gotchas-bash.md`.