Optimize AGENTS.md and skills for Codex
Optimizing AGENTS.md and skills for Codex means keeping the always-loaded instruction chain short and layered, moving multi-step procedures into skills that load only when a task needs them, and checking what Codex actually loaded with codex debug prompt-input. Codex joins project files root to leaf under a 32 KiB budget, so the deepest files are cut first.
This page is for the developer or tech lead who owns a repository’s Codex setup. The symptom is familiar: you added a precise rule to services/payments/AGENTS.md last week, and Codex still throws raw errors in that service while following every vague rule at the root. Before you blame the model, check whether that file reached the prompt at all.
If you are writing your first AGENTS.md, start with AGENTS.md setup and come back here once the files exist.
What you get from a tuned AGENTS.md and skills setup
Section titled “What you get from a tuned AGENTS.md and skills setup”- A way to see the exact instructions Codex received, without asking the model to remember them.
- A budget script you can run locally and in CI that fails before a file is silently truncated.
- A rule for deciding whether guidance belongs in
AGENTS.md, a skill, config, or a test gate. - A skill layout Codex discovers, with its own context budget under control.
- Four copy-paste prompts: cut a draft, find truncation, promote a procedure to a skill, and find contradictions.
How does Codex decide which AGENTS.md files to load?
Section titled “How does Codex decide which AGENTS.md files to load?”The loader in codex-rs/core/src/agents_md.rs (checked against Codex CLI 0.157.1 on 2026-09-26) builds the chain in this order:
- Global file. Codex reads
~/.codex/AGENTS.override.mdif it exists, otherwise~/.codex/AGENTS.md. It arrives as user instructions and does not count against the project budget. - Project root. Codex walks up from the startup directory until it finds a
project_root_markersentry (default:.git). With no marker, only the startup directory is searched. An empty list (project_root_markers = []) disables the walk. - One file per directory. From the root down to the startup directory, Codex takes the first name that exists as a file:
AGENTS.override.md, thenAGENTS.md, then eachproject_doc_fallback_filenamesentry. - Concatenation. Files join root to leaf, so the most specific file lands last in the prompt.
- Budget. The project files share
project_doc_max_bytes, which defaults to 32 KiB (32,768 bytes). - Trust. Since Codex 0.150.0, an untrusted project supplies no project-level
AGENTS.mdat all in a session. Only the global file loads.
Step 3 has a sharp edge. An empty AGENTS.override.md still wins its directory, contributes nothing, and hides the AGENTS.md beside it. You can reproduce this in a scratch repository in under a minute.
See exactly what Codex loaded with codex debug prompt-input
Section titled “See exactly what Codex loaded with codex debug prompt-input”Asking the agent “which instruction files did you load?” gets you a summary the model writes from memory. codex debug prompt-input renders the model-visible prompt as JSON instead, so the answer is deterministic. Run it from the directory where you normally start Codex:
# terminal, from your usual startup directorycodex debug prompt-input "ping" > /tmp/prompt.jsongrep -o 'AGENTS.md instructions for [^"]*' /tmp/prompt.jsonThe match shows the whole <INSTRUCTIONS> block Codex will send, with every loaded file in order. To see the budget cut without editing config, lower it for one run:
codex debug prompt-input -c project_doc_max_bytes=4096 "ping" | grep -o 'AGENTS.md instructions for [^"]*'In a scratch repository with an 18-byte root file and a 51-byte services/pay/AGENTS.md, -c project_doc_max_bytes=40 ended the block at - Throw only Pay: the module file’s heading survived and its only rule was cut mid-word (Codex CLI 0.157.1, 2026-09-26). That half-rule is what a real truncation looks like.
Fail the build before a file is truncated
Section titled “Fail the build before a file is truncated”codex debug prompt-input depends on local trust and config, so it is a diagnostic, not a CI gate. For the gate, compute the same chain from the file system. Save this as scripts/agents-md-budget.sh:
#!/usr/bin/env bash# Usage: scripts/agents-md-budget.sh [START_DIR]# Prints the AGENTS.md chain Codex loads for START_DIR and fails if it exceeds the budget.set -euo pipefailbudget="${AGENTS_MD_BUDGET:-32768}" # keep in step with project_doc_max_bytesstart="$(cd "${1:-.}" && pwd -P)" # physical path: git prints the resolved rootroot="$(git -C "$start" rev-parse --show-toplevel)"chain=()dir="$start"while :; do for name in AGENTS.override.md AGENTS.md; do # add your fallback names here if [ -f "$dir/$name" ]; then chain=("$dir/$name" ${chain[@]+"${chain[@]}"}); break; fi done [ "$dir" = "$root" ] || [ "$dir" = / ] && break dir="$(dirname "$dir")"donetotal=0for file in ${chain[@]+"${chain[@]}"}; do size=$(wc -c < "$file") total=$((total + size)) printf '%7d bytes %7d total %s\n' "$size" "$total" "${file#"$root"/}" [ "$size" -eq 0 ] && echo " warning: empty file shadows the AGENTS.md beside it" >&2doneif [ "$total" -gt "$budget" ]; then echo "AGENTS.md chain for $start is $total bytes, over the $budget-byte budget" >&2 exit 1fiThen check every directory that holds an instruction file, because the deepest directories carry the longest chains:
# terminal or CI step, from the repository rootgit ls-files --cached --others --exclude-standard -- \ 'AGENTS.md' '*/AGENTS.md' 'AGENTS.override.md' '*/AGENTS.override.md' \ | xargs -n1 dirname | sort -u \ | xargs -n1 scripts/agents-md-budget.shThe --others --exclude-standard flags include new files you have not committed yet, so the check gives the same answer locally as in CI. The script ignores the global file on purpose, matching the loader. A green run proves every chain fits. It does not prove the rules are good, which is the next section’s job.
What belongs in each AGENTS.md layer?
Section titled “What belongs in each AGENTS.md layer?”Each layer answers one question. Anything that fails that question belongs somewhere else.
| Layer | File | Holds | Size target |
|---|---|---|---|
| Personal | ~/.codex/AGENTS.md | How you like to work in every repository | Under 20 lines |
| Repository | AGENTS.md at the root | Commands, test framework, conventions that differ from defaults | Under 50 lines |
| Module | services/payments/AGENTS.md | Rules that apply only inside this directory | Under 30 lines |
A module file earns its place when it states something the root cannot:
- Throw only through `PaymentError` from `src/errors.ts`; the API layer maps it to HTTP codes.- Every public endpoint needs the `rateLimit()` middleware from `src/middleware/rate-limit.ts`.- Run `pnpm --filter payments test` before you finish; the root test command skips this package.Three kinds of lines waste the budget in every layer:
- Things the model already does. “Write clean code” and “use meaningful names” change nothing.
- Things the code already says. A directory map or architecture overview goes stale and costs bytes on every session.
- Procedures. A 15-step release checklist loads on every turn, even when nobody is releasing. Move it into a skill.
For the evidence on cutting instead of adding, and a full ablation method, see Pruning CLAUDE.md and AGENTS.md.
When should a rule become a skill, config or a test instead?
Section titled “When should a rule become a skill, config or a test instead?”AGENTS.md is advice the model reads. Some guidance needs a stronger home.
| The guidance is… | Put it in | Why |
|---|---|---|
| A short convention that applies to most tasks | AGENTS.md | Loaded every session, cheap if short |
| A multi-step procedure for some tasks (release, migration, PR prep) | A skill | Only its name and description load until it is used |
| A setting (model, sandbox, MCP servers) | config.toml | Config is applied, not interpreted |
| A command the agent must never run unsandboxed | Codex rules (.rules) | Enforced outside the model |
A rule that must always hold (no raw errors, no console.log) | A lint rule or test, plus one line in AGENTS.md | The build fails when the agent forgets |
The last row is how quality stays provable. AGENTS.md makes the right output more likely. A lint rule or test makes the wrong output fail the build, so you verify the rule by reading a red or green check instead of every diff.
Write a skill Codex will pick up
Section titled “Write a skill Codex will pick up”A skill is a directory with a SKILL.md file. Codex lists each skill’s name and description in a catalog, and reads the full file only when you invoke the skill or your prompt matches its description.
.agents/skills/pr-ready/ SKILL.md # required: frontmatter + instructions scripts/ # optional: code the skill runs references/ # optional: docs the skill reads on demand agents/openai.yaml # optional: Codex UI metadata and dependencies---name: pr-readydescription: Prepare the current branch for a pull request. Use when the user asks to get changes PR-ready, open a PR, or check a branch before review. Not for reviewing someone else's PR.---
1. Run `pnpm lint --fix`, then `pnpm lint`. Stop and report if errors remain.2. Run `pnpm test`. Fix failures caused by this branch; report pre-existing ones separately.3. Run `pnpm typecheck`.4. Write a PR description: what changed and why, how it was tested, breaking changes.5. End with a table of each check and its pass or fail result.The description does the routing. Say when to use the skill and when not to, or implicit matching fires on the wrong prompts.
Where Codex finds skills
Section titled “Where Codex finds skills”| Scope | Location | Notes |
|---|---|---|
| Repository | .agents/skills/<name>/SKILL.md | Committed and shared. Scanned from the working directory up to the repository root |
| Personal | ~/.agents/skills/<name>/SKILL.md | Read by Codex 0.157.1 (checked 2026-09-26) |
| Installer target | $CODEX_HOME/skills (default ~/.codex/skills) | Where the bundled $skill-installer writes |
| Bundled | Ships with Codex | imagegen, openai-docs, plugin-creator, review-agent, skill-creator and skill-installer in 0.157.1; review-agent is bundled but not listed in the default catalog |
Invoke a skill explicitly with $pr-ready in the prompt, or browse them with /skills. To scaffold a new one, type $skill-creator and describe the task.
Install shared skills
Section titled “Install shared skills”OpenAI’s catalog is the openai/skills repository. Inside Codex, the bundled installer reads its curated list:
$skill-installer install gh-fix-ciFrom a terminal, the cross-agent skills CLI (1.7.0 on 2026-09-26) installs into the project’s .agents/skills/:
npx skills add openai/skills --skill gh-fix-ci -a codexInstall per project when you can. With -g, the CLI writes Codex skills to ~/.codex/skills/, not ~/.agents/skills/, so confirm with /skills that Codex sees them.
Keep the skill catalog inside its budget
Section titled “Keep the skill catalog inside its budget”Skills are cheaper than AGENTS.md, not free. The catalog of names and descriptions has its own budget, skills.max_context_tokens, which defaults to 2% of the model’s context window and is capped at 10,000 tokens when you set it. Too many installed skills crowd each other out of that catalog: with -c skills.max_context_tokens=50, codex debug prompt-input listed no skills at all. Turn off the ones you do not use:
[[skills.config]]name = "imagegen"enabled = false
[[skills.config]]path = "/home/you/.codex/skills/old-release/SKILL.md"enabled = falseFor shared skill standards across a team, see skills optimization and team sharing.
Use AGENTS.override.md for a temporary phase
Section titled “Use AGENTS.override.md for a temporary phase”An AGENTS.override.md replaces the AGENTS.md in the same directory while it exists. That makes it a clean switch for a migration or a freeze:
# TEMPORARY: delete when the v3 router migration is merged (owner: @api-team)- Add new endpoints only under src/routes/v3/. Do not edit v1 or v2 routes.- Use AuthContext from src/lib/auth-v3.ts in all new middleware.- Run `pnpm test:contract` before finishing; v2 clients must keep passing.The override hides the whole permanent file, so copy across any permanent rule you still need. Put an owner and an exit condition in the first lines, and let the budget script’s file list remind you it is still there.
Trim the context the setup costs
Section titled “Trim the context the setup costs”/status in the Codex TUI shows the current session configuration and token usage. /mcp lists the connected MCP tools. Each MCP server adds tool schemas to every turn, so switch off the ones this repository does not need, or narrow them to the tools you use:
# ~/.codex/config.toml or .codex/config.toml[mcp_servers.jira]enabled = false
[mcp_servers.github]enabled_tools = ["get_pull_request", "list_pull_request_files"]Raise project_doc_max_bytes only after you have cut and split. A larger budget keeps the file whole, but every session still pays for it:
project_doc_max_bytes = 65536 # default 32768If you raise it, set AGENTS_MD_BUDGET in CI to the same value. For the wider picture of compaction and context across the App, CLI and cloud, see context management across Codex surfaces.
Prove the instructions work without reading every session
Section titled “Prove the instructions work without reading every session”A clean setup is one you can check from outputs, not transcripts:
-
Loaded.
scripts/agents-md-budget.shpasses in CI for every directory with an instruction file. -
Received.
codex debug prompt-inputfrom each service directory shows that service’s last rule inside<INSTRUCTIONS>. -
Enforced. Every rule that must always hold has a lint rule or test. The CI result proves compliance, and a reviewer does not have to spot it in the diff.
-
Owned.
AGENTS.md,AGENTS.override.mdand.agents/skills/sit under aCODEOWNERSentry for the tech lead who owns the setup. Changes to them get reviewed like code, because they change every future session.
When AGENTS.md and skills break in Codex
Section titled “When AGENTS.md and skills break in Codex”- A module rule is ignored while root rules are followed. The chain is over budget. Run the budget script from that directory, then cut or split the root file. Raise
project_doc_max_bytesonly as a last resort. - A whole directory’s rules vanished. An empty or forgotten
AGENTS.override.mdis shadowing theAGENTS.mdbeside it. Runfind . -name AGENTS.override.mdand delete what no longer has an owner. - No project instructions load at all. The project is untrusted (0.150.0 and later), or the startup directory is outside the repository root.
codex debug prompt-inputdoes not apply the trust check (it still rendered project files withtrust_level = "untrusted"in 0.157.1), so a clean render does not rule trust out. Look at the[projects."<path>"]entry in~/.codex/config.toml, and trust the project when Codex asks. - Rules are followed early and forgotten late in a long session. Compaction summarised the conversation. Restate the one constraint that matters in your prompt, or start a new session with
/new. - A skill never fires implicitly. Its description does not match how people ask. Add the phrases your team uses, invoke it with
$nameuntil it does, and check that/skillslists it. - A skill fires on the wrong tasks. Its description is too broad. Add a “Not for…” clause, and disable overlapping skills with
[[skills.config]]. - Cloud tasks ignore your local rules. Cloud environments read the
AGENTS.mdcommitted to the repository. Commit what matters; keep only personal preferences in~/.codex/AGENTS.md.
Where to go next with AGENTS.md and skills
Section titled “Where to go next with AGENTS.md and skills”- AGENTS.md setup covers writing the first global and project files.
- Codex configuration explains
config.tomllayers, profiles and overrides. - Team collaboration and shared configuration rolls committed config, rules and skills out to a whole team.
- Agent skills: turn policy into a tested workflow shows how to prove a skill fires and holds, across Claude Code, Codex and Cursor.
- Making a codebase agent-ready puts
AGENTS.mdnext to the tests and gates that back it up. - Using Claude Code too? The Claude Code memory system is the
CLAUDE.mdcounterpart of this page.