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:
- An explicit choice. The
CLAUDE_CODE_EFFORT_LEVELenvironment variable, launching with--effort, or running/effortin the session. - A hold on the model's default effort, on certain models. More on this below, because it is the one that confuses everyone.
- Your settings. The level you saved for that model, or an
effortLevelkey in a settings file. - The model's default effort, which is
highon 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
Enterin the/effortslider or the/modelpicker, 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
--effortat launch, or pressingsin 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:
Enterin the slider or the/modelpicker, or a level typed after/effort— saves the level as your default and applies it in later sessions.sin 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:
- Check for
CLAUDE_CODE_EFFORT_LEVELin your shell environment. This is the most common culprit by a wide margin. - Check whether you are on a model with a default-effort hold, and clear it by confirming a level interactively with
Enterrather than a flag. - Check your settings files for an
effortLevelkey and for a per-model saved level. - Check whether a
maxEffortLevelor organisation cap is quietly limiting you — if levels are missing from the/effortpicker, 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