🎯What you get here
Direct Claude → Codex mapping for each configuration component. Leave knowing where each file lives, which syntax to use (TOML vs JSON), and why they’re separate .codex/ × .agents/.
Detailed content
📜 AGENTS.md — CLAUDE.md’s sibling
Markdown file in the project root that Codex reads at the start of the session and injects into the system prompt. Identical function to CLAUDE.md. People migrating copy CLAUDE.md, rename it to AGENTS.md, and it works in 90% of cases.
Direct mapping
⚠️The 10% that DOESN’T port
- • Backtick-bang inside AGENTS.md → isn’t interpreted; it becomes literal text
- • Descriptions that are too long may be truncated (hidden limit ~8K chars)
- • References to Claude-exclusive tools (Task, plan mode) → ignored
- • Inline hooks/permissions don’t work—they belong to
config.toml
Key concepts
Project system prompt
Global → project → subdir
Becomes text
~1-2KB
📂 Why TWO folders — .codex/ and .agents/
Codex does one intentional separation: what is proprietary (Codex config, agents in TOML) stays in .codex/; what an open spec (Agent Skills) is stays in .agents/. Compatibility with other tools that adopt the spec.
🔧 .codex/ — owner
.codex/
├── config.toml ← settings (TOML)
├── agents/ ← sub-agents (TOML)
│ ├── reviewer.toml
│ └── doc-writer.toml
└── commands/ ← slash commands
└── review.md
Things specific to Codex. No other tool understands this.
🌐 .agents/ — open spec
.agents/
└── skills/ ← Agent Skills spec
└── my-skill/
├── SKILL.md
├── agents/openai.yaml ← sidecar
├── scripts/
└── references/
Shareable. Other tools (Cursor, etc.) that follow the spec can read it too.
🚨The most common path error
You read "Codex skill" and instinctively put it in .codex/skills/. Wrong. Skill lives in .agents/skills/ — always. .codex/ is just proprietary config and sub-agents in TOML.
📊 Full comparison
Key concepts
.codex × .agents
.agents = portable
Different syntax
~/.codex and ~/.agents
⚙️ config.toml — TOML settings
Equivalent of settings.json from Claude, but in TOML. It’s not harder—it’s DIFFERENT. Section syntax uses brackets, arrays use double brackets, and multiline strings use triple quotes.
commented config.toml
# modelo padrão model = "gpt-5-codex" approval_policy = "on-failure" # quando pedir aprovação sandbox_mode = "workspace-write" # nível de sandbox # profiles — perfis nomeados [profiles.safe] sandbox_mode = "read-only" approval_policy = "always" [profiles.danger] sandbox_mode = "danger-full-access" approval_policy = "never" # MCP servers [mcp_servers.github] command = "npx" args = ["-y", "@modelcontextprotocol/server-github"] [mcp_servers.github.env] GITHUB_TOKEN = "${GITHUB_TOKEN}" # model providers [model_providers.openai] base_url = "https://api.openai.com/v1" api_key_env_var = "OPENAI_API_KEY"
TOML syntax in 30 seconds
# comentário chave = "string" numero = 42 booleano = true array = ["a", "b", "c"] [secao] # seção (= objeto) chave = "valor" [secao.sub] # sub-seção outra = "outra" [[lista_de_secoes]] # array de seções nome = "item1" [[lista_de_secoes]] nome = "item2" multiline = """ texto em várias linhas """
Key concepts
Object equivalent
Array of sections
Multiline string
Env interpolation
👤 Sub-agents in TOML — not Markdown
Sub-agents in Codex are .toml files in .codex/agents/. Structure, not prose. You fill in the fields of a struct: name, description, model, tools, e instructions (multiline string with the system prompt).
Example — .codex/agents/code-reviewer.toml
name = "code-reviewer" description = "Reviews code for correctness bugs. Call explicitly with 'use code-reviewer to ...'" model = "gpt-5-codex" tools = ["read", "grep", "glob", "bash"] instructions = """ You are a senior code reviewer focused on correctness. ## Your role - Read the diff carefully - Flag correctness bugs (NOT style — linter handles that) - Check edge cases (null, empty, off-by-one, race conditions) - Note security risks (SQLi, XSS, path traversal, auth bypass) ## Output format A numbered list of findings: 1. **[severity]** file:line — what's wrong, why, suggested fix Be terse. No fluff. """
🔷 Claude Code agent
--- name: code-reviewer description: Use proactively... tools: Read, Grep, Bash --- You are a senior code reviewer. ...
Markdown with frontmatter. Prose flows naturally.
🟣 Codex agent
name = "code-reviewer" description = "Call with 'use code...'" tools = ["read", "grep", "bash"] instructions = """ You are a senior code reviewer. ... """
Structured TOML. Prompt inside a string.
💡Practical conversion
To port a Claude sub-agent to Codex: take the frontmatter and turn it into TOML keys. Take the Markdown body and put it in instructions = """...""". Adjusts the description to mention "call explicitly".
Key concepts
Not Markdown
Multiline string
["read", "bash"]
By agent
🚦 Explicit invocation — the Claude → Codex gotcha
In Codex, sub-agents Are NOT auto-triggered through the description. You need to call it by name in the prompt. This is the difference that most confuses people coming from Claude.
🔷 Claude — auto
User: "revisa essa PR" → Claude lê descriptions → Match: code-reviewer → Dispara sub-agent → Devolve findings
You don’t need to know the agent exists.
🟣 Codex — explicit
User: "revisa essa PR"
→ Codex faz revisão genérica
→ Sub-agent code-reviewer NÃO roda
User: "use code-reviewer para
revisar a PR #123"
→ AGORA dispara o sub-agent.
You need to remember the agent and call it.
🚨Error symptom
"Why isn’t my agent being called? It’s exactly like in Claude!"
→ Because you didn't call it. In Codex, description is only there to REMIND you that the agent exists, not to trigger it. Call it by name.
Design trade-off
Predictable. You always know what will run. No surprise like “Claude decided to call X when I wasn’t expecting it.”
Less ergonomic. You HAVE to remember the agents. If you forget, an agent becomes "dead code."
Key concepts
"use agent X..."
By design
Trade-off
For you, not the LLM
🏖️ Sandbox and approval modes
Codex has configurable sandbox via config.toml. Three increasing levels of power + approval policies that control when to ask for confirmation. More granular and explicit than Claude’s equivalent.
read-only
Read-only. Bash works for ls, cat, grep. No writes, no network. Ideal mode for risk-free analysis.
workspace-write (default)
Writes to the project. Doesn't write outside it. Limited network. Day-to-day mode.
danger-full-access
No restrictions. It can write anywhere, the network is open, and any commands are allowed. Only in a real sandbox (container/VM).
Approval policies
"always" — asks for confirmation on EVERY command"on-failure" — only ask if the first attempt failed (reasonable default)"on-request" — asks only if the model thinks it needs to"never" — never prompts (works with a restrictive sandbox)Key concepts
read / write / full
When to ask
Pre-agreed
By sandbox
🔄 Slash commands in Codex
Codex supports custom slash commands in .codex/commands/ (files .md). Same concept as Claude's — some differences in argument syntax and no backtick-bang.
Example — .codex/commands/review.md
---
description: Revisa o diff atual procurando bugs
---
Revise o diff atual da branch (rode git diff).
Procure:
- Bugs de correção
- Casos não tratados
- Vulnerabilidades comuns
Se passar argumento, foque nesse arquivo.
Retorne lista numerada de findings + severity.
Usage: /review or /review src/api/auth.ts
⚠️No backtick-bang
In Claude, you could write Branch atual: `!git branch --show-current` inside the command, and the result was inserted into the prompt. In Codex, it becomes literal text. Solution: ask the agent to RUN the command (fallback prose) or call a script.
Key concepts
Same convention
minimal description
Fallback prose
Alternative to injection
🎯Module summary
Next module:
3.2 — Skills in Codex and the openai.yaml sidecar (the quirk that causes the most confusion)