Skip to content

Course · Codex · Skills

Skills

Some work you do with a coding agent is a procedure you keep narrating: every time a bank’s export lands in the course’s example repo, the same import steps travel from your head into the chat window by hand - which column is the date, which the amount, how cents come out of the decimal string, where the importer goes, what proves it worked. The file is always different. The steps never are. And a new session starts cold to them, because they are written down nowhere the agent reads.

This chapter is about writing a procedure down once so the agent runs it on recognition - noticing the situation and loading the steps itself, without you naming anything.

Quick check before you build anything: search your own project’s chat history for an instruction longer than two sentences that you have typed, close to verbatim, more than once. Found one? You already own this chapter’s problem, in your own repo, right now. If nothing turns up yet, the habit still pays the first time one does - skim the decision lesson and come back once you have hit it.

Ground truth first: budgetcli (the course’s running example, a small self-hosted personal-finance API in Python and FastAPI) imports one format today. app/importers/csv.py is the repo’s one importer, built for the CSV shape the project shipped with - ISO dates, a single decimal amount column, a description. It works, the suite pins it, and the money path through it runs on Decimal. What it does not do is accept any other bank’s idea of a CSV.

Constructed scenario, labeled once for the chapter: the fourth bank, its differently shaped export, and the sample file data/newcard.csv are this course’s defined teaching scenario. Nobody has run it. It is a definition, not a log, and every turn count in this chapter belongs to it.

Onboarding a new format is the same job every time, even though the file is always different:

  • read a sample of the export, identify the date, amount, and description columns, and note the formats - date shape, a single signed amount column or separate debit and credit columns, any thousands separator
  • map the columns onto budgetcli’s transaction fields and normalize the dates to the stored ISO format
  • convert each amount to integer cents without passing through a float
  • write a small importer under app/importers/, following the one that exists
  • run it against the sample, show parsed rows back for confirmation, and pin the conversion

Five steps, unchanged from bank to bank. What changes is only ever the file in front of you.

Plenty is already written down. AGENTS.md - about 115 estimated tokens - loads into every session and holds the standing rules: integer cents, never floats; ISO 8601 dates. The saved profile has the trust posture pre-decided. With those in place, the bare-repo mistakes do not happen. What no file holds is the procedure itself, so watch what a cold import still costs, narrated fresh:

  1. You describe the job in plain English. Codex reads the sample and reports its column guesses.
  2. It asks which column holds the amount - this bank splits debits and credits into two columns, and nothing in your description mentioned that wrinkle, because you forgot it until asked.
  3. You answer; it proposes the mapping and the conversion; you say go ahead.
  4. It writes the importer and runs the sample - and mis-parses this bank’s amounts, because the standing cents rule never spelled out this bank’s thousands separator. Not the float bug back again; that path runs Decimal and is pinned. A fresh procedural miss no standing rule was written to catch.
  5. You catch it reviewing the parsed rows, correct it, and it fixes the conversion.
  6. It reruns against the sample, the rows check out, and you confirm and commit.

Six turns, every bank, cold, forever - because the five steps live in your head, and your head gets asked to produce them from scratch every single time.

Where the six sits: it is the defined scenario with the rules file and the saved profile already in place, measured against a plain prompt - the combination, not either piece alone. This chapter’s job is the last step of that stack.

Add the skill this chapter writes, and the same defined scenario puts the job at two turns: you describe the situation in your own words, Codex recognizes it, and the body that already knows the steps - including the thousands-separator check - runs before your second message. A third of the six-turn cost, and the separator miss never happens, because the step that catches it is written at the exact point it bites.

You will watch that two-turn run two lessons from now, as a labeled reconstruction you can count against the six above. It is the scenario’s measurement, not a captured log - the same honesty rule as every number in this course.

(Every number in this chapter follows the two estimators from the first chapter - ten tokens per line of code, four characters per token for prose - against the same 200,000-token window.)

A Skill is a directory with a SKILL.md file inside it. The frontmatter says when to use it; the body says what to do. At session start Codex builds an initial skills list carrying each skill’s name, description, and path, and keeps that list in context - capped at roughly two percent of the context window, or 8,000 characters when the window is unknown. On this course’s arithmetic, two percent of 200,000 tokens is 4,000.

The cap has a shape worth knowing before your catalog grows. When many skills are installed, Codex shortens descriptions first; for very large catalogs it omits some skills from the list entirely, with a warning. One skill of ours costs about ninety estimated tokens against that four-thousand budget, so none of this bites yet. And when a request matches a description, Codex reads the full instructions and follows them - no procedure re-pasted, no shape re-explained.

You can still name a Skill explicitly when you want to; the new thing is that it can fire on recognition, without you naming it at all. Skills are documented on the Codex Skills page; this chapter walks the whole arc on one concrete procedure:

  • Author the Skill - the directory, the SKILL.md, the frontmatter and body - and build the import procedure end to end in .agents/skills/.
  • Make it fire at the right time - meet recognition, watch the six turns above collapse to two, and tune the field that decides whether the Skill fires.
  • Know when a Skill is the wrong tool - Skill vs AGENTS.md rule vs a plain prompt, run on the same job, with a verdict for each.

By the end, importing a new format is something Codex owns, not something you narrate. Start by giving the procedure a home Codex can find on its own.