Filed from you-are-hear on 2026-09-23. I checked which model its review bot runs now that Opus 5.5 has shipped, and it's Opus 5. The same fix is needed in every target.
The problem. blueprint/references/templates/claude-review.yml and templates/claude.yml ask the target to fill in model IDs ([<workhorse model id>], [<mid-tier model id>], and [<top-tier or workhorse model id>] in the review template's deep branch). Every target filled in a full ID. A full ID never moves, so each model release means a hand edit in every target, and those edits don't happen together:
| Target |
claude-code-action pin |
Claude Code it installs |
Review model / fallback (every branch, both files) |
| you-are-hear |
v1.0.206 |
2.1.246 |
claude-opus-5 / claude-sonnet-5 |
| echosphere |
v1.0.193 |
2.1.233 |
claude-opus-5 / claude-sonnet-5 |
| crease-data/crease |
v1.0.183 |
2.1.220 |
claude-opus-4-8 / claude-sonnet-4-6 |
crease's ID is behind the model its own action would pick: Claude Code 2.1.220 already resolves opus to Opus 5.
How an alias would resolve. The model-config page (code.claude.com/docs/en/model-config) says: "Aliases point to the recommended version for your provider and update over time. To pin to a specific version, use the full model name, for example claude-opus-5-5, or set the corresponding environment variable like ANTHROPIC_DEFAULT_OPUS_MODEL." Its provider table maps opus to Opus 5.5 and sonnet to Sonnet 5 on the Anthropic API. It adds, for opus only: "Before v2.1.280, opus resolved to Opus 5 on the Anthropic API, … from v2.1.219." The page gives no version history for sonnet, so what sonnet resolves to under an older pin isn't documented.
That resolution happens inside Claude Code, and each action release installs one fixed version of it: src/entrypoints/run.ts sets claudeCodeVersion (2.1.246 at v1.0.206, 2.1.273 at v1.0.226, 2.1.280 at v1.0.232), and base-action/action.yml carries the same value. The first release whose opus means Opus 5.5 is v1.0.232, published 2026-09-23.
The action removes --model from claude_args and passes it on as the SDK's model option (base-action/src/parse-sdk-options.ts, lines 204–205 and 317 at v1.0.206), so an alias reaches Claude Code unchanged. One exception: run.ts passes model: process.env.ANTHROPIC_MODEL as the explicit option, and that wins over --model. An ANTHROPIC_MODEL set on the action step would silently override the alias.
So an alias does not make the model float. It moves the pin from the model ID to the action's commit SHA, which Dependabot already maintains (.github/dependabot.yml.example: github-actions, monthly, cooldown: default-days: 7). A new model then arrives inside the action-bump PR, and no target needs a per-model edit. Bumping the action by hand stays available for anyone who doesn't want to wait.
The cooldown doesn't block this action. It releases almost daily (v1.0.206 on 2026-08-25 to v1.0.233 on 2026-09-23 is 27 releases in 29 days), so the newest release is nearly always inside a 7-day window. GitHub's options reference ("If a dependency's new release falls within its cooldown period, Dependabot skips updating the version for that dependency") doesn't say what happens then. The targets' own Dependabot PRs show it: Dependabot picks the newest release that is out of the window.
The worst case for a model bump is therefore about 37 days (a release six days before the 1st waits for the following 1st), plus the merge. It's often shorter, because a dependabot.yml change triggers a run and open PRs are re-resolved mid-month.
Proposal.
-
Templates. Replace the model-ID fill-ins with family aliases. In claude.yml: --model opus and --fallback-model sonnet. In claude-review.yml's three label branches: opus by default, sonnet under claude-fast-review, and opus at xhigh under claude-deep-review. Write the deep branch as opus, or fable for a project that escalates it, but not best. best resolves to Fable wherever it's available, which would make that escalation silent.
A project choosing fable should know two things:
- Before Claude Code 2.1.257,
fable means Fable 5, not 5.1.
- Through the Agent SDK, "Claude Code never shows the consent prompt. When a Fable request there would bill to usage credits, Claude Code bills it without asking."
The template comment should also say two things:
- The version now comes from the action pin, so the SHA bump is the model bump.
- Don't set
ANTHROPIC_MODEL on the step.
-
Record the resolved model where it can be found. With an alias, the review prompt's Model in use: ${{ steps.model.outputs.model }} reads opus, and the Dependabot diff shows only a SHA. The model does appear in the run log, because the action prints the system / init message, but the log expires and nobody reads it for this.
The action writes the raw SDK messages to its execution_file output as a JSON array (base-action/src/execution-file.ts). That array includes the init message, which carries model, and the result message, whose modelUsage keys name every model that ran, fallback and subagents included. In claude-review.yml, give the action step id: review (neither template's action step has an id today) and add:
- name: Record the resolved model
if: always() && steps.review.outputs.execution_file != ''
env:
EXECUTION_FILE: ${{ steps.review.outputs.execution_file }}
REQUESTED: ${{ steps.model.outputs.model }}
EFFORT: ${{ steps.model.outputs.effort }}
run: |
started=$(jq -r '[.[] | select(.type == "system" and .subtype == "init") | .model][0] // "unknown"' "$EXECUTION_FILE")
used=$(jq -r '[.[] | select(.type == "result") | (.modelUsage // {}) | keys[]] | unique | join(", ")' "$EXECUTION_FILE")
echo "Review model: started \`$started\`, used \`${used:-none recorded}\` (requested \`$REQUESTED\`, effort \`$EFFORT\`)" >> "$GITHUB_STEP_SUMMARY"
claude.yml has no model step, so its copy sets REQUESTED: opus and drops EFFORT. I tested the jq expressions against a sample array but haven't run them in a workflow. Two things are still unconfirmed: whether init.model shows the alias or the full ID when --model opus is passed, and whether the line lands in the job summary. The first target to adopt this should check both.
-
orchestration.md § Generation notes. Add a line: the review bot is the one dispatch that names a family alias rather than an ID. That is deliberate, and its version moves with the action pin. The action-bump PR that changes the resolved model is where the bot's effort settings get re-checked, because "effort names do not carry across models" (§ Generation notes; § Anti-patterns, "Reusing an effort table after a model change"). The templates must keep passing --effort explicitly, since "Opus 5.5 starts at medium unless one of the sources above sets a level for it".
Per target, after the kit change:
v1.0.226 installs Claude Code 2.1.273, where opus is still Opus 5. So whichever PR merges now, Opus 5.5 arrives with the next bump that reaches v1.0.232 or later, or with a hand bump.
Related: #52, closed by #57, which shipped these templates.
Filed from you-are-hear on 2026-09-23. I checked which model its review bot runs now that Opus 5.5 has shipped, and it's Opus 5. The same fix is needed in every target.
The problem.
blueprint/references/templates/claude-review.ymlandtemplates/claude.ymlask the target to fill in model IDs ([<workhorse model id>],[<mid-tier model id>], and[<top-tier or workhorse model id>]in the review template's deep branch). Every target filled in a full ID. A full ID never moves, so each model release means a hand edit in every target, and those edits don't happen together:claude-code-actionpinclaude-opus-5/claude-sonnet-5claude-opus-5/claude-sonnet-5claude-opus-4-8/claude-sonnet-4-6crease's ID is behind the model its own action would pick: Claude Code 2.1.220 already resolves
opusto Opus 5.How an alias would resolve. The model-config page (
code.claude.com/docs/en/model-config) says: "Aliases point to the recommended version for your provider and update over time. To pin to a specific version, use the full model name, for exampleclaude-opus-5-5, or set the corresponding environment variable likeANTHROPIC_DEFAULT_OPUS_MODEL." Its provider table mapsopusto Opus 5.5 andsonnetto Sonnet 5 on the Anthropic API. It adds, foropusonly: "Before v2.1.280,opusresolved to Opus 5 on the Anthropic API, … from v2.1.219." The page gives no version history forsonnet, so whatsonnetresolves to under an older pin isn't documented.That resolution happens inside Claude Code, and each action release installs one fixed version of it:
src/entrypoints/run.tssetsclaudeCodeVersion(2.1.246 at v1.0.206, 2.1.273 at v1.0.226, 2.1.280 at v1.0.232), andbase-action/action.ymlcarries the same value. The first release whoseopusmeans Opus 5.5 is v1.0.232, published 2026-09-23.The action removes
--modelfromclaude_argsand passes it on as the SDK'smodeloption (base-action/src/parse-sdk-options.ts, lines 204–205 and 317 at v1.0.206), so an alias reaches Claude Code unchanged. One exception:run.tspassesmodel: process.env.ANTHROPIC_MODELas the explicit option, and that wins over--model. AnANTHROPIC_MODELset on the action step would silently override the alias.So an alias does not make the model float. It moves the pin from the model ID to the action's commit SHA, which Dependabot already maintains (
.github/dependabot.yml.example:github-actions, monthly,cooldown: default-days: 7). A new model then arrives inside the action-bump PR, and no target needs a per-model edit. Bumping the action by hand stays available for anyone who doesn't want to wait.The cooldown doesn't block this action. It releases almost daily (v1.0.206 on 2026-08-25 to v1.0.233 on 2026-09-23 is 27 releases in 29 days), so the newest release is nearly always inside a 7-day window. GitHub's options reference ("If a dependency's new release falls within its cooldown period, Dependabot skips updating the version for that dependency") doesn't say what happens then. The targets' own Dependabot PRs show it: Dependabot picks the newest release that is out of the window.
The worst case for a model bump is therefore about 37 days (a release six days before the 1st waits for the following 1st), plus the merge. It's often shorter, because a
dependabot.ymlchange triggers a run and open PRs are re-resolved mid-month.Proposal.
Templates. Replace the model-ID fill-ins with family aliases. In
claude.yml:--model opusand--fallback-model sonnet. Inclaude-review.yml's three label branches:opusby default,sonnetunderclaude-fast-review, andopusatxhighunderclaude-deep-review. Write the deep branch asopus, orfablefor a project that escalates it, but notbest.bestresolves to Fable wherever it's available, which would make that escalation silent.A project choosing
fableshould know two things:fablemeans Fable 5, not 5.1.The template comment should also say two things:
ANTHROPIC_MODELon the step.Record the resolved model where it can be found. With an alias, the review prompt's
Model in use: ${{ steps.model.outputs.model }}readsopus, and the Dependabot diff shows only a SHA. The model does appear in the run log, because the action prints thesystem/initmessage, but the log expires and nobody reads it for this.The action writes the raw SDK messages to its
execution_fileoutput as a JSON array (base-action/src/execution-file.ts). That array includes theinitmessage, which carriesmodel, and theresultmessage, whosemodelUsagekeys name every model that ran, fallback and subagents included. Inclaude-review.yml, give the action stepid: review(neither template's action step has an id today) and add:claude.ymlhas nomodelstep, so its copy setsREQUESTED: opusand dropsEFFORT. I tested thejqexpressions against a sample array but haven't run them in a workflow. Two things are still unconfirmed: whetherinit.modelshows the alias or the full ID when--model opusis passed, and whether the line lands in the job summary. The first target to adopt this should check both.orchestration.md§ Generation notes. Add a line: the review bot is the one dispatch that names a family alias rather than an ID. That is deliberate, and its version moves with the action pin. The action-bump PR that changes the resolved model is where the bot's effort settings get re-checked, because "effort names do not carry across models" (§ Generation notes; § Anti-patterns, "Reusing an effort table after a model change"). The templates must keep passing--effortexplicitly, since "Opus 5.5 starts atmediumunless one of the sources above sets a level for it".Per target, after the kit change:
claude-review.ymllanded after the repo's only Dependabot run, so 2026-10-01 is its first chance.claude-review.ymlstill describes the pin as "the floating major tag", though it is a SHA.v1.0.226 installs Claude Code 2.1.273, where
opusis still Opus 5. So whichever PR merges now, Opus 5.5 arrives with the next bump that reaches v1.0.232 or later, or with a hand bump.Related: #52, closed by #57, which shipped these templates.