Skip to content

Course · Codex · Daily workflow

Briefing the agent well and smoothing the editing surface on budgetcli

The last lesson fixed the posture you work in; combined with the rules file, it took the course’s constructed fourth-bank job from 11 exchanges to 6 (the fourth bank is the teaching scenario; the repo imports a single format). This lesson protects the rest of the gain - not by adding a fifth technique, but by making sure the two you already built, the skill and the effort dial, land the way they were measured.

A profile without a sharp brief still burns a turn on a misread. A skill still has to be asked for cleanly, or it never fires at all.

Here is the difference that catches people. Chatting with a model, a vague question is cheap: you read the half-useful answer and ask again, and you have lost seconds. With an agent, one prompt can trigger a chain of work - read the importer, edit the parse path, run the tests, edit again - that grinds for minutes before it surfaces anything you can review.

By the time an ambiguous instruction bites, the agent has touched files on the strength of a guess. Vagueness did not cost you a re-ask; it cost you a run and a diff to unpick. The whole skill is reducing the ambiguity before execution starts, not correcting it after.

A prompt the agent cannot misread on budgetcli (the course’s running example, a small self-hosted personal-finance API in Python and FastAPI) has the same four parts every time. You do not need a template or a heading for each - just do not leave one out. (The new card’s export below is that constructed fourth bank.)

  1. Goal - what done looks like, in one concrete sentence, with an outcome verb. Not “look at the CSV importer,” but “extend app/importers/csv.py to read the new card’s statement format.”
  2. Context - the framework, and an analogous bit of the codebase to copy. “It is the same FastAPI service; follow the pattern in app/importers/csv.py, the one importer the repo has.” A pointer to existing code is worth a paragraph of description - the agent reads the reference and matches it.
  3. Constraints - what not to do. “Do not add new dependencies, do not change what POST /transactions accepts, money stays integer cents.” The off-limits list is where most wrong-but-reasonable runs come from: the agent will confidently make a technically fine choice that is wrong for this project if you never told it where the edges are.
  4. Completion criteria - a check it can actually run. “The new export imports and pytest exits clean.” Now the agent knows when it is finished instead of when it is tired.

A useful gut-check for scope: the sweet spot is a task a colleague could finish in an afternoon, with a clear before-and-after. Bigger than that, break it into ordered steps, each with its own small verification gate - the file parses, then the rows categorize, then the suite passes - so a wrong turn surfaces at the next gate instead of three changes downstream.

Most of this only needs saying once, though. The durable stuff - money is integer cents, dates are ISO, the test command - already lives in the AGENTS.md the repo has carried all week, and the agent reads it at session start. That is the point of writing things down: your per-task prompt carries only what is specific to this task. If you catch yourself re-typing a convention into every prompt, it belongs in the rules file, not the prompt.

Stop and rewrite - don’t nudge a bad run

Section titled “Stop and rewrite - don’t nudge a bad run”

When a run starts heading somewhere wrong, the instinct is to nudge it back: “no, not like that, do it this way instead.” Sometimes that works. But when the run went wrong because your prompt had two valid readings - and the agent picked the one you did not mean - nudging is the slow road. You are correcting on top of a foundation built from the wrong interpretation, and each correction inherits the original ambiguity.

The course lived a real two-reading prompt in the models chapter: “wire the categorizer into the import.” It had two valid homes - inside parse_csv, or in the import_csv loop in app/main.py - and they are not equivalent. The faster move, always, is to stop, throw the run away, and rewrite the brief so the reading you wanted is the only one left: “categorize inside parse_csv, so the parse hands the ledger fully labeled transactions,” stated up front rather than discovered three corrections in.

Reframing beats patching because the ambiguity was a bug in the prompt, not a failing of the agent. Interrupt immediately - the longer a misread run goes, the more diff you are discarding. A clean restart from a sharper brief beats five rounds of “no, the other thing.”

This is also why the budget-audit profile earns its place. While you are still figuring out what to ask for, explore with the agent unable to write - the cost of a misread is zero, because nothing changed. You switch to budget-build only once the brief is sharp enough to commit to.

The brief is the big lever. The small one is the friction in actually typing it - and because you do it dozens of times a day, small friction adds up to more than it looks.

The two ergonomics worth building into reflex:

  • Point at files by path instead of describing them. When you mean a specific file, name it rather than spending a sentence on where it lives - app/importers/csv.py lands faster and more precisely than “the CSV importer, in the importers folder.” Letting the agent resolve a path you typed is cheaper than letting it guess one from prose.
  • Let your shell carry your defaults. If you almost always want the same profile, you should not be re-typing it. The alias from the last lesson, or a small wrapper function, means a bare codex lands in the posture you want most, and you spend explicit flags only on the exception.

None of these is a feature you learn once; they are habits that shave a second off the action you repeat most. Over a week on budgetcli that is the difference between the tool feeling like a chore and feeling like an extension of your hands. The current set of input affordances is worth a skim in the Codex CLI reference so you adopt the ones that fit how you work.

Send a follow-up while Codex is still working

Section titled “Send a follow-up while Codex is still working”

A correction does not have to wait for the turn to finish. The Codex 0.163.0 release notes say you can send a follow-up while Codex is responding to steer it immediately, and that interrupting a turn also stops active Code Mode cells and their nested tool calls (release notes, read 2026-10-25). The earlier steer feature flag is listed as removed in codex features list, which is consistent with steering now being built in rather than opt-in.

The flag behind this is instant_interrupt, added as opt-in in 0.159.0 and switched on by default in 0.163.0 (#51812). codex features list still labels it under development; --disable instant_interrupt restores the old wait-for-the-turn behaviour if it misbehaves.

For a session you are not sitting in front of, codex queue adds a message to an existing one:

Terminal window
codex queue --thread <session-uuid-or-name> --message "also run the integration tests"

Queued prompts wait their turn, and from 0.164.0 they also wait for pending permission selections to resolve before continuing. Steer for a small correction, interrupt and rewrite when the brief itself was wrong, as the section above describes.

/goal sets a persistent goal for Codex to work toward. The terminal TUI describes it as “set or view the goal for a long-running task” (codex-rs/tui/src/slash_command.rs at rust-v0.163.0, read 2026-10-25), and goals is a stable flag in codex-cli 0.163.0. Release 0.140.0 made /goal keep oversized text, large pasted blocks and image attachments, and 0.155.0 added recovery of saved threads and active goals after a background-server restart. The desktop-app reference suggests shaping the goal with /plan first.

Use it for work that spans many turns toward one outcome, such as “all tests under tests/importers pass and no function exceeds 40 lines”. Draft the goal in plan mode first so the finish line is checkable; a goal like “improve the importer” gives the agent nothing to stop on.

These are all from release notes, not tested here. Check /help or the release page if a name differs on your version.

  • /tui chooses an optional fullscreen UI for your next launch, with transcript search and mouse selection (0.156.0). Release 0.157.0 made fullscreen transcripts the default; inline mode is still available with --no-alt-screen.
  • /config opens searchable settings, applies supported changes immediately, and shows which need a restart (0.163.0).
  • /keymap edits key bindings and has a leader key, Ctrl+X by default (0.163.0). Vim mode in the composer supports u for undo and Ctrl+R for redo (0.153.0) and . to repeat the last edit (0.150.0).
  • /presets saves reusable prompts and slash commands in ten numbered slots (0.164.0).
  • /usage opens an analytics dashboard of token totals and plugin and skill activity (0.156.0).
  • /voice starts or stops a voice conversation (F8 toggles it; 0.156.0 made voice conversations enabled by default, and from 0.163.0 F9 mutes). Availability follows platform support (0.155.0 introduced /voice as experimental). /voice settings chooses a voice.
  • @ opens a mentions menu for files, plugins and skills (0.140.0), and 0.150.0 added @ mentions of other Codex tasks.
  • /copy offers a picker for the full response, individual code blocks and blockquotes (0.150.0).

Image input works from the start: codex "fix the layout" -i screenshot.png attaches an image to the first prompt. -i takes a list, so put the prompt before it (or end the list with --: codex -i screenshot.png -- "fix the layout"); otherwise the prompt is read as a second image file. Several images can be given to one -i or by repeating it. image_generation and view_image are stable flags in the 0.163.0 list.

Not every prompt deserves your full attention budget. Reformatting a docstring, renaming a field, regenerating a fixture - low-stakes, well-specified, and you mostly want the answer quickly rather than carefully. Fast mode - the latency tier covered in Switch models - is worth reaching for on these mechanical sweeps.

Pair it with the light end of the reasoning-effort dial and you have a genuinely fast loop for the trivial stuff, which frees your patience for the prompts that deserve it.

The skills chapter already ran this exact comparison and put a number on it: the same fourth-bank job, once the import procedure is packaged as a skill instead of narrated fresh each time, drops from 6 turns to 2. That is not this lesson’s number to claim - the skill mechanically closes the gap, by recognizing the situation and running the five import steps itself instead of waiting for you to spell them out again.

What a sharp brief and a matched effort setting buy is smaller and easier to miss: they stop those 2 turns from creeping back to 3 or 4 when the skill needs a nudge - a column that does not map cleanly, a date format it guesses wrong - and they keep each turn cheap. This task is pattern-following work, the same corner the category-filter endpoint sat in. Reach for high effort anyway and you are spending more tokens for the same two turns, not fewer.

The skill buys the turn count. The brief and the dial are what stop you from losing it back.

That is most of the friction. You have profiles you switch by instinct, briefs sharp enough that runs go where you meant, and the small ergonomics that make the common case free. But even sharp briefs go sideways sometimes - the next lesson is the recovery reflex for when a run loops or drifts, and the honest reading of whether the stack actually holds.