---
title: "Codex Skills: Build a Reusable Workflow"
description: "How to create a skill in Codex: when a prompt earns one, the SKILL.md format OpenAI documents, a full worked skill that refuses bad inputs, and how to run it."
canonical_url: "https://builderscamp.com/guides/tools/codex-skills-reusable-workflows"
date_published: "2026-10-05"
date_modified: "2026-10-05"
author: "Guilherme Salgueiro"
publisher: "Builders Camp"
guide_class: "tools"
---

# How to create a skill in Codex: turning a repeated instruction into a reusable workflow

**TL;DR:** Create a Codex skill on the third time you type the same instructions: a folder in .agents/skills holding a SKILL.md with a name, a description that says when to use it, and numbered steps. The part that makes it reusable rather than a saved prompt is a list of required inputs the skill refuses to run without. Invoke it with $ and its name, and test the description against prompts that should and should not trigger it.

## When is an instruction worth turning into a Codex skill?

On the third time you type it. Builders Camp teaches this as the third-use rule in its AI operating system material: write the prompt the first time, notice the repetition the second, convert it into a skill the third. The first two runs are how you find out what the instructions actually need. OpenAI's [Codex best practices](https://learn.chatgpt.com/guides/best-practices) land on the same test from the other side: "if you keep reusing the same prompt or correcting the same workflow, it should probably become a skill."

The second half of that sentence matters more than the first. Typing the same prompt is mild waste. Correcting Codex the same way twice means the instructions you keep giving live in your head instead of in a file, and every teammate who runs the same job gets the uncorrected version. OpenAI's own list of good candidates is mostly product-adjacent work: release note drafting, PR review against a checklist, incident summaries, log triage.

## What is a Codex skill made of?

A skill is a folder with a `SKILL.md` file in it, plus optional folders for scripts, reference documents and assets. The [Codex skills documentation](https://learn.chatgpt.com/docs/build-skills) states the one hard requirement: "The SKILL.md file must include name and description." Everything else is instructions in plain markdown.

```text
.agents/skills/release-notes/
  SKILL.md              required: name, description, instructions
  references/style.md   optional: loaded only when the skill points to it
  agents/openai.yaml    optional: invocation policy and display settings
```

Codex loads skills progressively. At the start of a session it sees only each skill's name, description and file path, and reads the full `SKILL.md` when it decides to use the skill. The [skills documentation](https://learn.chatgpt.com/docs/build-skills) sets a budget for that opening list of at most 2 percent of the model's context window, or 8,000 characters when the window is unknown, and Codex shortens descriptions first when many skills are installed. That figure is the cap on the list, not on the skill itself, but it explains why the description has to front-load its trigger words: a long, polite description is the first thing to get cut.

Where the folder lives decides who gets the skill. As documented in October 2026, Codex scans `.agents/skills` in every folder from where you started it up to the repository root, and also reads `$HOME/.agents/skills` for your personal skills, plus admin and built-in locations. Commit team skills at the repository root so every subfolder sees them.

## What does a complete product skill look like?

Here is a full skill for a job most product teams repeat every release: customer-facing release notes built from the pull requests merged since the last tag. It lives at `.agents/skills/release-notes/SKILL.md` in the same invoicing repository used in the [AGENTS.md guide](https://builderscamp.com/guides/tools/how-to-write-agents-md-for-codex).

```markdown
---
name: release-notes
description: Draft customer-facing release notes from pull requests merged between two git tags. Use when asked for release notes, a changelog entry, or what shipped in a version. Do not use for sprint summaries, incident reports or internal status updates.
---

# Release notes

## Required inputs
Stop and ask for any input that is missing. Never pick a default.
- from_tag: the last released tag, for example v2.13.0
- to_tag: the tag or branch being released, for example v2.14.0
- audience: customers or internal

## Refuse and explain when
- Either tag does not resolve. Check with: git rev-parse --verify <tag>
- The range holds more than 40 merged pull requests. Ask whether to split it.
- A pull request in the range has an empty description. List it and stop.

## Steps
1. List merged pull requests in the range:
   git log --merges --first-parent --format='%s%n%b%n---' <from_tag>..<to_tag>
2. Drop pull requests labelled chore, refactor, test or deps, unless the
   description names an effect a customer would notice.
3. Group the rest under New, Improved and Fixed. One line each, written from
   the customer's side ("You can now export invoices as CSV"), not the code's.
4. End each line with the pull request number in brackets so it can be traced.
5. Any change to billing, tax or permissions goes in a final list called
   "Check before publishing" instead of the customer sections.
6. Apply the tone and banned words in references/style.md.

## Output
- Write the notes to docs/releases/<to_tag>.md. Do not commit or push.
- In chat, report: pull requests read, kept and dropped, and one reason per drop.
```

Three parts of that file do the real work. The description reads as a trigger with its exclusions, so Codex can tell "what shipped in 2.14?" from "summarise this sprint". The refusal block gives the skill a way to say no: without it, an empty pull request description becomes an invented customer benefit, and the output looks exactly as tidy as a correct one. And the "Check before publishing" list routes the lines that can hurt you, billing and permissions changes, to a person instead of to customers.

The style rules sit in `references/style.md` rather than inline, so they stay out of context until step 6 asks for them. The skill also says where its output goes and that it must not commit, which matters once you run it in a mode that lets Codex write files without asking.

## How do you invoke the skill and check it triggers correctly?

There are two ways in, per the skills documentation. Explicitly: in the Codex CLI or IDE extension, type `$release-notes` or pick it from `/skills`; in the ChatGPT desktop app, enabled skills also appear in the slash command list. Implicitly: Codex selects the skill when your request matches its description. An explicit call for this skill looks like:

```text
$release-notes from_tag=v2.13.0 to_tag=v2.14.0 audience=customers
```

OpenAI's best practice list includes "Test prompts against the skill description to confirm the right trigger behavior." Do it with a small table before anyone else relies on the skill:

| Test prompt | Should the skill run? | What a pass looks like |
|---|---|---|
| "What shipped between 2.13 and 2.14? Need it for the customer email." | Yes | Skill loads, asks for audience only if unclear |
| "Write release notes for 2.14." | Yes | Skill loads, stops to ask for from_tag |
| "Summarise what the team did this sprint." | No | Codex answers without the skill |
| "Draft the incident report for Tuesday's outage." | No | Codex answers without the skill |

If the third or fourth row triggers the skill, tighten the "Do not use for" clause. If you only ever want the skill to run when someone asks for it by name, add `agents/openai.yaml` with `policy:` and `allow_implicit_invocation: false`, and explicit `$release-notes` calls keep working. Codex picks up skill edits automatically; the docs say to restart Codex if a change does not appear.

## Can Codex write the first draft of a skill?

Yes, and it is a fast start. The skills page documents a built-in creator you invoke with `$skill-creator`; it asks what the skill does, when it should trigger, and whether it should be instructions only or include scripts, with instructions only as the default. Give it the transcript of the last time you did the job by hand, then edit the draft the way you would edit any generated file: rewrite the description as a trigger, and add the inputs it must refuse without, because a generator has no way to know which missing input will burn you.

## When is a skill the wrong mechanism?

A skill is a procedure you run some of the time. Three other homes fit other kinds of instruction, and putting a rule in the wrong one is the most common way a skill library goes bad.

- If the rule holds on every task in the repository, such as "money is integer cents", it belongs in AGENTS.md, which Codex reads before any work. A skill holding it only applies when that skill runs.
- If the rule must never be broken, such as "never write to the production config", a skill and AGENTS.md are both just text Codex follows. Use the sandbox and approval settings, a hook, or a CI check that fails the build.
- If the job is one-off, write the prompt and move on. A skill used once is a file someone has to maintain for no return.

The honest limitation is upkeep. A skill encodes how you did the job on the day you wrote it, and it keeps doing the job that way with total confidence after the process has changed. OpenAI's advice to "Keep each skill focused on one job" is partly about this: a small skill is easy to notice going stale and cheap to rewrite.

## What should a team do with a skill once it works?

Share it in the repository first. Personal skills in `$HOME/.agents/skills` help one person; a skill committed to `.agents/skills` is also the most accurate onboarding document the team has, because it is the procedure you actually run rather than one someone meant to write down. When a skill needs to reach other repositories or be installed by people outside the team, the Codex docs point to packaging it as a plugin instead of copying folders around.

Then review the library the same way you review AGENTS.md: once a month, list the skills, check which ones ran, and delete the ones that did not. A skill that has not been invoked in a month is either solved by something else or no longer how the work is done.

## Build the second skill from your review checklist

Release notes are a gentle first skill because the output is a draft a person reads before it goes anywhere. The second skill worth writing is the checklist you apply before a pull request is opened, so the evidence a reviewer needs is produced the same way every time. The [guide to reviewing Codex pull requests](https://builderscamp.com/guides/tools/reviewing-codex-pull-requests) has the PR description template that skill would fill, and the [Codex feature build loop](https://builderscamp.com/guides/tools/codex-feature-build-loop) shows where it runs in a full feature.

[See the Building with Codex bootcamp](https://builderscamp.com/bootcamps/building-with-codex?utm_source=guide&utm_medium=organic&utm_campaign=codex-skills-reusable-workflows) for the session plan and the next cohort dates.

## Frequently asked questions

### Where do I save a Codex skill so my team gets it?

In .agents/skills/<skill-name>/SKILL.md inside the repository, committed like any other file. As documented in October 2026, Codex scans .agents/skills in every folder from where you start it up to the repository root. Personal skills go in $HOME/.agents/skills and follow you across repositories.

### What does a SKILL.md file need at minimum?

YAML front matter with a name and a description, then the instructions in markdown. Folders for scripts, references and assets are optional. Start with instructions only and add a script when a step needs to behave exactly the same way every time.

### How do I run a skill in Codex?

Type $ followed by the skill name in the Codex CLI or IDE extension, or pick it from the /skills list. In the ChatGPT desktop app, enabled skills also appear in the slash command list. Codex can also choose a skill on its own when your request matches the skill's description.

### How do I stop Codex running a skill without being asked?

Add an agents/openai.yaml file inside the skill folder with policy: allow_implicit_invocation: false. Codex then runs the skill only when you invoke it explicitly with $ and its name. Use this for skills that write files or post anything.

### Does every installed skill cost context on every task?

Only its name, description and file path. OpenAI documents that the initial skills list uses at most 2 percent of the model's context window, or 8,000 characters when the window is unknown, and the full SKILL.md loads only when Codex selects the skill.

### Can Codex write the skill for me?

Yes. Invoke $skill-creator and it asks what the skill does, when it should trigger, and whether it needs scripts. Treat its draft like a generated AGENTS.md: a starting point you edit, especially the description and the inputs the skill must refuse without.

### When should a rule go in AGENTS.md instead of a skill?

When it is true on every task in the repository, such as how money is stored or which test command to run. A skill is for a procedure you run some of the time. If a rule must never be broken, neither file is enough; use the sandbox, a hook or CI.

## Sources

- [OpenAI Codex docs: Build skills](https://learn.chatgpt.com/docs/build-skills)
- [OpenAI Codex docs: Best practices](https://learn.chatgpt.com/guides/best-practices)
- [OpenAI Codex docs: Slash commands](https://learn.chatgpt.com/docs/reference/slash-commands)
- [OpenAI Codex docs: Custom instructions with AGENTS.md](https://learn.chatgpt.com/docs/agent-configuration/agents-md)

## How this guide was made

Researched from Builders Camp's bootcamp, track and masterclass material and the sources listed on this page, drafted with AI, and fact-checked against every source cited.
