π―What you get here
Understand exactly what changes in a skill when porting from Claude to Codex β where it goes, what needs adapting, and how the openai.yaml sidecar solves the MCP deps + branding problem.
Detailed content
π¦ Skill in Codex β .agents/skills/ not .codex/skills/
This is the first thing that causes confusion. People coming from Claude think: ".claude/skills/ in Claude β .codex/skills/ in Codex". Wrong. Skill lives in .agents/skills/.
Why .agents/ and not .codex/
.agents/ is the convention used by the open spec Agent Skills (agentskills.io). Any tool that follows the spec reads from there. Codex simply follows the convention instead of inventing its own path.
Result: your skill in .agents/skills/ works in Codex today, and will work in Cursor/Gemini/any compatible tool tomorrow, without moving the file.
Correct paths
~/.agents/skills/<nome>/ β global (suas skills) ./.agents/skills/<nome>/ β projeto (skills do repo) # NΓO existe: .codex/skills/ β Codex nΓ£o enxerga .codex/agents/skills/ β idem
β οΈError symptom
"I added the skill, but $minha-skill doesnβt trigger." β Check the PATH first. Itβs probably in .codex/skills/. Move to .agents/skills/, refresh Codex and it works again.
Key concepts
Required path
agentskills.io
Other tools read
Plugins β reload
π SKILL.md β almost identical to Claudeβs
The SKILL.md file itself is practically the same. Thatβs why the spec works: YAML frontmatter with name e description, Markdown body. These are the 4 things that always match.
SKILL.md in Codex
--- name: revisar-pr description: Use when the user asks to review a PR or diff. --- # Revisar PR ## Passo a passo 1. Identifica a PR 2. LΓͺ diff completo 3. Verifica bugs/edge cases/security 4. Retorna findings categorizados
β What ALWAYS works
- β’ Frontmatter
name+description - β’ Body in standard markdown
- β’ Folders
scripts/,references/,assets/ - β’ Relative references (
./references/x.md) - β’ Headings, lists, code blocks
β What it does NOT port
- β’
allowed-toolsin frontmatter (ignored) - β’
disable-model-invocation(ignored) - β’ Backtick-bang
`!cmd`(becomes text) - β’ Description > 8KB (silently truncated)
- β’
model: opusin frontmatter (not respected)
π‘The 4 portable pillars
The Agent Skills spec defines exactly 4 things in common: file name (SKILL.md), the name and description fields, Markdown body, folder convention. Keep your skill aligned with these 4 pillars and it will move to the other runtime without friction.
Key concepts
Common spec
No custom extension
scripts/refs/assets
Which become sidecars
π The agents/openai.yaml sidecar
This is where the detail that makes Codex most distinctive lives: everything that is runtime-specific (branding for the UI, MCP server dependencies, behavior flags) goes in a separate file β agents/openai.yaml inside the skill folder.
Complete structure with sidecar
.agents/skills/minha-skill/ βββ SKILL.md β obrigatΓ³rio (spec) βββ agents/ β βββ openai.yaml β SIDECAR do Codex βββ scripts/ βββ references/ βββ assets/
openai.yaml example
# Branding pra UI do Codex branding: display_name: "Revisar PR" icon: "π" category: "code-review" # MCP servers requeridos pela skill mcp_servers: - name: github command: npx args: ["-y", "@modelcontextprotocol/server-github"] env: GITHUB_TOKEN: "${GITHUB_TOKEN}" # Flags de comportamento hidden: false require_confirmation: true
Branding
Display name, icon, category. It appears in the UI. Without these, it looks generic.
MCP deps
Skill declares the MCPs it needs. Installation is turnkey.
Flags
Hidden, require_confirmation, etc. Behavior per skill.
Itβs optional
Without openai.yaml the skill works. You only lose refinements: no icon in the UI, generic branding, and MCP dependencies must be installed manually outside the skill. With a sidecar, the experience is polished.
Key concepts
Separate metadata
Skill runs without
Declares a dependency
Icon, name
π The hidden description limit (~8K)
Codex has a undocumented limit of about 8,000 characters for the description when indexed in the catalog. Above that, the description is truncated β and your skill loses the triggers at the end.
π¨The dangerous scenario
- You create a Claude skill with a long description (15KB)βit works well there
- Direct entry point to Codex
- Codex truncates at ~8K. The triggers at the end disappear.
- Skill seems to work (it still triggers on some prompts), but misses some cases
- You never find out because thereβs no errorβitβs silent
Front-loading technique
Put the most important triggers and examples in the first 1β2KB. The rest can come later (and can be cut without a fuss).
// CERTO β triggers no topo description: | Use when reviewing PRs. Triggers: "revisa PR", "review pull request", "code review". Examples: "revisa PR #123", "review da branch atual". More context (pode ser truncado): ... // ERRADO β triggers no fim description: | This skill specializes in deep technical code review with focus on correctness, security, and edge cases. It analyzes pull requests by reading the full diff and ... [muito mais texto] ... Triggers: "revisa PR" β truncado, nunca alcanΓ§a
π¦Polyskill anticipates
The polyskill Codex adapter automatically front-loads the content: it takes the triggers from the portable description and moves them to the top when generating output for Codex. You don't have to think about it.
Key concepts
Undocumented
No errors
Triggers at the top
Resolve at build time
π« No native backtick-bang β how to work around it
Codex doesnβt interpret `!cmd` (backtick-bang) as shell execution before the prompt. A skill that depends on this to inject dynamic context (git status, current log, branch) needs adaptation.
π· Claude (original)
Branch: `!git branch --show-current` Γltimo commit: `!git log -1 --oneline` Com base no acima, sugira...
The command RUNS. The result is already in the prompt.
π£ Codex (fallback prose)
Before you start, run: - `git branch --show-current` - `git log -1 --oneline` Based on the results, suggest...
The agent RUNS the commands when it reads the skill.
Alternative: delegated script
If you just want idempotent, structured output, put the logic in a script:
# scripts/context.sh #!/bin/bash echo "Branch: $(git branch --show-current)" echo "Commit: $(git log -1 --oneline)" # SKILL.md Antes de comeΓ§ar, rode `./scripts/context.sh` e leia o output.
π¦Polyskill when porting
When you import a Claude skill with backtick-bang, the polyskill Codex adapter automatically rewrites as fallback prose. Itβs not magicβitβs simple and it works. You trade a little elegance for portability.
Key concepts
Codex doesnβt have
"Run X and analyze"
Logic in sh
Automatic on import
π MCP servers in Codex
Same MCP spec. Same server runs. Only the declaration changes β TOML instead of JSON, inside the config.toml or in the sidecar openai.yaml of the skill (when MCP is a specific dependency).
π· Claude (.mcp.json)
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@mcp/github"],
"env": {
"TOKEN": "$GH_TOKEN"
}
}
}
}
π£ Codex (config.toml)
[mcp_servers.github]
command = "npx"
args = ["-y", "@mcp/github"]
[mcp_servers.github.env]
TOKEN = "${GH_TOKEN}"
Where to declare β config.toml Γ sidecar
Key concepts
Shared server
Only the syntax changes
config.toml Γ sidecar
Sidecar installs MCP
$ Skill invocation $skill β not /skill
Codex uses the dollar sign for explicit skill invocation, leaving slash for built-in commands. $nome-skill instead of /nome-skill. A small detail that catches you on day one.
π· Claude Code
/review β skill OU slash command /plan β built-in /output-style x β built-in
Everything is a slash command. No separation.
π£ Codex
$review β skill /help β built-in (Codex) /model β built-in (Codex)
Separation: $ for skills, / for built-ins.
π‘Autocomplete helps
Type $ and Codex suggests the available skills. Even if you forget itβs a dollar sign, not a slash, autocomplete quickly corrects it.
Key concepts
Invocation sigil
Reserved
Skill Name
Lists skills
π―Module summary
Next track:
T4 β Converting your project (prompt template + checklist + 5 pitfalls)