Skip to content

Course · Codex · Automation

Automation

Everything built so far - the trust postures, the rules file, the hooks and external tools from the extending chapter - has one thing in common: a human launched every run, read every diff, and answered every pause.

This chapter takes you out of the room and asks the question that was left hanging: what runs when nobody watches, and what does fail-shut even mean when there’s no one to fail in front of?

budgetcli (the course’s running example, a small self-hosted personal-finance API in Python and FastAPI) grows two jobs that run unattended, and the villain underneath this whole course arrives at its sharpest form here: there is no human left in the loop to catch the wrong turn.

Constructed scenario, labeled once for the chapter: the two jobs are not features of the repo. There is no report writer, no scheduled importer, no budgets file - there never was. They are this course’s defined teaching chores wrapped around two explicitly different states. The unpublished starter fixture has the categorizer at app/services/categorise.py, a float-based money parse in app/importers/csv.py, and six tests. The course’s labeled continuation later replaces that parse with Decimal and grows the suite to ten tests. The statements directory under ~/budget-data/ is constructed too. Nobody has run these jobs. They are definitions to reason with, not logs.

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 three things, each decided at a different time.

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 committed brief becomes the only brief, because there’s no back-and-forth left to correct a misunderstanding mid-run: whatever isn’t written down where Codex reads by default, 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 before letting a diff commit.

Every setting this chapter touches is one of those three doing a job a person used to do.

Both chores keep landing on a human by hand, and each is small enough to trace whole:

  • The monthly report. At month-end, run the month’s statement through the categorizer, total spend per category, and write up whatever went over.
  • The transaction check. Every time a fresh CSV batch lands or a push touches the import path, something needs to recheck the money paths and run the suite, so a malformed import gets caught at the door instead of corrupting months of history quietly.

Underneath, both are the same shape: 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. The running example traced stage by stage is the monthly report, because every stage shows up cleanly on it before the transaction check adds a second wrinkle: something other than you pressing the button.

State the payoff before configuring anything, so you can check it against the arithmetic as you go. What does an unattended report run read? On the starter fixture, little: the categorizer is 18 lines, the ledger 18, and the Python files total 166 lines (about 230 lines when tests, config, rules, and README are included). At the course’s rough 10-tokens-per-line teaching estimate, that is about 2,000 tokens, around one percent of a 200,000-token window. (Estimators covered once in the opening chapter.)

So the tokens are not the cost. This is: the report will run every month forever, 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:

By the end, the report writes itself and the checks run without you - you’ll know exactly which stage of an unattended run is the one you can’t take back, and which parts of this chapter’s automation were written rather than run.