Write the description so Codex invokes the Skill at the right moment
The Skill runs when you name it, but the whole point was that you wouldn’t have to — that Codex would notice you’re loading a new bank’s export and run the import procedure on its own. Whether that happens, and whether it happens at the right time, comes down almost entirely to one field: the description.
How Codex decides
Section titled “How Codex decides”Codex keeps every Skill’s frontmatter — its name and description — loaded so it always knows what’s on the shelf. The full body of a Skill only loads when the Skill actually fires. So the description does double duty: it’s both the menu Codex reads and the trigger it matches against. When your message looks like the situation a description names, Codex pulls in that Skill’s instructions and follows them. When it doesn’t, the Skill stays closed and costs almost nothing.
That means the description isn’t documentation — it’s the interface. A vague one is the number-one reason a Skill sits there and never fires. To keep the menu from crowding the context window, Codex caps how much room the loaded Skill list can take, so a long-winded description competes for space with every other Skill’s. The mechanics and the limits are on the Codex Skills page; the craft is in what you put in the field.
Describe the situation, not the Skill
Section titled “Describe the situation, not the Skill”The instinct is to write a description that says what the Skill is:
description: Imports bank CSV files.True, useless. It names the Skill; it doesn’t name the moment you’d want it. Codex has nothing to match against, because you’d never say “import a bank CSV file” in those words — you’d say “here’s a statement from my new card.” Compare the version from the last lesson, which names the situation and the things you’d actually type:
description: >- Import a new bank or credit-card CSV export into budgetcli when the file's column layout isn't one budgetcli already handles. Use when the user wants to onboard a new bank, add support for a statement export, or import transactions from an unfamiliar CSV shape.The pattern that works: what it does, then when to use it, in the user’s words. That second half — “onboard a new bank… add support for a statement export… an unfamiliar CSV shape” — is a list of the phrasings you actually reach for. Front-load the key use case, because the loaded listing is space-capped and gets truncated if it runs long, so the first sentence has to carry the trigger.
Test that it actually fires
Section titled “Test that it actually fires”A Skill you only ever invoke by name might as well be a saved prompt. So prove the recognition works. Open budgetcli, point Codex at a sample export from a bank it hasn’t seen, and say the kind of thing you’d really say — without naming the Skill:
> got a statement export from my new credit card in data/newcard.csv. can you get these transactions into budgetcli?
⎿ Using skill: import-bank-csv Read 6 rows of data/newcard.csv date → column "Posted Date" (MM/DD/YYYY) amount → column "Amount" (single signed column) description → column "Description"
Sample mapping (raw → stored): 04/12/2026, "-42.50", "CORNER MARKET" → 2026-04-12 · -4250 cents · "CORNER MARKET" 04/13/2026, "18.00", "REFUND - ACME" → 2026-04-13 · 1800 cents · "REFUND - ACME"
Mapping looks right? I'll write the importer and run the full file.The Using skill: import-bank-csv line is the recognition firing — you described a situation, and Codex matched it to the Skill and ran the body without being told which one. Notice the amounts came back as integer cents, the rule the Skill body restated at exactly the spot it matters. That’s the behaviour the whole chapter is building toward. If it doesn’t fire when you expect it to, the fix is almost always the description: it’s missing the words you actually used. Add the phrasing you’d really type and try again.
You can also invoke a Skill on purpose — by referencing it by name in your prompt, or from the /skills picker in the TUI — which is the fallback when you want the procedure right now regardless of how you phrased the ask.
The opposite failure: firing too often
Section titled “The opposite failure: firing too often”A description tuned too broad has the reverse problem — the Skill fires when you didn’t want it. Imagine you’d written “use whenever working with a CSV.” Now Codex tries to run the full import procedure the moment you so much as open a CSV to glance at it, even when you only wanted to read a couple of rows. The cure is to make the description narrower and more specific — pin it to the genuine onboarding moment (“a new bank,” “a layout budgetcli doesn’t already handle”) rather than any mention of CSVs.
Taking a Skill off the automatic menu
Section titled “Taking a Skill off the automatic menu”Some procedures you never want Codex deciding to run on its own — anything expensive, slow, or state-changing where a mistimed trigger is costly. Codex gives each Skill an optional companion config file, agents/openai.yaml, inside the Skill directory, for exactly this kind of Codex-specific control. Among other things it carries an invocation-policy switch — set implicit invocation off and the Skill drops off the agent’s automatic menu while staying available when you name it explicitly. That turns the Skill from “fires on recognition” back into “fires only when I ask” — the line between a Skill the agent reaches for and one you keep on a leash.
Our import-bank-csv doesn’t need that — it ends in a preview and waits for your “looks right” before the full import, so a mistimed trigger costs nothing but a glance. But it’s the knob to know about, and the exact field is on the Codex Skills page. The agents/openai.yaml file is also where a Skill declares dependencies on tools it needs, which is one of the threads the next chapter picks up.
Keeping a Skill scoped to the right moment is half the discipline. The other half is knowing when a Skill is the wrong container entirely — when the thing you’re about to write down is really a rule, or doesn’t need writing down at all. Skill, rule, or plain prompt — when does each one fit?