Course · Codex · Automation
Automation
Extending gave a single session more reach than it started with - a server it could query, a hook that could stop it cold. Every one of those still assumed you were in the room: launching Codex, watching the diff, answering the pause. This chapter takes you out of the room. budgetcli grows two jobs that run with nobody watching - a report that writes itself once a month, and a check that fires on every push - and the villain that’s been running under this whole course shows up here in its sharpest form: there is no human left in the loop to catch the wrong turn.
Here’s the contract this chapter holds to, stated once so every lesson can lean on it. The loop has four beats - read, propose, approve, apply - and a headless run is that exact loop with one beat removed. Approve doesn’t get replaced by nothing; it gets replaced by two things, decided at different times. The sandbox becomes the fence approve used to be, except it’s set before the run starts instead of during it - it can’t be talked to, only configured. The rules file becomes the only brief, because there’s no back-and-forth left to correct a misunderstanding mid-run - whatever isn’t already written down, the run never learns. And the exit code, backed by whatever you actually wired the run to check, becomes the review you used to do by hand, reading the diff before you’d let it commit. Every setting this chapter touches is one of those three doing the job a person used to do.
The two jobs, and the run underneath both
Section titled “The two jobs, and the run underneath both”budgetcli has two chores that keep landing on a human by hand:
- The monthly report. At month-end, someone runs the categoriser, totals spend against
budgets.toml, and writes up whatever went over. - The transaction check. Every time a fresh CSV batch lands, something needs to recategorise it and run the suite, so a malformed import gets caught at the door instead of corrupting months of history quietly.
Both chores are the same shape underneath: read some files, decide something, write a result, and tell you whether it worked. That shape is codex exec - the one command this whole chapter is built on - and the running example we’ll trace stage by stage is the monthly report, because it’s the smaller of the two jobs and every stage shows up cleanly on it before the transaction check adds a second wrinkle: something other than you pressing the button.
What the payoff actually costs
Section titled “What the payoff actually costs”State the payoff before you’ve configured anything, so you can check it against the arithmetic as you go. The categoriser budgetcli’s report depends on - src/budgetcli/categorise/rules.py, 512 lines - costs about 5,120 estimated tokens every time a run reads it fresh, at 10 tokens per line. (Full method: About the numbers.) Against a 200,000-token window that’s nothing, 2.6% of it - and it still recurs every single month, forever, because a headless run knows exactly as little at the start as an interactive one does. The report will cost that every month whether one person reads the number it produces or nobody ever does again - and the entire difference between those two outcomes is two flags and an exit code, not tokens. That’s the claim. The rest of the chapter re-derives it.
We’ll build the trace in order:
- Generate the monthly report headless with
codex exec- one call, one result, one exit code; the beat that goes missing and what fills the gap - Wire the transaction check into CI on every push - authentication with no browser, the posture that has to be granted before the run exists, and what the exit code is actually worth
- Make CI runs reproducible with
--ignore-user-configand--ignore-rules- strip everything that isn’t the committed brief, so the run means the same thing on any machine - Reach for the Codex SDK when
execruns out of room - where one call stops being enough, and the chapter’s ledger row
By the end, budgetcli’s report writes itself and its transactions get checked without you - and you’ll know exactly which stage of that unattended run is the one you can’t take back.