code-review skill: forked children inherit the parent model with no routing, no cost gate on model-initiated invocation, user policy cannot reach them

Status Open
Reported on v2.1.267
Maintainer reply None cached
Activity 0 comments · opened Sep 10, 2026

Summary

The bundled code-review skill runs as a forked agent on the parent session's model and then dispatches its finder and verifier agents through the Agent tool with no model set. Every child inherits the parent model. In a session whose model is claude-fable-5-1, one model-initiated /code-review 223 high produced 10 fable agents (the fork plus 9 children) and consumed about 1.5M cache-creation tokens and 13.7M cache-read tokens in 13 minutes before I killed it, with no report produced.

Three separate problems combine here:

  1. Child agents are not model-routed. The skill prompt says "Run 8 independent finder angles via the Agent tool" and "run one verifier via the Agent tool" and never names a model. The fork's transcript shows 9 Agent tool calls, all subagent_type: "general-purpose", all with model absent. Mechanical finder and grep-style verification work ran on the most expensive tier. Related: #73323 asks for a model selector for this skill; this report shows that the default is the worst case, not a neutral one.
  2. The model can self-invoke the skill, and there is no consent or cost gate. The skill is exposed in the model's skill listing like any other. In my session the assistant invoked it on its own in response to "do a review (no changes)"; I did not type /code-review. The docs put the average cost at $15-25 per review (https://code.claude.com/docs/en/code-review.md#pricing) but nothing at invocation time surfaces that, and the Skill tool has no model parameter, so even a careful invocation cannot route it down. Related: #88003 (usage limits exhausted in 10 minutes), #90902 (fork chain token consumption).
  3. User-level rules and hooks cannot reach the children. My SessionStart hooks load an orchestration policy that says "never leave model= default; never run subagents on fable". Per the sub-agents docs a fork inherits the entire parent conversation, and the parent transcript confirms the policy was present. The fork still followed the skill prompt over the inherited policy. SubagentStart fired for the fork (I can see its additionalContext attachments) but no hook point lets a user reject an Agent call whose model is unset or equals a given tier.

Steps to reproduce

  1. Set "model": "claude-fable-5-1[1m]" (or any top-tier model) in ~/.claude/settings.json.
  2. Open a session on a repository with a large open PR (mine was 269 files).
  3. Ask, in plain words, for a review of the PR. Do not type /code-review.
  4. Observe the assistant invoke the code-review skill as a fork ("forked execution, running in the background").
  5. Inspect the fork's transcript under the session's tasks/ directory: every Agent tool_use input lacks model; every child transcript's assistant turns report the parent model.

Measured usage (from the JSONL transcripts, one row per assistant message id)

| Scope | Model | Cache-creation tokens | Cache-read tokens | Output tokens |
|---|---|---|---|---|
| code-review fork + 9 children | claude-fable-5-1 (all 10) | 1,533,907 | 13,651,479 | 11,939 |
| Same review done by 3 hand-routed agents | opus, opus, sonnet | 562,745 | 14,062,548 | 4,596 |

The fork tree ran 08:14 to 08:31 UTC and was stopped by hand before it reported. The three hand-routed agents finished and reported.

Expected behavior

  • Finder and verifier agents spawned by bundled skills should carry an explicit model, defaulting to a lower tier than the parent for mechanical angles, or honor a user-level setting for skill sub-agent model.
  • A model-initiated invocation of a skill that forks and fans out should require user confirmation, or at least print the documented cost band before running. A user-typed /code-review can stay as it is.
  • A hook point (for example PreToolUse on Agent with access to input.model, or a settings key) should let a user block sub-agent dispatch on a named model tier, and it should apply inside forks.
  • The per-skill disable switch should be documented. disableBundledSkills: true is documented but disables every bundled skill. A per-skill skillOverrides key appears to work (the binary recognizes it) but is not in the settings reference.

Environment

  • Claude Code 2.1.267, macOS (darwin 24.6.0)
  • ~/.claude/settings.json: "model": "claude-fable-5-1[1m]", "effortLevel": "high", "permissions.defaultMode": "auto"
  • Skill invoked with args 223 high

I have the fork and child transcripts and can share redacted excerpts on request.

🤖 Written by Claude Code on behalf of elaye

View original on GitHub ↗