claude-code - 💡(How to fix) Fix `/effort` slider and welcome banner don't honor `CLAUDE_CODE_EFFORT_LEVEL=max` [2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#49538Fetched 2026-04-17 08:38:17
View on GitHub
Comments
2
Participants
2
Timeline
7
Reactions
0
Author
Timeline (top)
labeled ×4commented ×2subscribed ×1

Fix Action

Fix / Workaround

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.

  • 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.

Code Example

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

---

// 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

---

// 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
}

---

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

---

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

---

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

---

- 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
  }
RAW_BUFFERClick to expand / collapse

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)

ConcernLineSymbol
Settings schema (4-value)189effortLevel: y.enum([...])
Settings-write validator (4-value)899It6()
Env-var reader (5-value)899Zj6()
Runtime normalizer (5-value)id(), kh8(), UI
Effective-effort resolver899wy6(model, fallback)
Opus 4.7 pinned default899bF1(), unpinOpus47LaunchEffort
Max capability gate899Ct6(), deny set d8z
Zustand initial state2935effortValue: void 0
Zustand populator (settings-only)2898
/effort slash command handler7094VoY, qtK, koY
Slider initial-highlight logic7094slider picks tsK = 3 = xhigh on undefined
Welcome banner stringsearch "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.

extent analysis

TL;DR

To fix the UI/runtime parity issue, apply the three localized fixes: interpolate effort into the welcome banner, cascade into the slider's initial state, and extend the settings schema to accept max.

Guidance

  • Apply Fix 1: Interpolate effort into the welcome banner by changing the string to Welcome to Opus 4.7 ${wy6(currentModel) ?? "xhigh"}! to surface the effective effort.
  • Apply Fix 2: Cascade into the slider's initial state by extending the seed order in the Zustand effortValue populator to resolve the effective effort.
  • Apply Fix 3: Extend the settings schema to accept max by adding it to both validators, but consider the product decision on whether max should be session-only.

Example

// Fix 1: Interpolate effort into the welcome banner
- "Welcome to Opus 4.7 xhigh!"
+ `Welcome to Opus 4.7 ${wy6(currentModel) ?? "xhigh"}!`

// Fix 2: Cascade into the slider's initial state
- ...$ && w !== void 0 && { effortValue: w }
+ { effortValue: w ?? Zj6() ?? bF1(currentModel) ?? undefined }

// Fix 3: Extend settings schema to accept `max`
- effortLevel: y.enum(["low","medium","high","xhigh"])
+ effortLevel: y.enum(["low","medium","high","xhigh","max"])

Notes

The fixes assume the env-var path and UI were implemented independently, and the launch banner is safe to parameterize. A product decision is needed on whether max should be session-only.

Recommendation

Apply the three localized fixes to restore UI/runtime parity, but consider the product decision on Fix 3.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix `/effort` slider and welcome banner don't honor `CLAUDE_CODE_EFFORT_LEVEL=max` [2 comments, 2 participants]