I've noticed something among developers I know who use Claude Code: a lot of them set the effort level to high, xhigh, or even max, and just leave it there, forever.
The reasoning is understandable: "more effort means better code, right?".
Well, not exactly.
In this article I want to share the workflow I use when I build a new feature, or even an entire new project, where I spend a lot of effort (and tokens) when it matters, and very little when it doesn't.
What is effort anyway?
If you haven't played with it yet, effort is a setting in Claude Code that tells the model roughly how much work you want it to put into a task. You can change it at any time with the /effort command:
/effort low
/effort medium
/effort high
/effort xhigh
/effort max
Yes, high is not the top of the scale! With Opus 5.5 you also get xhigh and max, and from what I see these are the levels a lot of people actually use, as "if high is good, max must be better".
But every step up costs more. Taking medium (the default) as the baseline, this is roughly how many tokens each level consumes:
| Effort | Tokens compared to medium
|
|---|---|
low |
~0.7x |
medium (default) |
1x |
high |
~1.5x |
xhigh |
~2.5x |
max |
~5.2x |
So if you leave Claude Code on max for everything, you are spending about five times the tokens of the default, and more than seven times what the same task would cost on low. And the extra time adds up just as quickly.
Higher effort doesn't make the model "smarter". What it does is make Claude spend more time verifying its own work, checking edge cases, and making its own judgement calls. Lower effort gives you a quicker, simpler result that you are expected to iterate on.
Think about it like asking a colleague to do something. If you give them a full day, they will try to deliver the most complete version they can, and they will make a lot of decisions on your behalf along the way. If you give them an hour, they will deliver something that does the job and expect you to give feedback.
Neither is wrong, it depends on what you need at that moment.
The problem with "max effort all the time"
When you leave effort on high, xhigh, or max for everything, a few things happen:
- You burn a lot more tokens, even for tasks like renaming a variable or adding a field to a form.
- You wait longer for every single response.
- Claude makes more assumptions for you, which is great when you want it to work autonomously, but not so great when you want to stay in control of what's being built.
That last point is the one that surprised me the most. More effort doesn't automatically mean more of what you wanted, it often means more of what Claude thinks you wanted.
My workflow: plan high, execute lower
So here's what I do instead. I split the work into two very different phases, and I use a different effort level (and sometimes a different model) for each of them.
flowchart TD
A[Idea] --> B[Plan<br/>Opus 5.5, high effort]
B --> C[Plan + ADRs]
C --> D[Execute step N<br/>Opus or Sonnet 5.5, low/medium]
D --> E{Review}
E -- needs changes --> D
E -- looks good --> F[Verify<br/>high effort]
F --> G{More steps?}
G -- yes --> D
G -- no --> H[Done]
Step 1: Plan with high effort
The planning phase is where the hard thinking happens: what are we building, how do the pieces fit together, what are the trade-offs, what could go wrong.
This is exactly where I want the model to think hard, so I use Opus 5.5 with high effort:
claude --model opus
# Then inside the session
/effort high
I also ask Claude to interview me about the feature before writing the plan. This is a small trick that makes a huge difference, as it forces me to answer the questions I didn't think about, and Claude doesn't have to guess.
To do that, I use the grilling skill from Matt Pocock. If you don't know what skills are, they are just markdown files with instructions that Claude Code loads when they are relevant to what you are doing.
What I like about this skill is how structured the interview is:
- Claude maps every decision as a tree, where each decision unlocks the ones that depend on it.
- It asks the questions in rounds, only the ones that can be answered now, without guessing answers you haven't given yet.
- Each question comes numbered and with a recommended answer, so most of the time you can just say "yes" and move on.
- Facts it can find by itself, like what's in your codebase, it looks up on its own, and it only asks you about decisions.
- It doesn't start doing anything until you both agree there's nothing left to decide.
To install it, just follow the installation steps in the repository, it takes less than a minute.
Then in the planning session I just ask Claude to grill me:
I want to add bookmarks to my blog app, so logged-in users can save
articles and see them in a "Saved" page.
Grill me on this before writing any plan. Once we agree, write a plan
split into small, independent steps.
And a round of questions will look something like this:
❓ Q1 - Anonymous users: Should users who are not logged in see the
bookmark button?
➡️ Show it, but redirect to the login page when clicked.
❓ Q2 - Storage: Should bookmarks be stored server-side, or is
localStorage enough?
➡️ Server-side, so bookmarks follow the user across devices.
This can take a while, and with high effort it does use a good amount of tokens, but it's the best place to spend them, as every question answered here is one less assumption Claude has to make later.
Step 2: Write everything down
The output of the planning session is not code, it's documents. I normally end up with something like this:
.
|-- docs
| |-- adr
| | |-- 001-store-bookmarks-in-postgres.md
| | `-- 002-use-swr-for-client-fetching.md
| `-- plans
| `-- bookmarks.md
`-- CLAUDE.md
The plan, docs/plans/bookmarks.md, is split into steps, where each step is small enough to be done in a single session:
# Bookmarks feature
## Step 1: Database
- Create a `bookmarks` table (user_id, article_id, created_at)
- Add a unique constraint on (user_id, article_id)
- Write the migration and the rollback
## Step 2: API endpoints
- POST /api/bookmarks
- DELETE /api/bookmarks/:articleId
- GET /api/bookmarks
## Step 3: UI
- Bookmark button on the article page
- "Saved" page listing the bookmarks
For the decisions that need a "why", like choosing a library or a database design, I also ask Claude to write an ADR (Architecture Decision Record). An ADR is just a short markdown file that explains what we decided, why, and what alternatives we considered:
# ADR-002: Use SWR for client-side fetching
## Status
Accepted
## Context
The "Saved" page needs to fetch the bookmarks list and refresh it
when a bookmark is added or removed.
## Decision
Use the SWR hook with Suspense, as we already do in other pages.
## Consequences
- Caching and revalidation for free
- One more dependency in the frontend
If you want to know more about SWR and Suspense, I wrote about it in Using SWR hook with Suspense in React 18.
And finally, things that are important to remember, but that don't really belong in the plan (like "the staging database uses a different port" or "we use pnpm, not npm"), go into Claude's memory, like the CLAUDE.md file. This way they are available in every session, without cluttering the plan.
Step 3: Execute one step at a time, with low or medium effort
Now comes the part where most people keep the effort on high, and where I do the opposite.
For each step of the plan, I start a new session, point it to the plan, and lower the effort to low or medium, depending on how big the step is.
I can keep using Opus 5.5 for this, but for the more straightforward steps I often switch to a cheaper model like Sonnet 5.5:
# Stay on Opus 5.5...
claude --model opus
# ...or switch to Sonnet 5.5 for simpler steps
claude --model sonnet
# Then inside the session
/effort low # small, well-defined steps
/effort medium # bigger steps, or ones touching more files
Read docs/plans/bookmarks.md and the ADRs in docs/adr.
Implement Step 2 only. Don't touch anything outside that step.
Why does this work? Because all the hard decisions were already made during the planning phase. Claude doesn't need to think hard about how to design the API, it's written right there in the plan. It just needs to execute it.
Starting a new session for each step also has another advantage: the context is clean. No leftovers from previous steps, no long conversation history to drag along, just the plan, the ADRs, and the code.
If a step turns out to be trickier than expected, I just bump the effort up, or switch back to Opus. No big deal.
Step 4: Review, then verify with high effort
Once a step is done, I review the code myself, to make sure Claude got the gist of what I wanted. If something is off, I iterate, still on the same lower effort.
When I'm happy with it, I switch back to high effort and ask Claude to verify the work: run the tests, look for edge cases, check that nothing else broke.
/effort high
Review the changes for Step 2 against docs/plans/bookmarks.md.
Write tests for the edge cases (duplicate bookmarks, deleting a
bookmark that doesn't exist, unauthenticated requests) and run them.
This is where the extra effort really pays off, as hunting for edge cases is exactly the kind of work where thinking longer finds more problems.
Is this just my opinion?
Partly, yes! But it turns out Anthropic recently published a post on the claude.dev blog, Using Claude Code: Spending your effort, where they tested the same tasks at different effort levels, and a few findings match this workflow pretty well.
The most interesting one for me: when they gave Claude a vague request (like "build a fitness tracker app"), the effort level changed the result dramatically. But when they first had Claude interview them and produce a detailed spec, then implemented that spec at different effort levels, the results were very similar, just at very different speeds.
That's the whole point of planning first: a detailed plan removes most of the guesswork, and when there's no guesswork, you don't need to pay for extra thinking.
The loop they recommend is also very close to what I described above: get interviewed about the spec, implement on low effort, review and iterate, then verify and test on high effort.
To be fair, the same post also shows that higher effort does produce better results on hard problems, especially when there are a lot of hidden edge cases. So it's not that high effort is bad, it's that it's not free, and it's not always the thing that makes the difference.
When you should crank up the effort
As with everything, this is not a rule you should apply blindly. There are cases where I go straight to high, or even max, during execution:
- Bugs in an existing codebase. When you don't fully know why something is breaking, you want Claude to reproduce the problem first and verify the fix, not just patch the first thing that looks suspicious.
- Security-sensitive code. Things like input sanitisation, authentication, or permissions are full of edge cases, and missing one of them is expensive.
- Performance work. Claude needs to measure, test with bigger inputs, and iterate, not just write something that looks fast.
- Fully autonomous tasks. If you are not going to be in the loop to review each step, then you want Claude to do the verification on its own.
As a rule of thumb, I start with high, and I move to xhigh or max only when the task is really hard, or when Claude is going to work on its own for a long time without me checking in. Those are the cases where all that extra verification actually pays for itself.
And on the other side, there are cases where even planning on high is overkill: a typo fix, a small refactor, or a one-off script. Just do it on low and move on.
Conclusions
The effort level is not a "quality" knob you set once and forget, it's a budget you spend depending on the task.
So what I'd suggest is:
- Plan with a strong model and high effort, and let Claude grill you until there's nothing left to decide.
- Write it down: a plan split into steps, ADRs for the important decisions, and memory for everything else.
- Execute each step in a fresh session, with low or medium effort, and maybe a cheaper model.
- Verify with high effort, where finding edge cases actually matters.
You'll spend fewer tokens, wait less for each response, and in my experience, you'll stay much more in control of what's being built.
How do you use effort levels in Claude Code? I'd love to hear if you have a different approach, so let me know in the comments!
Top comments (0)