`/effort` slider and welcome banner don't honor `CLAUDE_CODE_EFFORT_LEVEL=max`

Resolved 💬 4 comments Opened Apr 16, 2026 by renchris Closed May 27, 2026

Both UI surfaces read from settings.json.effortLevel — a 4-value enum that excludes max — instead of from the effective-effort resolver (wy6()Zj6()) that correctly applies max to every API request. Users who follow the documented env-var path to persist max see xhigh in the welcome banner and /effort slider and reasonably conclude their configuration is broken, even though the runtime is honoring it.

Env var is the only persistent path to max, yet the UI only reads settings

Claude Code 2.1.112 supports five effort levels (low | medium | high | xhigh | max), but the settings.json.effortLevel schema accepts only four — max is silently discarded via .catch(void 0). The CLAUDE_CODE_EFFORT_LEVEL env var, validated by a separate 5-value enum, is the sole persistent path to max. The effective-effort resolver wy6() reads the env var correctly and applies max to API calls. Two UI surfaces, however, never consult the env var path — creating a credibility gap where the runtime behavior and the visible feedback disagree.

Three UI paths silently drop max

1. Welcome banner is a hardcoded string

// cli.js — near "7.7 is here", customContent:
FS.createElement(T, {bold: true, color: "claude"},
  "Welcome to Opus 4.7 xhigh!")

No interpolation of current effort. This string renders unchanged whether the effective effort is low, high, xhigh, or max. Reads like launch-announcement marketing copy that wasn't updated when max shipped.

2. /effort slider seeds from settings-only state

// cli.js ~line 7094 — slider component boY(q)
let z = M8(moY)                              // Zustand selector
// moY: (q) => q.effortValue                 — only settings-derived
if (!z) { A = tsK; break q }                 // tsK = 3 → "xhigh"

// cli.js ~line 2898 — Zustand populator:
let O = Y.settings.effortLevel
let w = _.effortLevel
let $ = O !== w
...$ && w !== void 0 && { effortValue: w }   // ONLY from settings

effortValue is populated from settings.json.effortLevel only — never from Zj6() (env var) or wy6() (effective resolver). When the env var is max and settings has no effortLevel, effortValue is undefined → slider falls back to hardcoded index tsK = 3 = xhigh.

3. Settings schema silently rejects "max"

// cli.js:189
effortLevel: y.enum(["low","medium","high","xhigh"])
  .optional().catch(void 0)
// cli.js:899 — settings-write validator
function It6(q) {
  if (q === "low" || q === "medium" || q === "high" || q === "xhigh") return q
  return  // undefined — silently dropped
}

Any attempt to persist effortLevel: "max" — whether by editing settings.json manually or by /effort max followed by a hypothetical persist path — is silently coerced to undefined. The env var is forced to be the only persistence mechanism, and then the UI can't display what the env var produces.

Contrast with the runtime-side validators that DO accept max:

UI = ["low","medium","high","xhigh","max"]    // 5-value enum
Zj6() → id(process.env.CLAUDE_CODE_EFFORT_LEVEL)  // accepts "max"
wy6(model) → "max" when Zj6() = "max" and Ct6(model) = true
Ct6("claude-opus-4-7") = true  // opus-4-7 NOT in deny set d8z

Runtime correctly honors max; UI doesn't.

Three localized fixes restore UI/runtime parity

Fix 1 — Interpolate effort into the welcome banner (1-line change)

- "Welcome to Opus 4.7 xhigh!"
+ `Welcome to Opus 4.7 ${wy6(currentModel) ?? "xhigh"}!`

Minimal diff. Preserves the Opus 4.7 branding. Immediately surfaces the effective effort to every user.

Fix 2 — Cascade into the slider's initial state (localized change)

In the Zustand effortValue populator (~cli.js:2898), extend the seed order:

- ...$ && w !== void 0 && { effortValue: w }
+ { effortValue: w ?? Zj6() ?? bF1(currentModel) ?? undefined }

So effortValue resolves: persisted setting → env var → model default → undefined. Slider now highlights the effective effort and always shows the user-visible truth.

Fix 3 — Extend settings schema to accept max (invasive, root-cause fix)

Add "max" to both validators:

- effortLevel: y.enum(["low","medium","high","xhigh"])
+ effortLevel: y.enum(["low","medium","high","xhigh","max"])

  function It6(q) {
-   if (q === "low" || q === "medium" || q === "high" || q === "xhigh") return q
+   if (q === "low" || q === "medium" || q === "high" || q === "xhigh" || q === "max") return q
    return
  }

Eliminates the env-var workaround. Users can persist max in settings.json via /effort max → settings write. Product decision needed: is the 4-value cap intentional (e.g., "max is session-only by design")? If yes, skip Fix 3 and keep env var as the documented escape hatch — but Fix 1 and 2 remain necessary.

Reproduction

  1. echo 'export CLAUDE_CODE_EFFORT_LEVEL=max' >> ~/.zshrc && source ~/.zshrc
  2. Verify shell has it: env | grep CLAUDE_CODE_EFFORT_LEVEL → prints max
  3. Open a new terminal tab (to ensure .zshrc is freshly sourced) and run claude

Expected: Welcome banner says "Welcome to Opus 4.7 max!" and /effort slider highlights max.

Actual: Welcome banner says "Welcome to Opus 4.7 xhigh!" and /effort slider highlights xhigh.

Verified working: API requests ARE sent at max effort. wy6() correctly resolves to max. Only the UI is wrong.

Version

  • Claude Code 2.1.111 and 2.1.112
  • macOS 15.x / zsh / Opus 4.7 (1M context)
  • User has unpinOpus47LaunchEffort: true in ~/.claude.json (which is required for env var to be honored per wy6() logic)

Code reference map (cli.js)

| Concern | Line | Symbol |
|---------|------|--------|
| Settings schema (4-value) | 189 | effortLevel: y.enum([...]) |
| Settings-write validator (4-value) | 899 | It6() |
| Env-var reader (5-value) | 899 | Zj6() |
| Runtime normalizer (5-value) | — | id(), kh8(), UI |
| Effective-effort resolver | 899 | wy6(model, fallback) |
| Opus 4.7 pinned default | 899 | bF1(), unpinOpus47LaunchEffort |
| Max capability gate | 899 | Ct6(), deny set d8z |
| Zustand initial state | 2935 | effortValue: void 0 |
| Zustand populator (settings-only) | 2898 | — |
| /effort slash command handler | 7094 | VoY, qtK, koY |
| Slider initial-highlight logic | 7094 | slider picks tsK = 3 = xhigh on undefined |
| Welcome banner string | — | search "Welcome to Opus 4.7 xhigh!" |

Gaps / assumptions

  • Assumes the env-var path and the UI were implemented independently (the UI code predates env-var support), not deliberately decoupled.
  • Assumes Opus 4.7's launch banner was drafted before max existed and is safe to parameterize.
  • Workaround for users blocked by this: export CLAUDE_CODE_EFFORT_LEVEL=max and trust the effective behavior; the tool-use status bar (gH6 / NXz) is the only UI element that renders live effort, so glance there for confirmation during operations.

View original on GitHub ↗

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