Codex reads five things from a repo. AGENTS.md for instructions. .agents/skills/ for skills. .codex/hooks.json for hooks. .codex/agents/ for subagents. .codex/config.toml for MCP servers. The last three load only in a project you trust.
Below: each file, what Codex does with it, and the real version from a generated Next.js repo. Tested on Codex CLI 0.161.
What Codex reads
| File | What it is | When it loads |
|---|---|---|
AGENTS.md, root and nested | Instructions | At start, from the root down to the folder you launch in. 32 KiB per chain |
.agents/skills/<name>/SKILL.md | Skills, run as $name | Name and description at start. The body when used |
.codex/hooks.json | Hooks around tool calls | Trusted project, after you review each hook in /hooks |
.codex/agents/<id>.toml | Custom subagents | Trusted project |
.codex/config.toml | MCP servers | Trusted project |
AGENTS.md: the chain and the 32 KiB limit
Codex builds its instructions once, when it starts:
~/.codex/AGENTS.override.mdif it exists, else~/.codex/AGENTS.md.- From the project root down to your current folder, one file per folder:
AGENTS.override.md, elseAGENTS.md, else a fallback name you set inproject_doc_fallback_filenames. - Joined root first. Closer files come later, so they win.
It stops adding files at project_doc_max_bytes, 32 KiB by default. Root files go in first, so a fat root file crowds out the nested ones. And files below your launch folder don't load at all.
A generated repo plans around both limits:
- The root file stays lean. It uses about half the budget.
- Folder rules live in nested files. This repo has 32 of them. Every chain, root down to the deepest folder, stays under 30 KiB. We checked that Codex CLI 0.161 loads a 28 KB chain whole.
- A full folder links instead of copying. When a chain runs out of room, that folder's AGENTS.md points at the rule's full text in
.agents/rules/<id>.md. - The root covers the launch-folder gap. It tells Codex to read every AGENTS.md on the path before it edits a file.
Here is the top of that root file. Note the $setup line: in Codex, skills start with $.
# my-app
Generated by [Agentic Boilerplate](https://github.com/agentic-studio/agentic-boilerplate) from [Agentic Studio](https://theagentic.studio). Same `agentic.config.json`, same repo: regenerate and diff any time.
- **Stack:** Next.js on Vercel (`nextjs-vercel`)
- **Services:** Drizzle ORM (`drizzle`), Neon (`neon`), Better Auth (`better-auth`), Stripe (`stripe`), Resend (`resend`), Sentry (`sentry`), PostHog (`posthog`), Admin panel (`admin-panel`), MDX blog (`blog-mdx`)
- **Design:** Daylight (`daylight`). Every UI change follows [DESIGN.md](DESIGN.md).
- **Package manager:** bun
- **Mode:** solo
## Start here
On a fresh clone, run the `setup` skill: `/setup` in most agents, `$setup` in Codex.
It reads [SETUP.md](SETUP.md), which lists every environment variable, where to get
it, and the order to set the services up.
```sh
bun install
bun run setup:env -- --check # what .env.local still needs
bun run verify
bun run dev
```
First 22 of 335 lines of AGENTS.md.
The full walkthrough of root and nested files: AGENTS.md examples.
Skills: .agents/skills and $name
Codex reads Agent Skills from .agents/skills/<name>/SKILL.md. At start it sees each skill's name and description. It loads the body only when it uses the skill. Run one by name with a $ in front, or let Codex pick it from its description.
The generated repo ships 29 skills. On a fresh clone, start with $setup. It reads SETUP.md, shows a plan, and fills .env.local after you say yes. Then $verify proves every service answers.
These are the same files Cursor, Copilot, Antigravity and most other agents read. Claude Code gets a copy in .claude/skills/. More: Agent Skills in every agent.
Hooks: .codex/hooks.json
Codex runs project hooks from .codex/hooks.json, in the same shape Claude Code uses: an event, a matcher, a command. Hooks are on by default in Codex CLI 0.161. This is the generated file:
{
"hooks": {
"PostToolUse": [
{
"matcher": "apply_patch",
"hooks": [
{
"type": "command",
"command": "bun \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents/hooks/run.mjs\" auto-lint --from codex",
"timeout": 60
},
{
"type": "command",
"command": "bun \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents/hooks/run.mjs\" enforce-doc-meta --from codex",
"timeout": 60
},
{
"type": "command",
"command": "bun \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents/hooks/run.mjs\" env-leak-detector-write --from codex",
"timeout": 60
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "bun \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents/hooks/run.mjs\" block-destructive --from codex",
"timeout": 60
},
{
"type": "command",
"command": "bun \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents/hooks/run.mjs\" enforce-typecheck --from codex",
"timeout": 60
},
{
"type": "command",
"command": "bun \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents/hooks/run.mjs\" env-leak-detector --from codex",
"timeout": 60
},
{
"type": "command",
"command": "bun \"$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.agents/hooks/run.mjs\" guard-neon-sql --from codex",
"timeout": 60
}
]
}
]
}
}
.codex/hooks.json, as generated.
How it works:
- One launcher. Every command runs
.agents/hooks/run.mjs <guard> --from codex. The guard scripts live once in.agents/hooks/, shared with every agent that runs them. - The repo root, found by git.
git rev-parse --show-toplevelkeeps the path right after Codex changes folder. - Edits arrive as one patch. Codex sends file changes as one
apply_patchcall. The launcher splits it into one write or edit per file, then runs the guards on each. - Exit 2 blocks. The reason goes back to Codex on stderr. In a live run, Codex 0.161 refused
rm -rf ./xwith "blocked by the block-destructive hook".
Two limits. A Claude Code rewrite (a bare tsc swapped for bun run typecheck) becomes a block in Codex that names the command to run instead. And hiding a secret in command output works in Claude Code only, so in Codex the check before the command is what stops a leak. env-leak-detector runs on shell commands only here.
Before any of it runs, trust the project, then review each hook once in /hooks. Codex won't run a project hook you haven't reviewed. Prove the guards still block with bun run verify:hooks. More: guard hooks in every agent.
Subagents: .codex/agents/*.toml
Codex reads custom subagents from .codex/agents/, one TOML file each. name, description and developer_instructions are required. The top of the generated PR reviewer:
name = "pr-reviewer"
description = "Reviews a diff against this repo's rules before it becomes a PR. Convention-aware, blocking on correctness and security, advisory on taste."
sandbox_mode = "read-only"
developer_instructions = '''
You are the PR reviewer for this repository. You review a change *against the
rules this repo has already written down*, not against your own preferences.
A reviewer who invents new standards mid-review is worse than no reviewer.
## Before you read a single line of the diff
1. Read the root `AGENTS.md` and every nested `AGENTS.md` between it and each
file the diff touches. The full text of each rule is in `.agents/rules/`.
First 12 of 85 lines of .codex/agents/pr-reviewer.toml.
developer_instructionsholds the prompt. The same text Claude Code's version uses.sandbox_mode = "read-only"keeps reviewers from writing. It's set onpr-reviewer,security-auditor,db-inspectorandproduct-analyst.- Optional fields inherit. Leave out
modelormcp_servers, and the subagent uses your session's.
The generated repo ships 7 subagents. Each prompt also lives in .agents/agents/ for agents that read that folder.
MCP: .codex/config.toml
Codex reads MCP servers from [mcp_servers.<name>] tables: ~/.codex/config.toml for you, .codex/config.toml for a trusted project. This is the generated one:
# Codex reads this file in a trusted project. MCP servers for this repo.
# Keys come from the shell you start Codex in. Codex never reads .env.local.
[mcp_servers.better-auth]
url = "https://mcp.better-auth.com/mcp"
[mcp_servers.neon]
url = "https://mcp.neon.tech/mcp?readonly=true"
[mcp_servers.posthog]
url = "https://mcp.posthog.com/mcp?readonly=true"
[mcp_servers.sentry]
url = "https://mcp.sentry.dev/mcp"
[mcp_servers.stripe]
url = "https://mcp.stripe.com"
.codex/config.toml, as generated.
- Remote servers sign in with OAuth. Run
codex mcp login <server>for each one. - Neon and PostHog connect read-only, through
?readonly=true. - Keys come from your shell. Codex never reads
.env.local. A server that needs a key reads it from the environment you start Codex in.
The Compound Engineering plugin
The generated repo works in a loop: brainstorm, plan, work, review, write down what you learned. The Compound Engineering plugin adds those commands. In Codex they start with $: $ce-plan, $ce-work, $ce-code-review. Install it once:
codex plugin marketplace add EveryInc/compound-engineering-plugin
codex plugin add compound-engineering@compound-engineering-plugin
Why not declare it in .codex/config.toml? We measured it: a marketplace declared in a project's config makes codex plugin list fail. SETUP.md prints the commands instead.
Codex setup checklist
- Open Codex at the repo root and trust the project.
- Open
/hooksand review each hook once. - Run
$setup. It fills.env.localand connects the services, after you say yes. - Sign in to each MCP server with
codex mcp login <server>. - Install the plugin with the two commands above.
- Run
bun run verify:hooksand watch every guard block in Codex's format.
Get a Codex-ready Next.js repo
Pick your stack at /build. Codex is one of 10 agents, all on by default. You get AGENTS.md and its nested files, .agents/ with every skill and guard, and .codex/ with hooks, subagents and MCP for your services. The same repo works in Claude Code, Cursor, Copilot and the rest. $99 once, with lifetime updates. What each agent gets: the agentic layer.
Other agents: Claude Code setup, GitHub Copilot setup, Cursor rules.
FAQ
Does Codex read AGENTS.md?
Yes. Codex reads ~/.codex/AGENTS.md, then one AGENTS.md per folder from the project root down to the folder you launch in. It joins them root first and stops adding files at 32 KiB by default.
Does Codex read CLAUDE.md?
Not by default. List it in project_doc_fallback_filenames and Codex reads it in folders that have no AGENTS.md.
Where does Codex look for skills?
In .agents/skills/<name>/SKILL.md. Run one as $name, or let Codex pick it from its description.
Does Codex support hooks?
Yes. Project hooks go in .codex/hooks.json or a [hooks] table in .codex/config.toml. They run in a trusted project, after you review each one in /hooks. A PreToolUse hook that exits 2 blocks the call.
How do I add an MCP server to Codex?
Add a [mcp_servers.<name>] table to .codex/config.toml, with a url for a remote server or a command for a local one. Or run codex mcp add. Sign in to a remote server with codex mcp login <server>.
Why aren't my Codex hooks running?
Usually one of three things: the project isn't trusted, you haven't reviewed the hook in /hooks, or the command can't find its script after Codex changed folder. Build the path from the repo root, like git rev-parse --show-toplevel.
Sources
Tool behavior is from the official docs, checked on October 8, 2026. Tools change. The docs win.
Keep reading
- CLAUDE.md template for Next.js, with real examplesA CLAUDE.md template for Next.js you can copy, where the file goes, what belongs in it, and how a repo shared with other agents loads AGENTS.md instead.
- AGENTS.md examples, from a real Next.js repoWhat AGENTS.md is, a template to copy, real root and nested files from a generated Next.js repo, and how Codex, Cursor, Copilot and Claude Code load them.
- CLAUDE.md vs AGENTS.md: which one you needCLAUDE.md is Claude Code's file. AGENTS.md is the one Codex, Cursor, Copilot and most other agents read. Who reads what, and how to keep both in sync.
- Cursor rules for Next.js, with real .mdc examplesHow Cursor rules work: the .mdc format, globs, alwaysApply and the four rule types, when a nested AGENTS.md is enough, and real Next.js rules to copy.