Skip to content
Zarif Automates

Skills and Reusable Instructions for Coding Agents

ZarifZarif
|Published

A project instruction file loads every session. A skill loads when it's needed. That one difference decides where most of your reusable instructions should go.

Claude Code's skills docs put it plainly: unlike CLAUDE.md, only a skill's description loads at the start, and the full content loads when the skill is invoked (Claude Code skills docs, read September 26, 2026). Codex and Cursor load skills the same way. So a ten-step release checklist costs almost nothing until someone asks for a release.

This page covers what a skill is in each tool, a worked skill you can drop into a repo, how to keep it portable, and a rule for deciding between a skill and a line in the instruction file.

What a skill is

A skill is a folder with a SKILL.md file in it. The file has YAML frontmatter with at least a name and a description, then Markdown instructions. The folder can also hold scripts, templates, and reference files the instructions point to.

The format comes from the Agent Skills open standard, which is why the same folder works in more than one tool. Where each tool looks, as of September 2026:

ToolProject skillsPersonal skillsInvoke by hand
Claude Code.claude/skills/<name>/SKILL.md~/.claude/skills//name
Codex.agents/skills/$HOME/.agents/skills/$name in the CLI
Cursor.agents/skills/ or .cursor/skills/~/.agents/skills/ or ~/.cursor/skills// then search

Sources: Claude Code skills, Codex skills, Cursor skills.

All three also invoke a skill on their own when your request matches its description. That makes the description the most important line in the file. It is both the trigger and the only part the agent sees until the skill runs.

Slash commands became skills

If you wrote custom slash commands in Claude Code as .claude/commands/deploy.md, they still work. The skills docs describe that format as the older one: a command file and a skill at .claude/skills/deploy/SKILL.md both create /deploy. Skills add a folder for supporting files, automatic invocation from the description, and extra frontmatter. For anything new, write a skill.

Worked example: a pre-merge check skill

The target: type /pre-merge (or $pre-merge in Codex) and the agent summarizes the uncommitted diff, runs the project's checks, and reports what it couldn't verify. It never commits.

Create .claude/skills/pre-merge/SKILL.md:

---
name: pre-merge
description: Checks the current uncommitted change before it is committed or merged. Summarizes the diff, runs lint and tests, and lists anything unverified. Use when the user asks if a change is ready, wants a pre-merge check, or asks what changed.
disable-model-invocation: true
allowed-tools: Bash(git diff *) Bash(git status *) Bash(npm run lint) Bash(npm test)
---

## Current change

!`git status --short`

!`git diff HEAD --stat`

## Steps

1. Read the full diff with git diff HEAD. Summarize it in two or three bullets.
2. Flag any file that looks outside the task the user described.
3. Run npm run lint, then npm test. Quote the last lines of any failure.
4. Check that every changed source file has a matching test change, or say
   why one isn't needed.
5. Report in this order: summary, check results, scope concerns, anything
   you could not verify. Do not commit, push, or edit files.

What each part does, per the Claude Code docs:

  • description says what the skill does and when to use it. Claude reads this to decide whether the skill fits a request.
  • disable-model-invocation: true means only you can start it. The docs suggest this for skills with side effects or ones you want to time yourself, such as deploy or commit. Leave it out if you want the agent to reach for the skill on its own.
  • allowed-tools pre-approves those commands while the skill runs, so you aren't prompted for each git diff. The grant clears after your next message.
  • The ! lines are dynamic context. Claude Code runs each command when the skill is invoked and replaces the line with its output, so the agent starts with the current status and file list already in view. If one of these commands fails, the whole invocation aborts.

Invoke it with /pre-merge. You can pass arguments too: text after the command lands in $ARGUMENTS inside the skill, so /pre-merge signup form validation could let step 2 compare the diff against that description if you reference $ARGUMENTS there.

Making the same skill work in Codex and Cursor

Copy the folder to .agents/skills/pre-merge/ and Codex and Cursor will find it. What carries over is the part the standard defines.

The Claude Code docs list the standard fields as name, description, license, compatibility, metadata, and allowed-tools. Fields such as disable-model-invocation, context, arguments, and paths are Claude Code additions, and the docs recommend sticking to the standard fields when you package a skill for other places. Cursor's docs list disable-model-invocation and paths among its own optional fields too, so check each tool's page for the extras it honors.

The dynamic-context ! lines are a Claude Code feature. In another tool they are just text. The portable version moves them into the steps:

## Steps

1. Run git status --short and git diff HEAD --stat to see the change.
2. Read the full diff with git diff HEAD. Summarize it in two or three bullets.
...

That costs one extra tool call and works everywhere. A practical setup for a mixed team is to keep the portable skill in .agents/skills/ and, if you want the Claude Code extras, a thin variant in .claude/skills/ with the same name. The worktrees docs note that Claude Code reads .claude/skills from the main checkout when a worktree lacks its own, so gitignored skills still load in worktree sessions.

Two more Claude Code options worth knowing

Run a skill in a subagent. Add context: fork and the skill runs in an isolated subagent with the skill body as its task. Pair it with agent: Explore for a read-only research skill. The skill's work stays out of your main context and only the result comes back. See the subagents page in this series for when that isolation is worth it.

Control who can invoke what. Permission rules accept Skill(name), so you can allow Skill(pre-merge) and deny Skill(deploy *). user-invocable: false does the reverse of disable-model-invocation: only Claude can load the skill, which suits background knowledge you never call by name.

Codex custom instructions: AGENTS.md

Codex's always-on instructions live in AGENTS.md. Per the Codex AGENTS.md guide, it reads a global file from ~/.codex, then walks from the project root down to your working directory, checking each folder for AGENTS.override.md, then AGENTS.md. It concatenates what it finds from the root down, so files nearer your working directory come later and win. It stops adding files once the total reaches project_doc_max_bytes, 32 KiB by default.

That cap is a useful forcing function. If your AGENTS.md is approaching it, some of it is a procedure that should be a skill. The CLAUDE.md and AGENTS.md guide in this series covers loading rules for both files in full.

When a skill beats a line in CLAUDE.md

The Claude Code docs frame it as facts versus procedures: static conventions belong in CLAUDE.md, multi-step procedures and large reference material belong in skills. In practice, move something into a skill when any of these is true:

  • It has steps. "Run lint, then tests, then check the changelog" is a procedure. The agent needs it only when doing that task.
  • It's long. Reference material such as a style guide, an API schema, or a voice guide costs context on every turn in the instruction file and costs nothing until needed in a skill.
  • It runs sometimes, not always. Release steps, a migration recipe, the checklist for a new blog post.
  • You want to trigger it by name. A skill gives you /release. A paragraph in CLAUDE.md doesn't.
  • It needs tools pre-approved. allowed-tools scopes permissions to the one task.

Keep it in the instruction file when it should shape every change: the package manager, the test command, naming conventions, "never commit to main". A one-line pointer in CLAUDE.md to a skill is fine and often helpful, for example "Before any article edit, load the content-voice skill."

And if the rule must hold whatever the model decides, neither place is enough. That's a hook.

For how this site's own instruction file handles what done means, see Your CLAUDE.md should explain what done means.

Previous in the series: MCP servers for coding agents. Next: Headless and CI use of coding agents.

Zarif

Zarif

Zarif builds AI agents and automation workflows and writes about what holds up in production: useful sources, the roles the AI era is creating, and agent workflows you can inspect end to end.