← Claude Code Hub
✦ Tip #149 Jul 29, 2026

Claude Code effort: not the level you think you have

You can spend months running at an effort level you never picked. Five places define it, four of them fail without saying a word, and your settings.json is one of them.

The five places that define effort in Claude Code ordered by precedence: the environment variable wins, the --effort max flag you asked for is ignored, and the terminal returns EFFORT=low without a single warning

TL;DR Five places define your effort level and only one wins. The environment variable overrides even the flag you launched with, and it does it silently. An effortLevel: "max" in your settings.json is ignored outright. The only way to read the real level from a script is a six-line skill using ${CLAUDE_EFFORT}. The precedence chain is checked by hand, row by row, on v2.1.220.

Open your ~/.claude/settings.json. If it says "effortLevel": "high", you assume you're working at high.

Maybe you are. There are four ways you aren't, and not one of them says a word.

Here's what happens when you launch asking for the highest level there is:

$ CLAUDE_CODE_EFFORT_LEVEL=low claude --effort max -p "/whicheffort"
EFFORT=low

You asked for max explicitly, in the command itself. You're running at low. No warning, no line in the header, nothing. (/whicheffort is a six-line skill we build at the end of this tip; it's the only way to get that number out.)

The five places, and who beats whom

Effort doesn't live in one place. It lives in five, in this order:

Where it's set Scope Beats
CLAUDE_CODE_EFFORT_LEVEL The session Absolutely everything
effort: in a skill or subagent's frontmatter While that skill runs Everything but the variable
/effort and the --effort flag The session (persists, except max) Settings and the default
effortLevel in settings.json Permanent Only the default
The model default When nothing else applies

I tested all five rows one by one. Two results that aren't obvious: a skill's effort: frontmatter beats the flag you launched the session with (--effort max with a skill set to low runs at low), but the environment variable beats the frontmatter in turn. It's the same mess you get with the model, under its own rules: if yours sticks or resets on you, that's a separate story.

The four silent failures

1. The typo in your settings.

$ claude --settings '{"effortLevel":"hight"}' -p "/whicheffort"
EFFORT=high

I wrote hight. Not a word of warning. It falls back to the default and carries on. Compare that to the flag, which does validate what you hand it:

$ claude --effort bananas -p "hello"
Warning: Unknown --effort value 'bananas' — ignoring it and using the default effort.
Valid values: low, medium, high, xhigh, max.

The flag shouts. The file swallows it.

2. max in settings isn't a thing.

$ claude --settings '{"effortLevel":"max"}' -p "/whicheffort"
EFFORT=high

effortLevel only accepts low, medium, high and xhigh. Both max and ultracode are session-only and aren't accepted there. If you wrote it months ago convinced you were running flat out, you've been on high ever since.

3. The environment variable beats everything, including your flag. That's the example up top. Export it once in your .zshrc for an experiment and it still rules every session you open today.

4. max doesn't survive closing the terminal. Set low, medium, high or xhigh in an interactive session and they persist. max is the exception: it lasts that session and it's gone, unless you pin it through the environment variable.

There's a fifth case, and that one you already know about: starting on Fable 5, Opus 4.8 or Opus 4.7 imposes that model's default even when you had another level set.

Of every surface, exactly one tells you the truth when something is overriding it:

$ CLAUDE_CODE_EFFORT_LEVEL=low claude -p "/effort max"
Not applied: CLAUDE_CODE_EFFORT_LEVEL=low overrides effort this session, and max is session-only (nothing saved)

Two warnings in one line, and it's the only line that gives them.

How to read the real level, scripts included

Interactively, the level sits in the session header next to the model. Outside that you're blind: /status isn't available in headless, and --output-format json hands you the model, the cost to the cent, the cache tokens and even whether fast mode is off, yet says nothing about effort.

The way out is a context variable almost nobody uses. Create .claude/skills/whicheffort/SKILL.md:

---
name: whicheffort
description: Report the active effort level
---
Reply with exactly this line and nothing else:

EFFORT=${CLAUDE_EFFORT}

Now you have a probe that works the same in your terminal and in CI:

$ claude -p "/whicheffort"
EFFORT=high

$ claude --effort ultracode -p "/whicheffort"
EFFORT=xhigh

That second result is worth a look: ultracode isn't an effort level, so it reports as xhigh, which is what actually reaches the API.

What's at stake when the level isn't what you think

If this only changed how much Claude thinks, it would be a billing problem. It's more than that. Per Anthropic's docs, lowering effort reduces all the tokens in a response, and that includes tool calls: Claude batches operations together, makes fewer calls, goes straight to work without explaining the plan and confirms in a couple of words.

In practice: with effort lower than you believed, Claude edits your code having read fewer of your files. It isn't thinking worse, it's looking at less before it writes.

Which is why it pays to check once and forget, rather than fiddling with it. Picking a level is already settled in how to adjust the effort level and in my routing across Sonnet 5, Opus 5 and Fable 5. And if you got here trying to spend less, effort is one front out of ten: the other nine are here.

Reference

Surface Persists? Warns on failure? Takes max
CLAUDE_CODE_EFFORT_LEVEL While it's exported No Yes
effort: in frontmatter Only while the skill runs No Yes
/effort Yes, except max Yes, the only one that does Yes, that session
--effort at launch That session only Yes, on an unknown value Yes
effortLevel in settings Yes No No, it ignores it

If all of this suggests effort is a knob that matters, that's because it's the only one still wired to anything.

Official docs: Model configuration: adjust effort level · Effort · Skills: frontmatter

Requirements

  • Checked on Claude Code v2.1.220. The ${CLAUDE_EFFORT} variable is available inside skills.
Free guide

The 51 essentials, as a PDF.

One page per tip. Five chapters. What I actually use daily in production — no theory, no fluff.

  • I. Getting started 10 tips
  • II. Awareness 3 tips
  • III. Mastery 22 tips
  • IV. Autonomy 10 tips
  • V. Comparison 6 tips
Are you a professional Web developer?

You'll receive the guide by email · You join the Gravitas newsletter · Unsubscribe anytime

of 51
#

Wmedia · 51 Tips
Free guide · 51 tips · 5 chapters

The 51 essentials, as a PDF.

Are you a professional Web developer? · Unsubscribe anytime