Blog · September 12, 2026 · 8 min read

Claude Code Effort Levels: Why Your Setting Keeps Getting Ignored

You set Claude Code to xhigh, restart the next morning, and the session header says something else entirely. Or you put effortLevel in your settings file, and it seems to be ignored roughly half the time. Neither of those is a bug. They are both the effort resolution order doing exactly what it is documented to do — and almost nobody has read that part.

Effort is the single biggest lever you have over how Claude Code behaves. It controls adaptive reasoning: how much the model thinks before it acts. Low is fast and cheap and fine for mechanical work. High is slower and noticeably better at problems where the first idea is wrong. Getting the wrong one silently is expensive in both directions.

This is the practical version: what the levels are, the exact order Claude Code resolves them in, the two mechanisms that override your choice, and how to make a setting actually stick.

The levels, briefly

The available levels depend on the model. Broadly you have low, medium, high and xhigh, with max available on some models. Models that do not support effort at all simply ignore the concept.

If you set a level the active model does not support, Claude Code does not error — it falls back to the highest supported level at or below what you asked for. Ask for xhigh on a model that tops out at high, and you get high. That silent downgrade is the first place people lose track of what they are actually running.

There is also ultracode, which appears in the /effort menu but is not really an effort level. It is a Claude Code setting that sends xhigh to the model and has Claude orchestrate dynamic workflows for substantial tasks. It has its own ultracode settings key, and neither the persisted effortLevel setting nor the CLAUDE_CODE_EFFORT_LEVEL environment variable accepts it.

The resolution order (this is the important part)

With ultracode off, Claude Code picks the session's effort level by taking the first of these that applies:

  1. An explicit choice. The CLAUDE_CODE_EFFORT_LEVEL environment variable, launching with --effort, or running /effort in the session.
  2. A hold on the model's default effort, on certain models. More on this below, because it is the one that confuses everyone.
  3. Your settings. The level you saved for that model, or an effortLevel key in a settings file.
  4. The model's default effort, which is high on most models that support effort.

Read that list again with your own setup in mind. If you have an environment variable set in your shell profile from three months ago, it beats everything else on this list — including the level you just picked in the settings file and forgot you had exported.

The hold, and why your setting "does not work"

On some models, Claude Code holds that model's default effort across sessions from the first time you run it — even when your settings would resolve a different level. This is deliberate, and it is step 2 in the list above, which means it sits above your saved settings.

What makes it slippery is that how you set a level determines whether the hold ends:

  • Ends the hold: confirming a level interactively — pressing Enter in the /effort slider or the /model picker, typing a level directly after /effort, or choosing one from a connected device's Remote Control effort control.
  • Leaves the hold in place for later sessions: passing --effort at launch, or pressing s in the slider or picker.

So the person who always launches with claude --effort xhigh gets xhigh for that session and then finds the next session back at the model default. That is not the flag failing. It is the flag applying to one session by design and never clearing the hold.

Session-only versus saved

When you set low, medium, high or xhigh interactively, you choose how long it lasts by how you confirm it:

  • Enter in the slider or the /model picker, or a level typed after /effort — saves the level as your default and applies it in later sessions.
  • s in the slider or picker — applies to this session only.

The level is saved per model, so each model keeps its own. If you switch models regularly, this is almost certainly why the effort level appears to change on its own. It did not change; you changed which model's saved level applies.

A related gotcha for scripted runs: setting a level with /effort inside a -p headless run applies to that run only and is not saved. On the models with a default-effort hold, it may report Not applied altogether — in which case pass --effort at launch instead.

What overrides you from above

Two caps can sit over everything you do, and both are silent if you are not looking for them.

The first is maxEffortLevel, a managed setting that caps effort on the client. It works on every provider, including Bedrock, Vertex and Foundry. The second is an organisation effort cap on Enterprise plans, set per role. When both apply to a model, the lower one wins. Levels above an organisation cap do not even appear in the /effort picker, and asking for one runs at the cap instead.

This is also why effortLevel and maxEffortLevel are not interchangeable in managed settings. Setting effortLevel applies a level at the settings step — users can still change it with /effort or --effort. If the intent is to keep people at or below a ceiling, only maxEffortLevel does that.

Skill and subagent frontmatter adds one more layer: an effort field there overrides the session level while that skill or subagent is active, but it does not beat the environment variable, and a cap still limits it.

How to check what you are actually running

Stop guessing. The current effort level is shown in the session header next to the model name — something like "with low effort" — so you can confirm it without opening anything. The footer also shows it briefly at startup and whenever it changes.

If it is not what you expected, work down the resolution order in order:

  1. Check for CLAUDE_CODE_EFFORT_LEVEL in your shell environment. This is the most common culprit by a wide margin.
  2. Check whether you are on a model with a default-effort hold, and clear it by confirming a level interactively with Enter rather than a flag.
  3. Check your settings files for an effortLevel key and for a per-model saved level.
  4. Check whether a maxEffortLevel or organisation cap is quietly limiting you — if levels are missing from the /effort picker, that is your answer.

Choosing a level in practice

Higher is not automatically better. Higher effort means more thinking per step, which means slower turns and more tokens. The practical shape most people land on:

  • Low or medium for mechanical work — renames, formatting, applying a pattern you have already specified, writing tests for code you just wrote.
  • High as the everyday default. It is the default on most models for a reason.
  • xhigh or ultracode for genuinely hard problems: debugging something that has already resisted one attempt, architectural decisions, anything where the obvious approach is probably wrong.

The habit worth building is changing it mid-task rather than setting it once. You can run /effort while Claude is working; it applies to the next request in the turn. Dropping to low once the hard thinking is done and the remaining work is mechanical is an easy win that almost nobody takes.

The cost of getting this wrong

Running too low on a hard problem is the more expensive mistake, and the less obvious one. You do not get an error; you get a plausible answer that is subtly wrong, and you find out twenty minutes later. Running too high on trivial work just costs time and tokens, which at least announces itself.

Both of which are easier to notice if you are not sitting there watching. Longer thinking at higher effort means longer gaps between the moments that actually need you — which is exactly the time you should be spending elsewhere.

If you want more control over what happens while you are away, the hooks guide covers firing your own scripts on Claude Code events, and context management covers the other lever that quietly determines output quality.

Keep reading

Claude Code Tips and Tricks: 12 Ways to Use Claude Code Effectively

8 min read

Claude Code Multiple Sessions: How to Run Agents in Parallel Without Losing Track

6 min read

A Claude Code Workflow That Doesn't Involve Watching the Terminal

5 min read

Claude Code Hooks: A Practical Guide to Automating Your Agent Workflow

7 min read

Claude Code Auto Mode: Fewer Permission Prompts Without Living Dangerously

7 min read

Claude Code Subagents: How to Delegate Work to Specialized Agents

7 min read

Claude Code Context Management: Treat the Context Window Like a Budget

6 min read

Per-Subagent Model Selection: Route the Grunt Work Down, Keep the Judgment Up Top

7 min read

Skills and Plugins: How to Teach Claude Code Your Way of Working

7 min read

Claude Code Background Tasks: Run Long Commands Without Blocking Your Session

6 min read

Codex CLI Notifications: How to Get a Ding When Codex Is Done or Needs Input

7 min read

Cursor Notification When Done: Every Way to Get Notified When Cursor Finishes

6 min read

Claude Code Notifications: How to Get Notified When Claude Code Finishes or Needs Your Input

6 min read

Want to Be Notified When Claude Responds? How Claude Notifications Work on Web, Desktop, and Mobile

5 min read

Claude Code Notification Scripts: Copy-Paste Recipes for Every Platform

6 min read

Get a Ding the Moment Codex Needs Your Response

6 min read

Get Notified the Moment Claude Code Is Waiting for Your Input

6 min read

“Notifications Are Turned Off for Claude” — Here Is the Fix

6 min read

Codex Sound When Done: Make Codex CLI Play a Sound When It Finishes

6 min read

terminal-notifier + Claude Code: Native macOS Alerts When Your Agent Finishes

6 min read

Gemini CLI Notifications: How to Get a Sound or Alert When Gemini Finishes

6 min read

Get Claude Code Notifications on Your Phone

6 min read

Claude Code Remote Control, Explained

7 min read

preferredNotifChannel: Claude Code's Built-In Notification Setting

6 min read

Claude Code Notifications in tmux and Over SSH

7 min read