Course · Codex · Models & effort
Switch models with /model, --model, and -c to match the task
The last lesson held the model fixed and only moved effort. Hold effort fixed this time - low on the accounts endpoint, high on the rules engine, the levels each task just earned - and move the other knob: which model answers at all. A capable model and a lighter one differ in what they can reason through, the same way effort differs in how hard a single model reasons. Confuse the two and you dial the wrong knob when a task fails.
The accounts endpoint again, model held light then capable
Section titled “The accounts endpoint again, model held light then capable”Same task, same effort, only the brain changes.
> add a CRUD accounts endpoint following the pattern in transactions.py (model: light, model_reasoning_effort = low)
read transactions.py ✎ accounts.py - list / create / read / delete, same shape Done.Matched. The same four routes as every low-effort trace in the last lesson - a light model reading an existing pattern needs nothing more from either dial.
> add a CRUD accounts endpoint following the pattern in transactions.py (model: capable, model_reasoning_effort = low)
read transactions.py ✎ accounts.py - list / create / read / delete, same shape Done.Overkill. Identical output, from a more capable brain that had nothing extra to contribute - the file next door had already settled every question this task had.
The rules engine again, same swap
Section titled “The rules engine again, same swap”Now hold effort at high - the level that earned the design last lesson - and swap only the model.
> design the categorisation rules engine for budgetcli - how rules match transactions, how conflicts resolve, how a user orders them (model: light, model_reasoning_effort = high)
Thinking… Matching: could use substring, or something smarter. Conflicts: rules could have priorities. Going with substring match, priority by list order.
✎ rules.py - substring match, first rule in the list wins Done.Underpowered. More deliberation text than low produced last lesson, but the same shallow design it would have picked anyway. A light model reasoning longer about a hard fork doesn’t reason deeper - it narrates the same guess at more length.
> design the categorisation rules engine for budgetcli - how rules match transactions, how conflicts resolve, how a user orders them (model: capable, model_reasoning_effort = high)
Thinking… Matching: substring is too blunt - merchant-code first, regex fallback. Conflicts: two rules can match one transaction. Need a deterministic tiebreak: explicit priority, first-match-wins, or most-specific-wins. First-match-wins is simplest and lets the user control order directly…
Here's the design I propose, before I write any of it: ## Matching merchant code first, then a user-ordered list of regex rules ## Conflicts first match wins; the user's ordering *is* the priorityMatched. This is the exact pairing behind last lesson’s high trace - the design only showed up once effort and model both cleared the bar. Neither dial alone would have gotten you here: hold the model light and high narrates a guess; hold effort at low and the capable model never gets asked to think at all.
Effort and model are provably independent, not just definitionally independent: the accounts endpoint stayed matched or overkill regardless of which model answered, and the rules engine stayed underpowered until both dials cleared their bar together. Now, the three ways Codex lets you set the model, in the order you’ll actually reach for them.
Mid-session: /model
Section titled “Mid-session: /model”When you’re already in a session and the next task wants a different gear, switch in place:
/modelIt opens a picker for the active model - and, where the model supports it, the reasoning effort alongside, so you choose the brain and how hard it thinks in one place. The change takes effect on your next prompt; nothing about the session resets. This is the move when the afternoon turns: you finished the endpoint on the light model, the rules-engine design is next, and you bump the model up without leaving the conversation you’ve built context in.
At launch: --model / -m
Section titled “At launch: --model / -m”When you already know which model you want before the session even starts, set it on the launch command:
codex -m <model> "design the categorisation rules engine"--model (short -m) overrides the model from your configuration for that run. It’s the right form when the whole session is one kind of work - a heavy design session, or a long run of mechanical edits - and you don’t want to switch partway through.
Per-invocation: -c model=…
Section titled “Per-invocation: -c model=…”The third form is the same -c key=value override you met on the effort dial, pointed at the model key. It sets the model for one invocation without changing any config:
codex -c model="<model>" -c model_reasoning_effort="high" "..."This is how you set both knobs for a single run - a specific model and a specific effort - without touching your standing defaults. It’s exactly the capable/high pairing that produced the matched design above. When a dedicated flag exists, prefer it (-m reads better than -c model=…); -c earns its place when you’re setting several keys at once, which is exactly what the next lesson turns into a reusable bundle.
The current flags and their short forms live in the CLI reference - pin to it rather than to memory, since these shift.
Why this lesson names no model, and why you should not memorise one
Section titled “Why this lesson names no model, and why you should not memorise one”You’ll notice none of the commands above, or the traces before them, name an actual model, and that’s deliberate. The available models and capabilities depend on the surface, account, workspace policy, and authentication method. ChatGPT sign-in and API-key workflows are not guaranteed to expose the same catalogue, and model names change faster than a course can track. Read the picker and the authentication documentation, then trust what the current session actually offers. For raw codex exec automation, use CODEX_API_KEY; keep the exact model selection explicit only after checking that it is available to the runner.
When speed is the thing you’re buying
Section titled “When speed is the thing you’re buying”There’s a lever here that isn’t about reasoning at all - it’s about latency. Some sessions are interactive in a way where waiting hurts: live iteration, firing a prompt every half-minute, where the agent’s response time is the bottleneck rather than its thinking. Codex exposes a priority service tier for exactly this - faster responses at the same intelligence, by prioritising the infrastructure rather than dialing the model down. You’ll have seen it as a /fast-style command in the TUI, surfaced when the active model advertises the tier; it can also be set as service_tier = "fast" in config.
Two things to keep honest about it. First, it changes speed, not capability - it won’t make a light model reason like a heavy one, and it won’t turn low into high. Second, the priority tier rides on the subscription sign-in, another place your auth tier decides what’s available. The exact UX - the slash command, where it surfaces, whether it’s a toggle or a per-run flag - is version-dependent and data-driven from the model catalogue. Don’t memorise the literal /fast; open the TUI and check what your session actually offers. The current behaviour is documented under speed.
You now have both knobs and all three timings for setting them - mid-session, at launch, per-invocation. Setting them by hand every time gets old fast when the same combinations keep recurring. The next lesson bundles them into a named profile you select with one flag.