anthropics / anthropics/claude-code
[FEATURE] `models:` frontmatter on .claude/rules/ — model-scoped instructions exist for subagents and for Claude Code's own prompt sections, but not for the user's instruction layer
- Dominant language
- Python
- Stars
- 145k
- Forks
- 23.1k
- PR merge metrics
- PR metrics pending
Description
Claude Code v2.1.220, Linux, first-party auth. Project CLAUDE.md files are
checked into source control and shared by a team whose members each choose
their own model, and /model can change the model mid-session.
## The need is already proven inside the product
Two existing mechanisms show that instruction text has to vary by model:
1. Subagent frontmatter documents a `model` field ("`sonnet`, `opus`, `haiku`,
`fable`, a full model ID (for example, `claude-opus-5`), or `inherit`") and
a per-agent `effort` field. Model-scoped configuration exists — one layer
below where shared instructions live.
2. Claude Code's own injected prompt sections are model-gated: #80988 documents
a section enabled only for claude-opus-5 via a capability flag, verified
against the shipped binary across versions. This issue is not about that
injection (#80988 covers it); we cite it as proof that Anthropic's own
instruction layer required model-gating to be correct.
The user's instruction layer — CLAUDE.md and .claude/rules/ — has the same
need and no mechanism.
## The docs' own guidance is mutually contradictory across models
Exhibit A, one page contradicting itself by model. Prompting best practices
recommends, for all current models: "Ask Claude to self-check. Append something
like 'Before you finish, verify your answer against [test criteria].'" The same
paragraph then adds: "Claude Opus 5 is the exception", and Prompting Claude
Opus 5 says to "remove them" because they cause over-verification. One
instruction, opposite verdicts, one CLAUDE.md loading for both.
Exhibit B, two official sample prompts pointing in opposite directions.
Prompting Claude Opus 4.8: "Spawn multiple subagents in the same turn when
fanning out across items or reading multiple files." Prompting Claude Opus 5:
"Delegate to a subagent only for large tasks that are genuinely independent
and parallelizable ... keep spawn counts low." No single wording satisfies both.
Exhibit C, where this stops being a quality question. Prompting Claude Fable 5
warns that instructions telling the model to "echo, transcribe, or explain its
internal reasoning as response text can trigger the reasoning_extraction
refusal category" — a declined request, not a degraded answer — and instructs
readers to "audit existing skills and system prompts" for such text. But Claude
Code has no migration moment (/model is a toggle, not a migration), and the
audit's findings have nowhere model-scoped to live: you cannot express "this
instruction, except on Fable 5." For prevalence: one widely vendored skill
(prompt-architect, MIT, 27 framework references) carries show-your-reasoning
instructions in 8 of its 27 files; any team that installed it and has one
member on Fable 5 is exposed, with no way to scope it.
## Why current mechanisms do not cover it
- .claude/rules/ does conditional loading, but the only axis is `paths:`.
- @imports load statically at launch.
- There is no $CLAUDE_MODEL; per the hooks reference, "Only SessionStart hooks
can receive a `model` field, and it is not guaranteed to be present."
- SessionStart does not re-fire on /model. This is not hypothetical: while
investigating this gap we switched models mid-session, and any
SessionStart-based profile would have been stale for the rest of the session.
- Self-selection ("if you are Opus 5, skip section 4") is unreliable: the model
cannot trustworthily identify its own model from inside the conversation.
- None of this helps a team-shared, source-controlled CLAUDE.md: a hook
workaround would have to be installed and trusted per developer, per machine.
## Ask
Add a `models:` frontmatter field to .claude/rules/, mirroring the existing
`paths:` field and accepting the same values the subagent `model` field
already accepts (`sonnet`, `opus`, `haiku`, `fable`, a full model ID, or
`inherit`). Evaluate it per session, and re-evaluate it when the model
changes mid-session — the same refresh the product already performs when it
re-reads project-root CLAUDE.md after /compact.
Both halves of this mechanism already exist in the product: rules already
load conditionally (on `paths:`), and model-scoped configuration already
exists (on subagents). This request is their composition.
When the field ships, the per-model prompting pages should say so: the
current "remove X" guidance assumes a model pinned per request, and a
shared, multi-model CLAUDE.md needs `models:` scoping instead of deletion.
Related: #80988 (model-gated injected section), #80646 (memory is advisory),
#81169 (CLAUDE.md precedence).
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by locating the .claude/rules/ loader that handles paths: and the subagent frontmatter handling for model values. Trace how project-root CLAUDE.md is refreshed after /compact and how /model changes the active model. Done means rules accept the documented models: values, load per session, and refresh when the model changes mid-session.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100