Codex Migration Guide skill for Codex
Bring your agent setup over without losing rules. Codex inventories another agent's setup, runs /import where it applies, and maps the rest by hand: instruction files to AGENTS.md, slash commands and skills to .agents/skills, MCP JSON to config.toml, allow and deny lists to sandbox settings and execpolicy rules, hooks and subagents to their Codex formats. Every piece is verified by behaviour, not file presence.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- codex-migration-guide Installs to ~/.agents/skills/codex-migration-guide/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install codex-migration-guide The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project codex-migration-guide Installs to .agents/skills/codex-migration-guide/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/codex-migration-guide.zipunzip -o codex-migration-guide.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) codex-migration-guide PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $codex-migration-guide, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Ports another coding agent's setup to Codex, mapping CLAUDE.md, .cursorrules, .cursor/rules, copilot-instructions and similar files to AGENTS.md, slash commands and skills to .agents/skills, MCP JSON to config.toml, permission settings to sandbox, approvals and rules, hooks and subagents to their Codex equivalents, using /import where it fits and verifying each piece. Use when a team moves from Claude Code, Cursor, Copilot, Windsurf or Gemini CLI to Codex, wants both tools to share one instruction file, or asks what /import did and did not bring over.
Use it when
- A team switches from another coding agent to Codex
- Two agents must share one instruction file during a transition
- Custom commands, MCP servers or hooks need porting
- Checking what the /import command migrated
Use something else when
- You are writing AGENTS.md from scratch with no prior setup: use agents-md-authoring
- Rolling Codex out across many teams with policy: use codex-team-rollout
How to check the result
Codex lists the expected instruction files in order, /skills and /mcp show every migrated command and server, execpolicy check blocks the same commands as before, and one real task matches the old tool's result.
The mistake it prevents
Copying command templates that relied on argument or shell interpolation, which Codex skills do not execute, so the migrated command silently does less.
A migration is done when Codex follows the same project rules as the old tool, every repeated workflow is invocable, MCP servers connect, permissions are at least as tight as before, and nothing was silently dropped. Copying files is the easy half; verifying behaviour is the job.
Inventory first
Run from the repository root and from your home directory, and list what exists:
ls -a | grep -Ei 'claude|cursor|windsurf|gemini|copilot|agents|mcp'
find . -maxdepth 4 \( -name 'CLAUDE*.md' -o -name 'AGENTS*.md' -o -name 'GEMINI.md' \
-o -name '.cursorrules' -o -name '.windsurfrules' -o -name '*.mdc' \
-o -name 'copilot-instructions.md' -o -name '.mcp.json' -o -name 'mcp.json' \) \
-not -path '*/node_modules/*' 2>/dev/null
ls ~/.claude ~/.cursor 2>/dev/null
Record each item with its scope (user or project) in a migration table before changing anything. Importing never modifies or deletes the source tool’s setup.
Option A: built-in import
Codex CLI: start a local interactive session and run /import, then choose Claude Code
or Cursor and select setup, project files and recent chats. The ChatGPT desktop app has
the same flow under Settings > Import (it also lists Claude Cowork).
| Imported item | Lands in |
|---|---|
| Instruction files | AGENTS.md |
settings.json | config.toml |
| Skills | Codex skills |
| Slash commands | Codex skills |
| MCP server configuration | Codex MCP configuration |
| Hooks | Codex hooks |
| Subagents | Codex subagents |
| Plugins | Codex plugins |
| Project memories (Claude Code) | Codex memories |
| Recent chats | Up to 50 chats from the last 30 days (CLI) |
/import is unavailable while a task is running, in remote sessions and while connected
to the local app-server daemon. After importing, still do the review steps below: the
docs call out tool restrictions in skills and agents, MCP auth, headers and env vars,
hook behaviour, and command templates that relied on arguments, shell interpolation or
file placeholders as needing manual checks.
Option B: manual mapping
Use this when importing is unavailable, for tools /import does not cover, or to keep
the migration reviewable in one PR. Full per-tool details, including frontmatter and
syntax differences, are in references/mapping.md; read it when
converting a specific file type.
| Source | Codex target |
|---|---|
CLAUDE.md, GEMINI.md, .cursorrules, .windsurfrules, .github/copilot-instructions.md | AGENTS.md at the same level |
| Nested instruction files in subdirectories | Nested AGENTS.md (closest file wins, appended last) |
| Personal, git-ignored instruction file | ~/.codex/AGENTS.md, or a git-ignored AGENTS.override.md (it replaces that directory’s AGENTS.md, so include the shared content) |
User-level instructions (~/.claude/CLAUDE.md and similar) | ~/.codex/AGENTS.md |
| Always-applied editor rules | Root or package AGENTS.md |
| Glob- or description-scoped editor rules | Nested AGENTS.md in matching directories, or a skill |
| Custom slash commands | Skills, explicit-only (allow_implicit_invocation: false) |
Existing SKILL.md folders | .agents/skills/<name>/ (same open skill format) |
MCP JSON (.mcp.json, .cursor/mcp.json) | [mcp_servers.<name>] in .codex/config.toml or codex mcp add |
| Allow/deny permission lists | sandbox_mode, approval_policy, .codex/rules/*.rules, permission-profile deny |
| Lifecycle hooks | .codex/hooks.json or inline [hooks] |
| Subagent definitions | .codex/agents/<name>.toml with name, description, developer_instructions |
Keeping two tools on one instruction file
During a transition, make AGENTS.md the source of truth and point the other tool at
it, or point Codex at the old file:
# ~/.codex/config.toml (bridge only; remove after migration)
project_doc_fallback_filenames = ["CLAUDE.md"]
Fallback names are read only when a directory has no AGENTS.md. A symlink
(ln -s AGENTS.md CLAUDE.md) also works if every tool on the team follows symlinks;
test it on Windows checkouts before relying on it.
Workflow
- [ ] 1. Inventory and migration table
- [ ] 2. Instructions -> AGENTS.md (dedupe, trim, keep commands exact)
- [ ] 3. Commands and skills -> .agents/skills
- [ ] 4. MCP servers -> config.toml, then codex mcp list
- [ ] 5. Permissions -> sandbox, approvals, rules, profiles
- [ ] 6. Hooks and subagents
- [ ] 7. Verify behaviour, not just files
- [ ] 8. Decide what to retire and when
Step 2 rules: remove tool-specific phrasing (“use the Read tool”, “in plan mode”),
keep build, test and lint commands verbatim, and stay under project_doc_max_bytes
(32 KiB by default for the whole chain). Codex has no include directive for
instruction files documented; inline what must always apply and link the rest as
“read docs/x.md before changing y”.
Step 5: map “always allowed” shell commands to prefix_rule(..., decision = "allow")
only if they must run outside the sandbox; commands that work inside the
workspace-write sandbox need no rule. Map deny lists to forbidden rules plus
permission-profile deny paths for secret files.
Verification
codex --ask-for-approval never "List the instruction files you loaded, in order."
codex -C services/payments --ask-for-approval never "Which instruction files apply here?"
codex mcp list
codex execpolicy check --pretty --rules .codex/rules/default.rules -- git push --force
Then, in an interactive session: /skills shows each migrated command; invoke two of
them with real arguments; /mcp lists the expected tools; /debug-config shows the
project layer loaded (the project must be trusted). Finally run one real task that the
old tool handled well and compare the diff.
Gotchas
- Project
.codex/config, hooks and rules load only for trusted projects; an untrusted checkout silently ignores them. - Some source tools allow per-command tool restrictions inside commands or skills; Codex skills do not enforce those. Express hard limits as rules or sandbox settings.
- Command templates using shell-interpolation or file-inclusion syntax do not execute
in skills; rewrite them as explicit steps (“run
git diff --statand use its output”). - Codex hook matchers accept
Bashfor shell commands andEdit/Writeas aliases forapply_patch, andmcp__<server>__<tool>for MCP tools; matchers naming other tools (file reads, searches, web fetches) may never fire. Hosted tools such as web search do not run hooks. Trigger each hook once and confirm it (/hookslists them). - Imported chats are history, not live context; start new work in a fresh session.
- Do not delete the old tool’s files until the team confirms the switch.
Output template
## Migration report
| Source item | Scope | Codex target | Method | Verified |
|---|---|---|---|---|
| CLAUDE.md | repo | AGENTS.md | manual, trimmed 9 KB -> 4 KB | instruction-list test |
| .claude/commands/release.md | repo | .agents/skills/release/ | /import, args rewritten | invoked with v2.4.0 |
| .mcp.json (github, sentry) | repo | .codex/config.toml | codex mcp add | /mcp shows 2 servers |
| settings.json deny rm -rf | user | ~/.codex/rules/default.rules | manual | execpolicy check |
Not migrated: <items and why>. Old files kept until: <date/decision>. What the zip contains
Codex reads bundled files only when a step points to them. Every one is shown here, so you can review it before installing.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "Codex Migration Guide"
short_description: "Bring your agent setup over without losing rules"
default_prompt: "$codex-migration-guide We're moving from Claude Code to Codex, port our CLAUDE.md and commands" references/mapping.md
# Per-tool conversion details
Read the section for the file type you are converting. Source-tool formats change;
when a source file does not match the shape described here, follow what the file
actually contains and note the difference in the migration report.
## Instruction files
### Codex discovery rules (target behaviour)
- Global: `~/.codex/AGENTS.override.md`, else `~/.codex/AGENTS.md` (first non-empty).
- Project: from the project root (git root by default, see `project_root_markers`)
down to the working directory; per directory Codex takes the first of
`AGENTS.override.md`, `AGENTS.md`, then names in `project_doc_fallback_filenames`.
- Files are concatenated root first; closer files come later and win on conflict.
- Total size capped by `project_doc_max_bytes` (32 KiB default).
- Rebuilt at the start of every run or TUI session; restart after editing.
### CLAUDE.md family
| Source | Target | Notes |
|---|---|---|
| `./CLAUDE.md` | `./AGENTS.md` | Move content; drop tool-specific tool names and mode names |
| `./sub/CLAUDE.md` | `./sub/AGENTS.md` | Keep only what differs from the parent |
| `CLAUDE.local.md` (personal, ignored) | `AGENTS.override.md`, git-ignored | An ignored `AGENTS.override.md` is copied into Codex-managed worktrees automatically. Note: an override replaces `AGENTS.md` in that directory rather than adding to it, so copy the shared content in or keep personal notes in `~/.codex/AGENTS.md` instead |
| `~/.claude/CLAUDE.md` | `~/.codex/AGENTS.md` | Personal defaults across repos |
| `@path/to/file` import lines | Inline the essentials; link the rest | No include directive is documented for AGENTS.md |
### Cursor rules
| Source | Target |
|---|---|
| `.cursorrules` (legacy single file) | Root `AGENTS.md` |
| `.cursor/rules/*.mdc` with always-apply set | Root `AGENTS.md` (merge, dedupe) |
| `.mdc` scoped by globs to a directory tree | `AGENTS.md` inside that directory |
| `.mdc` scoped by globs to a file type across the repo (e.g. `**/*.sql`) | A short section in root `AGENTS.md` ("When editing SQL files: ..."), or a skill if long |
| `.mdc` applied when the agent judges it relevant (description-based) | A skill whose `description` carries the same trigger |
| `.mdc` applied only when manually referenced | Explicit-only skill |
Strip the `.mdc` frontmatter; Codex does not read it.
### Other single-file instructions
`.github/copilot-instructions.md`, `.windsurfrules`, `GEMINI.md`, `CONVENTIONS.md`:
merge into `AGENTS.md`, or list them in `project_doc_fallback_filenames` as a temporary
bridge (only read where no `AGENTS.md` exists in that directory).
## Commands and skills
### Slash-command markdown files
Typical source features and their Codex treatment:
| Source feature | Codex skill equivalent |
|---|---|
| File name = command name | Skill folder name = `name:` in frontmatter |
| Frontmatter description | `description:` rewritten as "does X. Use when Y." |
| Argument placeholder (`$ARGUMENTS`, `$1`) | `## Inputs` section; the agent reads values from the message |
| Inline shell execution markers | Explicit step: "Run `<command>` and use its output" |
| File-inclusion markers | Explicit step: "Read `<path>` first" |
| Per-command tool allowlist | Not enforced by skills; use sandbox/rules for hard limits |
| Per-command model override | Not in SKILL.md; mention a recommended model, or use a profile |
Make command-style skills explicit-only:
```yaml
# .agents/skills/<name>/agents/openai.yaml
policy:
allow_implicit_invocation: false
```
### Existing SKILL.md folders
Skills follow the open agent skills format, so most folders copy across:
```bash
mkdir -p .agents/skills && cp -R .claude/skills/<name> .agents/skills/
```
Then: remove frontmatter keys other than `name`, `description` (and `license` or other
keys your team standardizes on), fix any hard-coded paths to the old skills directory
in scripts, and run each script once. Personal skills go to `~/.agents/skills/`.
## MCP servers
JSON (`mcpServers` object) to TOML:
```json
{ "mcpServers": { "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" } },
"docs": { "type": "http", "url": "https://mcp.example.com/mcp" } } }
```
```toml
[mcp_servers.github]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
env_vars = ["GITHUB_TOKEN"] # forward from the environment; don't paste the token
[mcp_servers.docs]
url = "https://mcp.example.com/mcp"
# bearer_token_env_var = "DOCS_TOKEN" # if it uses a bearer token
```
Or: `codex mcp add github --env GITHUB_TOKEN="$GITHUB_TOKEN" -- npx -y @modelcontextprotocol/server-github`
(this writes the literal value into config; prefer `env_vars` for secrets). OAuth
servers: `codex mcp login <name>`. Useful extras: `startup_timeout_sec` (default 10),
`tool_timeout_sec` (default 60), `enabled_tools`, `required = true` for servers a job
cannot run without.
## Permissions
| Source intent | Codex |
|---|---|
| Default ask-before-edit mode | `sandbox_mode = "read-only"`, `approval_policy = "on-request"` |
| Accept edits automatically, ask for risky commands | `sandbox_mode = "workspace-write"`, `approval_policy = "on-request"` |
| Allow specific commands without asking | Inside the sandbox they already run; outside: `prefix_rule(..., decision = "allow")` |
| Deny specific commands | `prefix_rule(..., decision = "forbidden", justification = "...")` |
| Deny reading secret files | Permission profile `"**/*.env" = "deny"` |
| Skip all permission checks | `--sandbox danger-full-access` only inside an isolated container |
Prefix rules match argument prefixes and live in `rules/` next to a config layer
(`~/.codex/rules/`, trusted `<repo>/.codex/rules/`). Test with `codex execpolicy check`.
## Hooks
Codex reads `~/.codex/hooks.json`, `<repo>/.codex/hooks.json` (trusted projects) or
inline `[hooks]` tables. Events include `SessionStart`, `UserPromptSubmit`,
`PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`,
`SubagentStart`, `SubagentStop`, `Stop`. Matchers: `Bash` (shell), `apply_patch` or
`Edit|Write` (file edits), `mcp__server__tool`. New or changed hooks must be trusted
(`/hooks`) before they run. Hook input and output JSON fields differ between tools:
re-test every script against the Codex hooks reference.
## Subagents
Markdown agent definitions become TOML files:
```toml
# .codex/agents/reviewer.toml
name = "reviewer"
description = "PR reviewer focused on correctness, security and missing tests."
model_reasoning_effort = "high"
developer_instructions = """
Review like an owner. Do not edit files. Cite file and line for every finding.
"""
```
Custom agents inherit the parent's sandbox, approvals, provider and MCP servers; those
keys in an agent file are ignored. Per-agent tool lists from the source tool do not
carry over except via `features.shell_tool = false` and similar feature switches.
About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.