opusplan plan mode skips Max-plan 1M auto-upgrade

Resolved 💬 3 comments Opened Apr 17, 2026 by calvindotsg Closed May 27, 2026

opusplan plan mode skips Max-plan 1M auto-upgrade

Version: claude 2.1.112 (also observed on 2.1.111)

Summary

The docs at https://code.claude.com/docs/en/model-config state: "On Max, Team, and Enterprise plans, Opus is automatically upgraded to 1M context with no additional configuration." This upgrade does not apply to opusplan plan mode.

Reproduction

  1. First-party Anthropic API user on a Max plan
  2. ~/.claude/settings.json has "model": "opusplan" and no ANTHROPIC_DEFAULT_OPUS_MODEL set
  3. Open a new Claude Code session and enter plan mode (Shift+Tab)
  4. Observed: the resolved model is claude-opus-4-7 (200K context)
  5. Expected: the resolved model is claude-opus-4-7[1m] (1M context)

Observable signals: the startup header suffix (1M context) is absent; /status shows claude-opus-4-7 without [1m].

Note: the "Welcome to Opus 4.7 xhigh!" welcome banner is a hardcoded string and is not a reliable signal — it does not reflect whether [1m] is active.

Code trace (2.1.112)

The opusplan router is om({permissionMode, mainLoopModel, exceeds200kTokens}). The plan-mode branch (verbatim from the binary):

if (ub() === "opusplan" && _ === "plan" && !K) return bh()

bh() is the opus model resolver. It returns ANTHROPIC_DEFAULT_OPUS_MODEL if set; otherwise returns the built-in claude-opus-4-7 constant. No [1m] is appended on either path.

The Max auto-upgrade function has the body pattern:

if (SD() && !pJ(H) && /opus-4-[67]/.test(H)) return H + "[1m]"

(SD() checks first-party Max eligibility; pJ(H) checks whether [1m] is already present.)

Grepping for call sites of this function in the 2.1.112 binary finds exactly 2 call sites, both on the subagent-resolution path. om() never calls it.

The main-loop default getter (dG()) does route through the Max auto-upgrade, but opusplan plan mode does not use dG() — it uses om() directly.

Result: SD() === true (first-party Max user), but plan mode still resolves to 200K because om() returns bh() without passing through the auto-upgrade wrapper.

Expected behavior

om() must wrap its opus return through the Max auto-upgrade function, consistent with how the /model opus, /model opus[1m], and subagent paths handle it.

Workaround

Set ANTHROPIC_DEFAULT_OPUS_MODEL="claude-opus-4-7[1m]" in ~/.claude/settings.json:

"env": {
  "ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4-7[1m]"
}

bh() returns the env var verbatim; om() in plan mode then yields claude-opus-4-7[1m]. The subagent auto-upgrade wrapper no-ops (because pJ("...[1m]") is true), so no double [1m] occurs.

Trade-off: this loses auto-latest — the env var must be manually bumped when a new Opus version ships.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗