Claude skills vs Codex skills: paths, $ vs /, openai.yaml, and precedence

Claude Code and OpenAI Codex both run Agent Skills from the same SKILL.md, but they load from different directories, invoke with different syntax, and put agent-specific settings in different places. Every difference, with examples.

Contents

Claude Code and OpenAI Codex agree on what a skill is. Both implement the Agent Skills specification: a folder, a SKILL.md, name and description in YAML, instructions in Markdown, optional scripts/ and references/ and assets/. A skill published for one installs into the other with a single command, and the body does not change.

Where they disagree is in the plumbing around the file. Codex walks a different set of directories with a documented precedence order, uses $skill-name where Claude uses /skill-name, keeps its vendor-specific settings in a separate agents/openai.yaml file rather than in the frontmatter, and exposes a config file for disabling skills. Claude Code puts a dozen optional fields directly in the frontmatter, merges slash commands into skills, and lets a skill fork into a subagent. This article lays out every difference so you can write once and understand what each tool will do with the result.

Directory scanning and precedence

Codex loads skills from four scopes and documents their precedence:

OrderScopePath
1Repository.agents/skills in the current directory, any parent, or the repo root
2User~/.agents/skills
3Admin/etc/codex/skills
4SystemSkills bundled with Codex

Codex follows symlinked skill folders, so a shared skills repository can be linked into ~/.agents/skills without copying.

Claude Code has its own set:

ScopePathNotes
Enterprise.claude/skills/ inside the managed settings directoryAdmin-controlled
Personal~/.claude/skills/<name>/SKILL.mdBeats a project skill of the same name
Project.claude/skills/<name>/SKILL.mdLoads from the start directory and every parent up to the repo root
Nested<subdir>/.claude/skills/Loads once Claude reads or edits a file in that subtree
Plugin<plugin>/skills/<name>/SKILL.mdExposed as /plugin-name:skill-name
Synced~/.claude/skills/synced/Skills enabled on claude.ai, downloaded when CLAUDE_CODE_SYNC_SKILLS is set

The two tools do not read each other’s directories. A repo that wants to serve both today either commits skills twice or uses a CLI that installs to both targets:

npm i -g skillmds
skillmd add anthropic/skill-creator                 # every agent detected on the machine
skillmd add anthropic/skill-creator -a codex        # Codex only
skillmd add anthropic/skill-creator -a claude-code  # Claude Code only

The Codex and Claude Code guides on SkillMD carry the exact paths.

Invocation syntax

ActionClaude CodeCodexChatGPT
AutomaticBy descriptionBy descriptionBy description
Explicit/skill-name$skill-name@skill-name
Pass arguments/skill-name arg1 arg2, read as $ARGUMENTS in the bodyFree text after the mentionFree text after the mention
Stack severalUp to six inline skills in one messageOne mention per skillOne mention per skill
Manual-onlydisable-model-invocation: true in frontmatterpolicy.allow_implicit_invocation: false in agents/openai.yamlSame openai.yaml
Agent-only (hidden from you)user-invocable: falseNot availableNot available

The $ versus / distinction is more than cosmetic. In Claude Code, skills and slash commands are the same thing: a .claude/commands/deploy.md and a .claude/skills/deploy/SKILL.md both produce /deploy, and the skill wins if both exist. Codex reserves / for its own built-in commands and gives skills the $ sigil so the two namespaces never collide.

Where vendor-specific settings go

This is the deepest design difference between the two implementations.

Claude Code puts extensions in the frontmatter. Beyond the spec fields, Claude Code reads:

FieldPurpose
argument-hintAutocomplete hint, e.g. [issue-number]
disable-model-invocationManual-only
user-invocableSet false to hide from the / menu
allowed-toolsTools pre-approved for the invoking turn (clears on your next message)
disallowed-toolsTools removed while the skill is active
modelModel override for the turn
context: forkRun the skill as a subagent
agentWhich subagent type to fork into
backgroundWhether a forked skill runs in the background (default) or blocks
hooksHooks registered when the skill is invoked

Claude also substitutes ${CLAUDE_SKILL_DIR} and ${CLAUDE_PROJECT_DIR} in both the body and in allowed-tools Bash rules, so a skill can pre-approve exactly the bundled script it tells the agent to run.

Codex puts extensions in a sidecar file. The SKILL.md frontmatter stays spec-clean, and an optional agents/openai.yaml inside the skill folder carries the rest:

interface:
  display_name: "Release notes"
  icon_small: "assets/icon-16.png"
  icon_large: "assets/icon-64.png"
  brand_color: "#0A84FF"
policy:
  allow_implicit_invocation: false   # default true
dependencies:
  tools:
    - type: mcp
      value: github

The interface block controls how the skill appears in the ChatGPT and Codex UI. policy is the Codex equivalent of disable-model-invocation. dependencies.tools declares the MCP servers the skill expects, so the agent can tell you what is missing instead of failing mid-task.

The consequence for authors: a skill that uses Claude’s frontmatter extensions still loads in Codex (unknown keys are ignored), but the behavior those keys encode does not carry over. A context: fork skill runs inline in Codex. A disable-model-invocation: true skill is auto-invocable in Codex unless you also add the openai.yaml policy. If manual-only matters, set it in both places.

Context budget

Codex publishes its number: the initial skill listing is limited to at most 2% of the model’s context window, or 8,000 characters when the window size is unknown. If you install more skills than fit, some descriptions will not be shown to the model, and those skills will not trigger automatically.

Claude Code does not publish a fixed cap, but the same principle applies through progressive disclosure: only name and description load at startup. Both tools reward short, specific descriptions. Both recommend keeping the body under 500 lines.

Enabling, disabling, and removing

TaskClaude CodeCodex
Stop automatic use, keep manualdisable-model-invocation: trueallow_implicit_invocation: false in openai.yaml
Disable without editing the skillskillOverrides in settings ("user-invocable-only")[[skills.config]] with enabled = false in ~/.codex/config.toml
RemoveDelete the folder; live change detection drops it from /skills in the current sessionDelete the folder
Restrict which skills the model may callPermission deny rules on the Skill toolConfig entries per skill

Claude Code watches its skill directories and applies edits within the session. Codex rescans on startup.

Distribution

Claude Code distributes skills through plugins. A skill folder with a .claude-plugin/plugin.json loads as a plugin and can bundle agents, hooks, and MCP servers alongside skills. Skills enabled on claude.ai sync into Claude Code sessions, including Cowork and cloud sessions that never see your laptop’s ~/.claude/skills/.

Codex ships a $skill-installer skill for curated skills and packages skills as plugins for broader sharing. The openai/skills repository holds first-party examples, including the skill-creator skill Codex uses to write new skills.

Both are compatible with third-party registries. SkillMD lists 25,000+ skills with a safety review on each, tags which agents each author tested against, and installs to either tool with one command. Claude Code users can also add the hosted MCP server and install by asking:

claude mcp add skillmds -- npx -y skillmds

Writing one skill for both

A checklist that produces a skill both tools run identically:

  1. Use only spec fields in the frontmatter: name, description, license, and optionally compatibility and metadata.
  2. Name the folder the same as name, lowercase with hyphens, under 64 characters.
  3. If the skill must be manual-only, add disable-model-invocation: true to the frontmatter and policy.allow_implicit_invocation: false in agents/openai.yaml.
  4. If the skill needs an MCP server, say so in the body for Claude and declare it under dependencies.tools for Codex.
  5. Reference bundled scripts by relative path from the skill root. Avoid ${CLAUDE_SKILL_DIR} in the body; it is Claude-only.
  6. Keep the body under 500 lines and move long material to references/.
  7. Run skillmd lint before committing.

The full multi-agent field table is in the compatibility matrix.

Summary table

DimensionClaude CodeOpenAI Codex
SpecAgent Skills SKILL.mdAgent Skills SKILL.md
Project dir.claude/skills (plus parents, nested, plugins).agents/skills (plus parents to repo root)
Personal dir~/.claude/skills~/.agents/skills
Admin dirManaged settings directory/etc/codex/skills
PrecedencePersonal > project > bundled; skill > command; namespaced pluginsRepo > user > admin > system
Explicit invoke/name, with $ARGUMENTS$name (ChatGPT: @name)
Vendor settingsFrontmatter fieldsagents/openai.yaml sidecar
Manual-onlydisable-model-invocationpolicy.allow_implicit_invocation: false
Subagent executioncontext: forkNot available
Tool pre-approvalallowed-tools (per turn)Not available
MCP dependency declarationIn the bodydependencies.tools
Disable via configskillOverrides[[skills.config]] enabled = false
Context cap for listingsNot published2% of window or 8,000 chars
Live reloadYesRescan on start
Cloud syncclaude.ai-enabled skillsRepo skills

Further reading

Frequently asked questions

Do Claude Code skills work in OpenAI Codex?

Yes. Both implement the Agent Skills specification. A skill that uses name, description, and a Markdown body loads unchanged in Codex once it is in a directory Codex scans, such as .agents/skills. Claude-only frontmatter fields are ignored.

Where does Codex look for skills?

In order of precedence: .agents/skills in the working directory, its parents, or the repo root; ~/.agents/skills for personal skills; /etc/codex/skills for admin-installed skills; then built-in system skills.

How do I invoke a skill explicitly in Codex vs Claude Code?

Codex uses a dollar sign: $skill-name. ChatGPT uses an at sign: @skill-name. Claude Code uses a slash: /skill-name, and accepts arguments that the skill body reads as $ARGUMENTS.

What is agents/openai.yaml in a Codex skill?

An optional file inside the skill folder that holds Codex- and ChatGPT-specific settings: a display name, icons, and brand color for the UI, a policy that can disable implicit invocation, and declared MCP tool dependencies. It keeps vendor settings out of the shared SKILL.md frontmatter.

How do I turn off a skill in Codex without deleting it?

Add a [[skills.config]] entry with enabled = false to ~/.codex/config.toml. In Claude Code, set disable-model-invocation: true in the frontmatter to make it manual-only, or delete the skill folder to remove it.