- Book: Observability for LLM Applications
- Also by me: Thinking in Go (2-book series) — Complete Guide to Go Programming + Hexagonal Architecture in Go
- My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools
- Me: xgabriel.com | GitHub
Unexpectedly high Claude Code spend on an API or cloud-provider plan "usually traces back to long sessions that were never cleared or to Opus left as the default model." That line is from Anthropic's cost guide for Claude Code, which also says thinking tokens "are billed as output tokens." At list price, Claude Opus 5.5 output costs $20 per million tokens and Claude Haiku 5.5 output costs $0.50 (Anthropic pricing). That is a 40x gap on the kind of token a high-effort run produces most.
The opposite mistake costs time instead of money. Hand a race condition that spans three services to a small model at low effort, and you get a confident patch, then a second one, then a third. Then you switch models anyway and explain the bug again from the start.
Decide the model and effort per kind of task once, and give each combination a name you can type: chore, feature and deep, for both Claude Code and Codex. Every flag and key below matches each CLI's docs as of October 18, 2026.
Three kinds of task, three settings
| Preset | Typical task | Claude Code | Codex |
|---|---|---|---|
chore |
rename, typo, docstring, version bump |
haiku, low
|
gpt-6-luna, low
|
feature |
an endpoint plus its test, a normal ticket |
sonnet, medium
|
gpt-6.1-sol, medium
|
deep |
flaky test, race condition, design question |
opus, xhigh
|
gpt-6.1-sol, xhigh
|
The picks follow each vendor's own descriptions. Anthropic's model config docs describe the haiku alias as "for simple tasks", sonnet as "for daily coding" and opus as "for complex reasoning", and the cost guide says "Sonnet handles most coding tasks well and costs less than Opus." OpenAI's Codex models page calls GPT-6 Luna its "most efficient model for focused, high-volume tasks, including summarization, extraction, and focused coding," and positions GPT-6.1 Sol for complex work at a lower cost than Astra. If your account has GPT-6 Astra, which OpenAI calls its most capable model, it can take the Codex deep slot instead.
Effort is the second dial. Claude Code accepts low, medium, high, xhigh and max on the 5.5 models, and Opus 5.5, Sonnet 5.5 and Haiku 5.5 all default to medium (model config). Codex's model_reasoning_effort takes whatever the model advertises, "such as low, medium, high, xhigh, max, or ultra" (config reference). Luna goes up to Max but not Ultra.
Two caveats on the chore row. OpenAI's models page suggests starting Luna at High, and Haiku 5.5 charges more once a prompt passes 100,000 tokens: $0.50 instead of $0.10 per million input tokens (pricing). Low effort in a short session is a choice for mechanical edits. If it starts missing call sites, raise it. On a Claude Pro or Max plan you don't pay per token, but the same work still draws down your plan's usage.
Codex: one profile file per preset
If you learned Codex profiles from an older tutorial, you wrote [profiles.deep] tables inside ~/.codex/config.toml. That format is gone. The advanced config docs say that from Codex 0.134.0, --profile no longer reads [profiles.<name>] from config.toml, and the top-level profile = "..." selector is no longer supported. A profile is now its own file, ~/.codex/<name>.config.toml, with top-level keys. Codex loads your base config, then lays the profile file on top.
Your base config holds the feature row, because that's most days:
# ~/.codex/config.toml
model = "gpt-6.1-sol"
model_reasoning_effort = "medium"
Each profile file only needs the keys that differ:
# ~/.codex/chore.config.toml
model = "gpt-6-luna"
model_reasoning_effort = "low"
# ~/.codex/deep.config.toml
model_reasoning_effort = "xhigh"
deep keeps Sol from the base file and only raises the effort. Profile names can use letters, numbers, hyphens and underscores. Launch with --profile, or its short form -p:
codex -p chore "Rename getUser to fetchUser in src/"
codex -p deep "Find why orders.test.ts fails 1 run in 10"
codex exec -p chore "Fix the typos in README.md"
For a one-off bump without writing a new file, -c overrides any key for that run. Values parse as TOML when they can and fall back to a literal string otherwise (CLI reference), so wrapping a string value in TOML quotes keeps it unambiguous:
codex -p deep -c model_reasoning_effort='"max"'
Max and Ultra on Sol depend on your settings, per the models page. If you still have old [profiles.*] tables, the docs' migration is to move each one into its own <name>.config.toml, then delete the table and the profile selector from config.toml.
Claude Code: shell functions around --model and --effort
Claude Code has no profile flag. It has --model, which takes an alias such as haiku, sonnet, opus or fable, or a full model name. It also has --effort, which sets the level for the current session and "does not persist" (CLI reference). Three shell functions are enough:
# ~/.zshrc or ~/.bashrc
cc-chore() {
env -u CLAUDE_CODE_EFFORT_LEVEL \
claude --model haiku --effort low "$@"
}
cc-feature() {
env -u CLAUDE_CODE_EFFORT_LEVEL \
claude --model sonnet --effort medium "$@"
}
cc-deep() {
env -u CLAUDE_CODE_EFFORT_LEVEL \
claude --model opus --effort xhigh "$@"
}
"$@" passes everything through, so a prompt and extra flags still work:
cc-chore "Rename getUser to fetchUser in src/"
cc-deep --permission-mode plan "Why does the order queue stall?"
The env -u line is there for the trap in the next section. One more thing about aliases: they follow the provider. On the Anthropic API, opus, sonnet and haiku are the 5.5 models today. On Amazon Bedrock and Google Cloud's Agent Platform, sonnet and haiku still point at 4.5 models, and on Microsoft Foundry even opus is Opus 4.6, per the alias table in the model config docs. If the preset has to mean the same model next month, write the full name, such as claude-opus-5-5.
When a chore turns out to be harder than it looked, /model inside the session still works. It outranks --model. In the picker, s applies the switch to the current session only, and Enter saves it as your default for new sessions. That saved default sits below --model in the precedence list, so your functions still win on the next launch.
If you only use Claude Code, there is a built-in option for background sessions too: claude agents takes --model and --effort as defaults for the sessions it dispatches (CLI reference).
The two settings that quietly undo your presets
Both CLIs have a layer that sits above the preset you just built.
Claude Code: CLAUDE_CODE_EFFORT_LEVEL beats --effort. For the model, the command-line flag beats the environment variable: --model overrides ANTHROPIC_MODEL. Effort works the other way round. The env vars reference says the variable "Takes precedence over --effort, /effort, and the modelSettings and effortLevel settings." Export CLAUDE_CODE_EFFORT_LEVEL=high in your shell profile once, forget about it, and cc-chore runs Haiku at high on every rename.
It costs you a second time in subagents. The model config docs say an effort field in skill or subagent frontmatter overrides the session level while that skill or subagent runs, "but not the environment variable." A reviewer subagent you set to effort: high runs at whatever the variable says. That's why the functions above start with env -u CLAUDE_CODE_EFFORT_LEVEL, and why the variable is better left out of your shell profile. To see whether it's set right now:
env | grep CLAUDE_CODE_EFFORT_LEVEL
The variable can also come from the env block in ~/.claude/settings.json or in a trusted project's .claude/settings.json (settings reference). env -u doesn't clear that, and env | grep won't show it, so check those files too:
grep -s EFFORT_LEVEL ~/.claude/settings.json \
.claude/settings*.json
An organization's maxEffortLevel cap still applies on top of all of this, so xhigh can come out lower on a managed machine.
Codex: a trusted project's config beats your profile. The basic config docs list the order, highest first: CLI flags and --config overrides, then project .codex/config.toml files, then the profile you selected, then ~/.codex/config.toml. Project files load only for trusted projects, and the one closest to your current directory wins. So if a repo you trust commits model = "gpt-6.1-sol" in its .codex/config.toml, codex -p chore in that repo runs Sol, not Luna. Check before you blame the profile:
cat .codex/config.toml 2>/dev/null
If the project file sets the model or effort, either drop those keys from it or pass them as flags, which sit at the top of the list:
codex -p chore -m gpt-6-luna "Rename getUser to fetchUser"
| Layer | Claude Code | Codex |
|---|---|---|
| Wins over your preset |
CLAUDE_CODE_EFFORT_LEVEL (effort), /model mid-session |
-m, -c, trusted .codex/config.toml
|
| Your preset |
--model, --effort
|
--profile file |
| Loses to your preset |
ANTHROPIC_MODEL, settings |
~/.codex/config.toml |
The same presets in Hermes IDE
I build Hermes IDE, so weigh this section with that in mind. Shell functions and profile files cover one agent on one account. Once you run Claude Code and Codex side by side, maybe on two accounts, picking the combination per task is the part Hermes handles.
Press ⌘N (Ctrl+Shift+N on Windows and Linux) for the New task sheet. Its chips pick the agent, the project, a new hermes/ worktree, the approval mode, the model and the effort, and per the README you can pick the account per task too, with several accounts per agent. Combinations you use often save as presets, and the New Session wizard preselects the last agent and how you ran it.

The ⌘N New task sheet in Hermes 2.3.4: chips for Claude Code, the orders-api project, a new hermes/ worktree, Accept edits, model and effort, and the "Hermes will run" preview of the claude command.
The "Hermes will run" line shows the command before anything starts. By default Hermes runs each agent in a real terminal with the agent's own interface, so the precedence rules above still apply there. A trusted .codex/config.toml can still override what you picked, and if that terminal inherits an exported CLAUDE_CODE_EFFORT_LEVEL, the variable still beats the effort you chose. Check both first.
When a task outgrows its preset, the bar above each session keeps Model, Plan and Review in the same place for every agent since 2.3.4, and you can pin the ones you use. And when one agent hits its usage limit, you can continue the task in another.

The bar above a Claude Code session in Hermes 2.3.4: Model, Plan and Review pinned, with the Commands list open.
Hermes 2.3.4 shipped on October 15, 2026. It is free, source-available under BSL 1.1, and runs on macOS, Windows and Linux. It is not affiliated with Anthropic, OpenAI or Nous Research.
If this was useful
Picking a model and an effort level per task is a cost and quality decision, and you just made it by hand for your coding agents. Once LLM calls run inside your own product, the same choice needs numbers behind it: what each call cost, how long it took, and whether the cheaper setting broke anything. Observability for LLM Applications covers the traces, evals and cost tracking that give you those numbers.
If you want to try the presets across agents, download Hermes IDE, and if it saves you a session, star it on GitHub.

Top comments (0)