← Claude for Real Work

Models and effort

Lesson 17 of 28 · 12 min · Updated

Models and effort are the two dials on a Claude Code session: which model answers, and how hard it thinks before it does.

Most people never touch either, and the default is a reasonable place to leave them. This lesson exists so that when a session is going badly you know there is something to change, and so you know what the change costs.

The models

Pick one with /model in a session, or --model at launch. You can use an alias rather than a version number:

  • opus - the latest Opus. Complex reasoning.
  • sonnet - the latest Sonnet. Daily coding work.
  • haiku - fast and cheap. Simple, mechanical tasks.
  • fable - Fable 5, for work larger than a single sitting.
  • best - Fable 5 where your organisation has it, otherwise the latest Opus.
  • opusplan - Opus while planning, then Sonnet to do the work.
  • default - clears any override and goes back to your account’s default.

The aliases move as new versions ship, which is what you want most of the time and not what you want when you are trying to reproduce something. Name the version explicitly for that: --model claude-opus-5.

opusplan deserves a second look, because it matches how lesson 14 said to work. The expensive model decides what to do, which is where thinking pays, and the cheaper one carries it out, which is where thinking mostly does not.

What does the effort level change?

Effort controls how much the model reasons before answering. Set it with /effort, or --effort at launch:

low, medium, high, xhigh, max. The default is high on every model that supports it.

The scale is calibrated per model, so high on Haiku and high on Opus are not the same amount of thinking. And max is not the best one by definition: the documentation’s own wording is that it “may show diminishing returns and is prone to overthinking”. That matches experience. A model at max on a two-line fix will find three architectural concerns you did not ask about.

One more, for a single turn rather than a session: put the word ultrathink anywhere in your prompt and Claude Code adds an instruction asking for deeper reasoning on that turn only. Other phrasings people try, like “think hard” or “think step by step”, are passed through as ordinary text and do nothing.

What the difference looks like

Numbers from one run, in a stockroom clone, both asked the same open question:

Read src/domain/stock.ts and src/domain/movements.ts carefully. Is there a bug in how
stock is valued? Be specific and name the function.
ModelCostTimeTurnsAnswer
Haiku$0.047545s3Confident, specific, wrong
Opus 5$1.0209181s22Correct, and worse than I knew

Twenty-one times the money and four times the wait. That is the honest headline, and if the answers had been equally good it would be an easy argument for Haiku.

They were not. Haiku said unitCost could be undefined and produce NaN in the valuation. It named a function, quoted a line, and explained the mechanism. It is also not true: record() defaults unitCost to the item’s cost, so it is never undefined. A plausible, specific, checkable-and-false answer, delivered in the same tone as a correct one.

Opus read further and found something worse than the bug I knew about. MovementKind includes adjustment, but record() only negates a pick and rejects any quantity of zero or less. So a downward adjustment, which is how you write off damaged stock, cannot be expressed at all: write off ten units and you get a positive ten. It then lands in averageCost’s receipt branch, because that branch tests the sign rather than the kind, and gets valued at the item’s list cost. Damaged stock increases the valuation.

That bug is real and it was not planted. It took 22 turns of reading to find.

Do not take this table as a benchmark. It is one question on one repository on one day, and a rerun will give different numbers and possibly different answers. What is stable is the shape: the cheap model answers quickly and sometimes wrongly in a way you cannot detect without checking, and the expensive model reads more before it commits.

Choosing, in practice

Haiku for work where you would recognise a wrong answer instantly. Renaming things, mechanical edits, formatting, “what does this file do”, running a command and reporting output.

Sonnet for the ordinary day. Most changes with a clear shape.

Opus or Fable when you do not know the answer yourself. Debugging something strange, a change across many files, anything where a confident wrong answer would cost you an afternoon. That is the real rule: spend the money in proportion to how hard the mistake would be to catch.

Effort moves in the same direction for less. Before reaching for a bigger model, try /effort xhigh on the one you have.

The failure worth naming: running everything at the maximum of both dials because it feels safer. It is slower, it costs more, and on simple work it produces more to review, which is your time rather than the machine’s.

Switching mid-session

Both dials change without restarting. /model sonnet and /effort medium take effect from your next message and the conversation carries on.

The move that works: plan on the expensive setting, execute on the cheap one. Once the plan is agreed and the file list is known, the remaining work is mostly typing.

The move that does not work: switching models to escape a session that has gone wrong. If the context contains four failed attempts, a better model inherits four failed attempts. /clear first, then switch. Lesson 16.

Your turn

Ask the same question at two settings and measure both, in a stockroom clone.

Q="Read src/domain/stock.ts and src/domain/movements.ts carefully. Is there a bug
in how stock is valued? Be specific and name the function."

claude -p --output-format json --model haiku "$Q" < /dev/null > /tmp/cheap.json
claude -p --output-format json --model opus  "$Q" < /dev/null > /tmp/dear.json

Then read the cost, the time, and the answers:

python3 -c "
import json
for n in ('cheap','dear'):
    d = json.load(open(f'/tmp/{n}.json'))
    print(n, '\$%.4f' % d['total_cost_usd'], '%.0fs' % (d['duration_ms']/1000), d['num_turns'], 'turns')
    print(d['result'][:400], '\n')
"

Check: both files contain a total_cost_usd and a result, the two costs differ by more than a factor of ten, and you can say in one sentence what each answer claimed. Then the real check, which no script can do for you: open src/domain/movements.ts and decide which of them is right. If you accept an answer here without opening the file, you have just demonstrated the failure this whole lesson is about.

Recap

Two dials. /model picks who answers, /effort picks how hard they think, and both change mid-session. Aliases move with releases; name a version when you need to reproduce something.

Spend in proportion to how hard the mistake would be to catch, not in proportion to how important the task feels. Cheap models fail by being confidently specific and wrong, which is the failure mode that gets past review.

opusplan for plan-then-execute, ultrathink for one deep turn, and /clear before you switch away from a session that has gone wrong.

Next: deciding once what Claude may do without asking, and the short list of things that should always stop.