Course · Codex · Skills
Choose between a Skill, an AGENTS.md rule, and a plain prompt
You’ve now watched recognition turn six turns into two. But “write something down so Codex does it right” describes three different containers, and reaching for the wrong one is a common way to fight the grain. This lesson is the decision: when the import procedure is genuinely a Skill, when the next thing you want to capture is really an AGENTS.md rule, and when it shouldn’t be written down at all.
Skill vs rule: what Codex does vs what it knows
Section titled “Skill vs rule: what Codex does vs what it knows”This is the distinction that matters most, and the one most often gotten wrong. Both a Skill and AGENTS.md are “context you write down once” - but they load differently and they answer different questions.
- An
AGENTS.mdrule is a standing fact. “Money is integer cents, never float.” “The category list is groceries, rent, subscriptions…” Codex readsAGENTS.mdautomatically before every run, so a rule is always in view - it shapes everything Codex does, whether or not you mention it. - A Skill is a procedure. “To onboard a new bank’s CSV: read a sample, map the columns, normalise dates, convert to cents, write an importer.” It loads only when the situation fires, runs as a sequence of steps, and is silent the rest of the time.
The test: can you run it? “Always store money as cents” isn’t something Codex runs - it’s a constraint it should hold at all times. That’s a rule. “Import a new bank’s CSV” is a multi-step thing Codex does on a specific occasion. That’s a Skill. Put a standing fact in a Skill body and it only applies when the Skill happens to fire - exactly when you don’t want a money rule to be conditional. Put a multi-step procedure in AGENTS.md and it’s loaded into every run whether you’re importing a bank that day or not, paying full context cost to sit idle.
You saw the two cooperate two lessons back: the cents-not-float rule lives in AGENTS.md as a standing constraint and the import Skill restates the rounding step at the one point where a fresh bank’s format still slips past it. That’s not redundancy - the rule governs everything; the Skill puts the check at the point of maximum risk. Rules are the floor; a Skill can reinforce the floor where a procedure tends to trip over it. The rent a rule pays for that always-on coverage is real, and it’s priced in the good-rules lesson - keep that pricing in mind for the table below.
Skill vs plain prompt: does it repeat?
Section titled “Skill vs plain prompt: does it repeat?”The other failure is over-engineering - packaging something as a Skill that didn’t need packaging. The honest test is repetition:
- One-off, or rare and varied → a plain prompt. If you’re parsing one weird file once, just ask Codex to do it in the conversation. Writing a
SKILL.mdfor it is busywork - if theSKILL.mdtakes longer to write than the task it automates, you’ve over-built. - Same multi-step procedure, again and again → a Skill. The import job cleared this bar the moment you noticed you were re-narrating the same five steps for each new bank - and paying six turns for it every time.
A good way to arrive at a Skill is to not write it first. Do the job by hand in a normal session - onboard the first new bank as a plain prompt. When you find yourself doing the same thing a third time, you’ll already know the exact steps, the failure modes, and the wording that triggers it. Then the SKILL.md writes itself, and it’s grounded in a procedure you’ve actually validated rather than one you guessed at.
Same job, three routes
Section titled “Same job, three routes”Put a number on it rather than trust the shape of the argument. Take the exact task from this chapter - onboard one unseen bank’s CSV - and run it through all three containers:
| Route | This job’s cost | Recurs next bank? | Verdict |
|---|---|---|---|
| Skill | ~80 tokens every session (the stub) + ~280 tokens only when it fires; 2 turns | Yes - the procedure is captured once | Right home |
AGENTS.md rule | The same ~280-token procedure, but loaded on every session, importing or not - on top of the ~284 tokens the existing rules file already spends | Yes, but the coverage is paid for whether or not it’s used that day | Wrong shape - pays rent idle |
| Plain prompt | ~0 tokens until you need it, but 6 turns of re-describing, re-asking, and re-correcting - the walkthrough from the chapter opening | No - you’re the memory, and the step you forget is the one that bites | Works once, taxes forever |
Same procedure, same bank, three prices. The Skill is the only route that’s both cheap on a quiet day and complete on the day it’s needed.
The three-way test
Section titled “The three-way test”When you’re about to write something down for Codex, ask in this order:
- Is it a fact Codex should always hold, or a procedure it runs on occasion? Always-on constraint or domain fact →
AGENTS.mdrule. A multi-step thing it does at a specific moment → Skill. - Does the procedure actually repeat? A genuine, recurring, multi-step routine → Skill. A one-off or rarely-the-same task → just prompt it; don’t build a file.
- If it’s a Skill, should Codex fire it on its own? Harmless if mistimed, like our preview-first import → leave implicit invocation on, let it fire on recognition. Expensive, slow, or state-changing → take it off the automatic menu with the per-Skill policy from the last lesson.
Keep those straight and you’ll almost always reach for the right container. Rules are what Codex knows; Skills are what it does; a plain prompt is for what it does once. The quiet mistake is cramming a standing fact into a Skill body, where it only loads when the Skill fires, instead of into AGENTS.md where it’s always in view - so when in doubt, ask whether the thing is a fact or an action.
You can run that judgment on the ledger it’s really about. A rule pays its full size in every run; a Skill pays a tiny always-visible stub and loads its body only when it fires; a plain prompt costs nothing until you need it - and again every time after. Four pieces of knowledge, three homes each - see what the wrong home costs:
Notice which placements the widget punishes hardest: a fact filed as a skill, because a fact has no moment of invocation and just never loads, and a procedure filed as a rule, paying rent every session for the few that need it. Those are the two swaps this lesson exists to stop you making.
What a Skill still can’t do
Section titled “What a Skill still can’t do”A Skill only orchestrates what Codex can already reach - your files, your shell, the importers already in the repo. The import procedure stays inside budgetcli because everything it touches is in budgetcli. The moment a procedure needs to touch a system outside the repo - pull a live exchange rate for a foreign-currency transaction, query an external service - or needs a check that runs every time, deterministically, no matter what Codex decides, you’ve reached the edge of what a Skill alone can do. And a Skill is still guidance, not a rule the sandbox enforces: for a security-critical condition like “never write to the real ledger,” you still want database permissions, sandboxing, and CI backing it up, the way the approvals chapter already does - not a Skill body carrying that weight alone.
The chapter’s row in the ledger
Section titled “The chapter’s row in the ledger”Score the finished Skill on the same four questions the course has used since chapter one:
| Move | Tokens | Turns | Blast radius | Recurs? |
|---|---|---|---|---|
| Read-only question (“what does this do”) | ~3,900 est. | 1 | None - nothing written | No |
| Fix the CSV date bug | ~2,100 est. (csv.py alone) | 4 | Money-adjacent - meant the date field, briefly drifted into amount | Partly - the fix holds, the habit behind it didn’t exist yet |
Onboard a new bank via import-bank-csv | ~360 est. (80 stub every session, 280 body only when it fires) | 2 | Money-adjacent - same shape as the fix above, still reviewed before write | Yes - the procedure holds for every bank from here on |
That last cell splits the same way the fix two rows up did. The date fix held because it’s a line in git; the habit behind it didn’t, because nothing carried the procedure forward to the next bank. The Skill is what closes that second gap - not just today’s fix committed, but tomorrow’s version of the same job already covered.
Skills close a real gap: Codex now owns the procedures you used to narrate, firing them when the situation calls. Next chapter gives it something a Skill alone can’t reach on its own: reach into external systems with MCP servers, and a deterministic check that runs no matter what the agent decides.