Files
chemenu/instructions/claude-code-model-selection.md
T
torben 2c4c2b1c7c
CI / verify (push) Failing after 57s
Release / release (push) Successful in 37s
stack: TOC-Pflicht fuer Referenzdateien ueber 100 Zeilen (docs toc); session-setup.md/gates.md nennen die tatsaechliche Budget-Ausnahmeliste (schliesst #73, #76)
Files changed:
- AGENTS.md
- CHANGES.md
- VERSION
- instructions/CONTRACT.md
- instructions/capture-session.md
- instructions/claude-code-model-selection.md
- instructions/dev/issue-tracking.md
- instructions/dev/testing-conventions.md
- instructions/dev/version-parts.md
- instructions/evolve-subtypes.md
- instructions/gates.md
- instructions/german-terminology.md
- instructions/ingest-large-tree.md
- instructions/kb-profiles.md
- instructions/link-taxonomy.md
- instructions/mcp-read-server.md
- instructions/migrate-corpus.md
- instructions/migrations/3.0.0-authoring-conventions.md
- instructions/migrations/4.0.0-link-taxonomy.md
- instructions/private-instance.md
- instructions/session-setup.md
- instructions/setup-instance.md
- kb/CONTRACT.md
- kb/CONVENTIONS.md
- kb/concepts/COLLECTION.md
- raw/CONTRACT.md
- tools/CONTRACT.md
- tools/chemenu/commands/docs_verify.py
- tools/chemenu/commands/instructions_cmd.py
- tools/chemenu/tests/test_docs_verify.py
- tools/chemenu/tests/test_instructions_cmd.py
- tools/chemenu/tests/test_toc.py
- tools/chemenu/toc.py
- types/type-spec.md
2026-09-09 20:38:42 +02:00

135 lines
8.2 KiB
Markdown

---
type: types/instruction.md
name: claude-code-model-selection
description: Which Claude model and effort level to run a Claude Code session, a spawned subagent, or a /code-review pass at for a given task in this repo.
---
# Pick the Claude model and effort level for the task at hand
Scale the model and effort to **what catches a mistake in this part of the work** - not to how
important the task feels, and not to its name. Running everything at the most capable model and
highest effort is safe but wasteful: the gates in [gates.md](gates.md) are enforced in code, not
by model judgment, so a weaker model cannot bypass them - it can only do a worse job of the calls
the gates don't cover.
That last clause is the whole rule, turned into a test. Where a check lives in code - `pytest`,
`docs verify`, `instructions verify`, CI, the gates - a weaker model's mistake surfaces and costs
one more round. Where the only enforcement is a session reading prose, the same mistake does not
surface at all: it ships, and it stays until someone happens to notice. The two are not the same
risk, and they should not get the same model. This is the argument
[docs/why-gates-are-code.md](../docs/why-gates-are-code.md) makes about gates, applied to who is
holding the keyboard.
Both directions cost something, which is why the axis matters rather than a blanket answer:
over-provisioning is a standing cost paid every session, while under-provisioning in an unchecked
phase is a silent error with a long tail. A corrective session, its bump, its CI runs and its
release together cost more compute than the model difference they were saving.
Claude-Code-only, and imported by CLAUDE.md rather than linked from AGENTS.md: the model names,
the `/code-review` effort dial and the `Agent` tool's `model:` override have no equivalent in the
other harnesses this repo supports (Codex CLI, GitHub Copilot CLI, Mistral Vibe). See
[instructions/CONTRACT.md](CONTRACT.md) for that split.
<!-- wikitool:toc -->
## Contents
- [When to run](#when-to-run)
- [Steps](#steps)
- [Decision points](#decision-points)
- [Scope](#scope)
<!-- /wikitool:toc -->
## When to run
Before spawning a subagent with an explicit `model:` override, before picking a `/code-review`
effort level, and when the user asks which model to use - or when the session's current model is
clearly mismatched to the task that just started.
Two of the three choices are the agent's to make; the session's own model is not. An agent cannot
switch the model it is running as - that is the user's `/model` - so step 1 is a recommendation
to *make*, not a setting to apply.
## Steps
1. **Recommend the session's model and effort by what catches a mistake in the phase it is in**,
when asked or when the mismatch is worth one sentence. Say it once and continue working either
way - a session that argues about its own model instead of doing the task has already cost
more than the model difference:
| Phase / task | What catches a mistake here | Model | Effort |
|---|---|---|---|
| `wiki-status`, simple `wiki-query` lookups | the answer is re-checkable against the corpus | Sonnet | default |
| `wiki-lint` | `lint` itself is the check | Sonnet | default |
| `wiki-ingest`, `wiki-manage`, judgment-heavy `wiki-query` | `lint` and `docs verify`, partly - the judgment about a claim is not covered | Sonnet | high |
| Stack dev: design, the version part, a boundary-crossing judgment | nothing - `docs verify` checks that a crossing documents itself, never that the part was right | Opus | high |
| Stack dev: code, tests, mechanical doc sync (command tables, contract rows) | `pytest`, `docs verify`, `instructions verify`, CI | Sonnet | high |
| Stack dev: closing an issue, `docs/` staleness, changelog prose | nothing, by construction - see below | Opus | high |
**Stack development is not one row**, which is the point of splitting it. The middle phase is
where the tokens are and where the checks are, so it is the phase worth running cheaper. The
two around it have no mechanical guard at all - a `docs/` page carries no normative sentence,
so there is nothing for `docs verify` to check ([AGENTS.md](../AGENTS.md) § File naming), and
the same holds for whatever tracker an instance keeps its open work in, which `wikitool`
deliberately knows nothing about. Those two phases are short - minutes, not hours - so keeping
them on the stronger model is cheap, and it protects the only work in the session that fails
silently.
**Effort is the cheaper lever than the model.** Reach for it first: `medium` deliberately does
not appear in this table for stack work, because multi-file consistency is exactly what a
reduced effort level gives up. Sonnet at `high` is the floor for anything touching more than
one file or a contract; `default` is for a single-file mechanical edit with a test behind it.
**A session cannot switch its own model**, so these rows only become real if someone offers the
switch at the moment the phase changes - once, without arguing about it, and never as a reason
to stop work that is already underway.
<!-- dist:strip-start -->
In this repo those moments are named, one per skill rather than both in one: `stack-dev`'s own
step 3 breaks for the first (design settled, work turns mechanical), and `stack-dev` itself
ends at the publish rather than asking the same session to break out of its own momentum a
second time. The second switch lives at the opening of `stack-close`, the skill `stack-dev`
hands off to once the publish succeeds (the unchecked tail begins) - a session has to invoke
it to reach that step at all, which is the point: nothing left to skip past mid-flow.
<!-- dist:strip-end -->
2. **Pick a spawned subagent's model by what it does**, via the `Agent` tool's `model:`
parameter - the values are `haiku`, `sonnet`, `opus`, `fable`:
- Read-only search/lookup (an `Explore` agent, or a `general-purpose` agent doing pure
retrieval): `model: "haiku"`. No judgment call is being delegated, only retrieval.
- A subagent that writes pages, reviews code, or decides something: leave `model:` off so it
inherits the session's model, chosen per step 1.
- A fork (`subagent_type: "fork"`) always inherits the parent session's model; a `model:`
override on a fork is ignored.
3. **Pick a `/code-review` effort level by blast radius, not by habit.** The levels are `low`,
`medium`, `high`, `xhigh`, `max` and `ultra` (multi-agent, in the cloud):
- A routine diff (a skill wording fix, an ordinary ingest's tool output): `low` or `medium` -
fewer, high-confidence findings are enough.
- Gate code (`run_budget.py`, `git_publish.py`, anything implementing the Mass-Update or
Iteration gates), the compiler, or a change about to ship in a version bump: `high` and up -
broader coverage is worth the cost when the blast radius of a missed bug is a safety gate.
- `ultra` is user-triggered and billed separately; recommend it, never assume it.
## Decision points
- **Task spans both a mechanical step and a judgment call?** Pick by the judgment call, not the
mechanical one - `wikitool` carries the mechanical part regardless of which model is
supervising it.
- **Unsure which row applies?** Default to Sonnet at high effort, not the most capable model at
the highest effort. Under-provisioning *where a check exists* costs one worse answer in one
session; reflexively over-provisioning is a standing cost paid every session.
- **Unsure whether the phase is checked?** Treat it as unchecked. The asymmetry is not symmetric:
a needless Opus phase costs money once, an unchecked Sonnet phase can ship something nobody
looks at again.
- **Mid-session and the phase changed, but nobody switched?** Do the work anyway - never block a
publish or an issue close on a model the session cannot change itself. Say which phase ran on
which model in the handover, so the gap is visible rather than silent.
## Scope
Does not apply to non-Claude-Code harnesses - see the note above; a follow-up issue tracks
whether and how they should decide this differently. Does not set the classifier model behind
Claude Code's own `auto` permission mode - that is a harness internal, not a per-task choice
this repo controls.