Home / Blog / Codex

Codex skills: build reusable workflows that trigger

A Codex skill is a small directory that teaches Codex one repeatable job. The hard part is not writing the checklist. It is defining the trigger, the proof of completion, and the boundary where the skill should stay out of the way.

How a Codex skill loads Your taskchanging input Name + descriptionrouting layer SKILL.mdworkflow + boundary Scripts + referencesloaded when needed Verified resultdefined completion match activate as needed execute scalably.io
Codex sees the routing layer first. The full workflow and its supporting files load only after the task matches.

I use skills for work that has a stable method but changing inputs: checking a PDF, researching an OpenAI feature against current documentation, building an on-brand diagram, or preparing a release without publishing it. The prompt changes. The standard does not.

A good skill replaces a prompt you were tired of rewriting. A bad skill adds permanent instructions to every task and fires when it has nothing useful to contribute. This guide builds one complete skill and shows how to test both sides.

What a Codex skill actually is

A skill is a directory with a required SKILL.md file and optional scripts, references, templates, and interface metadata. Codex first sees the skill's name and description, then reads the full instructions only when the task matches.

That loading model matters. OpenAI calls it progressive disclosure. The initial skill list gets a limited part of the context window, while the complete instructions are loaded only after a skill is selected. According to the official Codex skills documentation in September 2026, the initial list uses at most 2 percent of the context window, or 8,000 characters when the window size is unknown.

The practical consequence is simple: the description is routing code. SKILL.md is execution code. Treat both with the same care you would give a function signature and its implementation.

A complete skill can look like this:

release-check/
├── SKILL.md
├── references/
│   └── release-policy.md
├── scripts/
│   └── verify.sh
└── agents/
    └── openai.yaml

Only SKILL.md is required. Start there. Add a script when the check needs deterministic behavior, a reference when the instructions would otherwise become a wall of text, and openai.yaml when the skill needs presentation metadata or a declared tool dependency.

Build the smallest useful SKILL.md

The minimum file has YAML frontmatter with name and description, followed by direct instructions. The description should say when the skill applies and, just as importantly, when it does not.

Here is a complete release-check skill:

---
name: release-check
description: Verify a local web release before commit or deployment. Use for release readiness, preflight checks, or "ready to ship" requests. Do not deploy, publish, commit, or push.
---

# Release check

1. Read the repository release instructions and current git status.
2. Identify the exact files in scope. Preserve unrelated changes.
3. Run the smallest build and test commands that prove the change.
4. Check links, metadata, and generated artifacts used by the changed pages.
5. Report blockers separately from non-blocking findings.

## Completion

Return:

- verdict: ready or not ready;
- verification commands and results;
- changed files;
- anything still requiring approval.

Never commit, push, deploy, or contact anyone.

This file is intentionally boring. It names the inputs, the sequence, the output, and the authority boundary. It does not explain what a release is or repeat generic software advice. Codex can already inspect the repository. The skill exists to make the method consistent.

The line Do not deploy, publish, commit, or push belongs in the description as well as the body. The description is visible during selection, so it prevents the skill from being chosen under the wrong authority before the full file is loaded.

The description decides whether the skill works

Most skill failures are routing failures. A description that is too broad fires on unrelated work; one that lists only the skill's name never fires on the phrases people actually use.

Compare these two descriptions:

description: Helps with releases.
description: Verify a local web release before commit or deployment. Use for release readiness, preflight checks, or "ready to ship" requests. Do not deploy, publish, commit, or push.

The first tells Codex almost nothing. The second carries three kinds of information:

  • The job: verify a local web release.
  • Trigger language: release readiness, preflight, ready to ship.
  • The boundary: verification only, no outward action.

I front-load the job because Codex may shorten descriptions when many skills are installed. Trigger phrases come next. Exclusions come last, unless the exclusion is safety-critical, in which case it belongs in the first sentence.

Do not stuff the description with every possible synonym. A skill should own one recognizable job. If it needs a paragraph to distinguish itself from neighboring skills, the split between those skills is probably wrong.

Put knowledge in references and behavior in scripts

Keep SKILL.md focused on decisions and sequence. Put long policies and examples in references/, and use scripts only when the result must be deterministic.

For the release skill, references/release-policy.md might contain environment names, required checks, or a schema checklist. Codex reads it when the skill says it is needed. That keeps the core instructions short without throwing away detail.

A script is justified for checks such as:

#!/usr/bin/env bash
set -euo pipefail

npm test
npm run build
python3 scripts/check_internal_links.py

The script removes interpretation from a mechanical gate. It should not decide whether a production deploy is authorized, whether a failing test is acceptable, or whether unrelated dirty files can be discarded. Those are judgment and authority questions. Keep them visible in the instructions and the final report.

This is the same separation I use in production agents: code retrieves facts and enforces hard boundaries; the model handles the parts that need interpretation. Moving a deterministic check into prose makes it less reliable. Moving a judgment call into a shell script hides the decision.

Test positive and negative triggers

A skill is not finished when it runs once. Test that it activates for the right requests, stays inactive for neighboring tasks, and produces the promised evidence.

For release-check, I would run four tests:

  1. "Check whether this branch is ready to ship." The skill should activate.
  2. "Run a release preflight but do not commit or deploy." It should activate and preserve the authority boundary.
  3. "Explain semantic versioning." It should not activate.
  4. "Deploy this to production." The skill may help with preflight, but it must not treat the skill itself as deployment approval.

Then break one check on purpose. A release skill that reports "ready" only when everything already passes has not been tested. The failing path proves whether it returns a useful blocker or papers over the result.

The final test is context. Install several neighboring skills and try the same prompts again. Selection that works in an empty profile can become ambiguous when release, deployment, QA, and security skills all claim the word "ship."

Use a skill locally and a plugin for distribution

Use a standalone skill while the workflow is local, changing, or specific to one repository. Package it as a plugin when other people need to install it or when it ships with connectors and shared tools.

Codex discovers repository skills under .agents/skills from the current directory up to the repository root. It can also load user, admin, and system skills. This makes a repository skill the right place for rules tied to one codebase.

Plugins are the distribution layer shared by ChatGPT and Codex. A plugin can carry one or more skills and can also include connectors backed by MCP. If your workflow depends on a connected service rather than local files alone, read the MCP server model before turning the skill into a public package.

The practical sequence is:

  1. Prove the workflow as a local skill.
  2. Run it on real tasks until the instructions stop changing every day.
  3. Remove organization-specific paths, secrets, and assumptions.
  4. Package it as a plugin only when installation is the remaining problem.

This differs from the older Claude Code command and skill model, even though both systems use Markdown instructions and supporting files. Copy the workflow idea. Do not assume the discovery paths, metadata, or invocation rules are interchangeable.

The skill should make the agent more predictable

The test for a skill is not whether Codex can read it. The test is whether a recurring job now produces a more consistent, inspectable result with less prompting.

The best skills in my setup are narrow. They name the evidence required before success, they keep dangerous actions behind explicit approval, and they leave changing project facts in the repository rather than freezing them into a global prompt.

That is why I moved this part of my workflow into Codex rather than maintaining a library of giant prompts. Skills let the method travel while the task stays grounded in the current workspace. In my Codex vs Claude Code comparison, this reusable workflow layer is one piece of the larger migration. It is not the whole reason, but it is one of the parts that made the change hold.

Frequently asked questions

What are Codex skills?

Codex skills are reusable workflow packages made from a required SKILL.md file and optional scripts, references, assets, and interface metadata. Codex initially sees each skill's name and description, then loads the full instructions when the task matches.

Where does Codex read skills from?

For repositories, Codex scans .agents/skills directories from the current working directory up to the repository root. It can also load skills from user, administrator, and system locations. Repository skills are best for codebase-specific workflows.

What is the difference between a Codex skill and a plugin?

A skill defines a reusable workflow. A plugin is an installable package that can contain skills, connectors, or both. Build and test the workflow as a skill first, then use a plugin when you need distribution or connected services.

Should a Codex skill contain scripts?

Only when part of the workflow needs deterministic execution. Use scripts for repeatable checks or transformations. Keep judgment, authority boundaries, and the definition of completion visible in SKILL.md.

How do I know whether a skill triggers correctly?

Test requests that should activate it, requests that should not, and a deliberately failing workflow. Also test it beside neighboring skills, because overlapping descriptions often appear only after the skill is installed in a real profile.