effortLevel setting doesn't support "max" value

Status Fixed / completed
Maintainer reply None cached
Activity 9 comments · opened Mar 18, 2026 · closed Aug 19, 2026

Bug

/effort max works as a session-only command and sets effort to "Maximum capability with deepest reasoning (Opus 4.6 only)", but this value cannot be persisted in settings.json.

The effortLevel field in the settings schema only allows "low", "medium", "high":

"effortLevel": {
  "description": "Persisted effort level for supported models.",
  "type": "string",
  "enum": ["low", "medium", "high"]
}

Setting "effortLevel": "max" in ~/.claude/settings.json is silently ignored (falls back to default).

Expected behavior

"max" should be a valid value in the effortLevel enum so it can be persisted across sessions, just like the other effort levels.

Steps to reproduce

  1. Run /effort max — works, confirms "Set effort level to max (this session only)"
  2. Add "effortLevel": "max" to ~/.claude/settings.json
  3. Restart Claude Code
  4. Run /effort — shows "high", not "max"

Environment

  • Windows 11 Pro
  • Claude Code CLI
  • Model: Opus 4.6

View original on GitHub ↗

8 Comments

toffee-desuwa · 5 months ago

Same issue here. Windows 11 + PowerShell, v2.1.79. Setting "effortLevel": "max" in ~/.claude/settings.json is silently ignored, falls back to medium. /effort max works at runtime but doesn't persist.

Astro-Han · 5 months ago

Can confirm — "effortLevel": "max" in settings.json is silently ignored because the schema enum is ["low", "medium", "high"]. No warning, no error, just falls back to default.

I read this field via --slurpfile in claude-lens and max never appears in the statusline output, even when set — because the fallback happens before any external script reads it.

+1 on adding max to the enum. The silent fallback is the worst part — at minimum it should log a validation warning on startup.

yurukusa · 5 months ago

The schema currently only accepts "low", "medium", "high""max" is only available as a runtime command via /effort max and doesn't persist across sessions.
Workaround — SessionStart hook to auto-remind:

// ~/.claude/settings.json
{
  "effortLevel": "high",
  "hooks": {
    "Notification": [
      {
        "matcher": "SessionStart",
        "hooks": [{
          "type": "command",
          "command": "echo '⚡ effort is set to high (max not supported in settings). Run /effort max if needed.' >&2"
        }]
      }
    ]
  }
}

This sets the highest persistent level (high) and reminds you at session start that /effort max is available for the current session.
Alternative — CLAUDE.md instruction:
Add to your project's CLAUDE.md:

Always use maximum thinking effort. Take your time and think deeply about every problem.

This doesn't change the API-level effort parameter, but it instructs the model to use thorough reasoning regardless of the effort setting. Combined with "effortLevel": "high", this gets close to max behavior.
The silent fallback with no warning is the worst part of this bug — at minimum the settings parser should warn when an unsupported value is provided.

relanderolli · 4 months ago

Ive found a temporary workaround, put this to your settings.json:

{
  "env": {
    "CLAUDE_CODE_EFFORT_LEVEL": "max"
  }
}
ivan-ai-san · 4 months ago

Confirming the same behaviour on Linux (Ubuntu, Claude Code CLI, Opus 4.6).

"effortLevel": "max" in ~/.claude/settings.json is silently ignored. Every new session starts at auto (currently medium). /effort max works session-only.

Additionally — permissions defined in the same settings.json also appear to not be fully applied on session start, which suggests the silent-ignore behaviour may extend beyond just effortLevel. Possibly related: #30519, #36192, #36168.

Workaround: /effort max at session start.

andywebaholics · 4 months ago

Still present on Claude Code 2.1.112 / macOS 14.1.2 (Darwin 23.1.0), Opus 4.7 (1M context).

The schema has since been updated to accept xhigh (I currently have "effortLevel": "xhigh" persisted), but max is still silently dropped.

Repro via /model instead of /effort:

  1. Run /model, select max effort. Banner prints: Set model to Opus 4.7 (1M context) (default) with max effort
  2. Check persisted value:

``bash
python3 -c "import json; print(json.load(open('/Users/me/.claude/settings.json'))['effortLevel'])"
``

  1. Expected: max. Actual: prior value (in my case xhigh).

Side effects:

  • Custom statuslines reading effortLevel from settings.json can never render a max styling (see also #41985, #45805 asking for effortLevel in statusline stdin).
  • The /model confirmation message is misleading because it claims persistence succeeded.

Suggested fix: add "max" (and "xhigh" if missing) to the effortLevel enum in the settings schema, gated on the user's plan if necessary (per #33937 for Max plan scoping).

yigitkonur · 4 months ago

small update for anyone landing here — the CLI flag path on v2.1.116 now explicitly accepts max in the help text:

$ claude --help | grep effort
--effort <level>  Effort level for the current session (low, medium, high, xhigh, max)

settings.json effortLevel still silently falls back to xhigh on a fresh restart (the schema enum hasn't been updated to include max), so this issue's core problem is still reproducible. but the CLI flag is now documented, which gives a clean launch-time workaround that doesn't rely on env var inheritance quirks:

alias claude='command claude --effort max'

combined with "effortLevel": "xhigh" in settings.json as a valid baseline (won't silently fail on startup, and the alias overrides it per-session), this gives a stable max-effort setup until the schema is updated.

also confirming @relanderolli's env var approach (CLAUDE_CODE_EFFORT_LEVEL=max under env) works alongside this — but the CLI flag is now first-class in --help, so it's the most discoverable path forward for new users hitting this.

real fix request stands: add max to the effortLevel enum in the settings schema. the inconsistency between "CLI accepts it, settings.json rejects it" is the confusing part, and a silent fallback with no validation warning on startup is the worst UX.

eztean · 1 month ago

Still reproducible on 2.1.220 (currently the latest published version), Linux, claude-opus-5, via the VS Code extension. Two findings that I think matter for the fix, since neither is visible from outside.

1. The fallback value isn't a constant — it's the model's default, which is why this thread reports four different ones. Comments here variously report medium, auto (currently medium), xhigh; I measured high. There are two different parsers. Startup resolution is, in effect:

gW(cli.effort) ?? (settings.ultracode === true ? "xhigh" : undefined) ?? Q6e(settings.effortLevel)

gW accepts the full canonical list (low|medium|high|xhigh|max, plus integers and the med alias); Q6e returns only low|medium|high|xhigh, and undefined for anything else — which is what the .catch(void 0) then swallows. So the asymmetry isn't only that the enum lacks max: the flag channel and the settings channel validate with different functions. With nothing resolved, the per-turn resolver falls back to ait(model) = default_effort ?? "high", so the level you land on depends on the model, not on a fixed app default.

2. Two more silent downgrades that would survive the proposed one-line fix. Same per-turn resolver: if (s === "max" && !eqe(model)) s = "high" (model max_effort capability gate), then a clamp to the organization's maxEffortLevel. Both silent, both producing the identical symptom by a different cause — there's even a prepared "exceeds your organization's limit" message that doesn't fire on this path. Neither gate is biting on my account (the --effort max flag path passes both and does run at max), but it means adding max to the enum alone wouldn't guarantee the symptom disappears for everyone landing here. What closes the whole class is a startup validation warning when effortLevel holds a value that can't be honored, instead of .catch(void 0).

Worth noting: the schema has been edited since this was filed — xhigh was added, max wasn't. Not a forgotten field.

Verification method, in case it helps triage: reading settings.json back can't answer this, since the bug is precisely that config and effect disagree. echo $CLAUDE_EFFORT from inside a session does — the CLI injects the turn's resolved effort into tool subprocesses.

Identifier names above are from the 2.1.220 bundle and get remangled per build; the control flow is the stable part, not the names.

Showing cached comments. Read the full discussion on GitHub ↗