Teaching Codex Your Project: The AGENTS.md Chain, config.toml, Skills and MCP
Codex chains its instructions from the global AGENTS.md through every directory from the repo root to the working directory; the closer file comes later and wins, and anything after 32 KiB in total never reaches the model. In Bookstore: root and subfolder AGENTS.md files, a shared instruction strategy with Claude Code, the trust-gated project config.toml layer, profiles in separate files, a migration skill with implicit invocation turned off and a version-pinned MCP server.
Version note: This post describes Codex CLI 0.169.0 (13 November 2026); instruction discovery, configuration layers and skill details were checked on 15 November 2026 against the Custom instructions with AGENTS.md, Config basics, Advanced Configuration, Configuration Reference, Build skills, Model Context Protocol and Import from another agent pages at learn.chatgpt.com/docs, and the behaviour for files in subdirectories against the base instructions file in github.com/openai/codex on the same day. This post is based on the official documentation. The sample config.toml files were parsed locally and validated against Codex's official JSON schema, and the YAML frontmatter of the skill files was parsed.
Guess First
Emre, who works on Bookstore, the online bookstore used as the shared example across this site's series, got tired of explaining the same things to Codex for a week and wrote everything into files. In his own ~/.codex/AGENTS.md he wrote "use pnpm when installing packages". Into the AGENTS.md at the repo root he pasted the build commands, the layer rules and the whole architecture document; the file grew past 40 KB. He put the Angular rules into web/bookstore-web/AGENTS.md and started Codex at the repo root as usual.
What is your guess? With a repo that uses npm, which package manager does Codex pick? Which part of the 40 KB file reaches the model? And in a session started at the root, are the Angular rules loaded automatically? The answers are in the chain section and the Bookstore section.
We covered the tool-independent side of instruction files, that is, what belongs in an AGENTS.md and what does not, in the second post of the AI-Assisted Development series (/blog/agentsmd-copilot-instructions-context-dosyalari). This post focuses on Codex's mechanics: which file is read in which order, which layer the configuration comes from, how repeated work becomes a skill and where an MCP server is defined.
How Is the AGENTS.md Chain Built?
When a session starts, Codex builds an instruction chain, and it does so again on every run; there is no cache to clear. The order in the documentation has three steps:
- Global: in the Codex home folder (by default
~/.codex, on Windows%USERPROFILE%\.codex) Codex first looks forAGENTS.override.md, otherwiseAGENTS.md, and takes only the first non-empty file at this level. - Project: in every directory from the project root (usually the Git root) down to the working directory it looks for
AGENTS.override.md,AGENTS.mdand the names inproject_doc_fallback_filenames, in that order, and takes at most one file per directory. - Merge: the files are concatenated from the root down, separated by blank lines. A file closer to the working directory comes later in the prompt and therefore overrides the earlier one.
The answer to the first question from the guess is in this order. The global file comes first in the chain and the file at the repo root comes after it. If the root AGENTS.md says "use npm" explicitly, that rule wins because it comes later; if the repo says nothing on the matter, you can expect Codex to apply the global preference. Writing a project rule into the global file therefore affects other repos as well and makes it unclear what applies in the project.
Empty files are skipped, and once the combined content reaches the project_doc_max_bytes limit (by default 32 KiB, that is 32,768 bytes) Codex stops adding files. The answer to the second question is here too: everything after the first 32 KiB of Emre's 40 KB file never reaches the model, and according to the documentation files in subdirectories are not added either once the limit is reached. You can raise the limit, but the documentation's main recommendation is to split instructions across nested directories. The Pricing page also suggests keeping AGENTS.md small and splitting it across nested directories to make usage limits last longer; the file's content is added to the context.
The third question is subtler. The chain covers only the path from the project root to the working directory; if you started Codex at the root, web/bookstore-web/AGENTS.md is not added to the prompt at the start. Codex's open-source base instructions file on GitHub tells the model to check for applicable AGENTS.md files when it works in a folder below the working directory, and that a file's scope is the whole folder it sits in. So the rules in the subdirectory are read by the model, but that is an instruction the model follows, not a load that Codex guarantees. Starting a session in which you will work mostly on Angular with codex -C web/bookstore-web makes sure the rules enter the chain.
Bookstore: One Source at the Root, Details in Subfolders
Bookstore's root AGENTS.md is kept short: commands, layout and rules. The architecture document is not copied into the file; Codex can read it from the repo when needed.
# Bookstore
Online bookstore: ASP.NET Core 10 API, Angular 22 client, SQL Server.
See README.md for local setup.
## Build and test
- Build: `dotnet build Bookstore.slnx`
- API tests: `dotnet test` (needs SQL Server; the connection string `ConnectionStrings:BookstoreDb` is in user-secrets)
- Client: run `npm test` and `npm run build` in `web/bookstore-web`
- Run the relevant tests before you say a change is done, and show the test summary.
## Layout
- `src/Bookstore.Api`: endpoints, EF Core `BookstoreContext`, migrations in `src/Bookstore.Api/Data/Migrations`
- `src/Bookstore.Contracts`: DTOs shared with the client; no reference to EF Core
- `tests/Bookstore.Api.Tests`: API tests
- `web/bookstore-web`: Angular client with its own `AGENTS.md`
## Rules
- Money is `decimal` with currency `TRY`; times are stored in UTC.
- Endpoints return `ProblemDetails` on errors.
- Read-only EF Core queries use `AsNoTracking()` and pass the `CancellationToken` through.
- Never edit an existing migration; add a new migration instead (see the `add-migration` skill).
- Never put secrets in code or appsettings files; use user-secrets locally.
- Ask before adding a NuGet or npm package.
Area-specific rules live in that area's folder. The Angular rules are in web/bookstore-web/AGENTS.md, and the migration rules in src/Bookstore.Api/Data/Migrations/AGENTS.md:
# Migrations
- Files in this folder are generated by `dotnet ef migrations add`. Never edit or delete a migration that is already committed.
- To change the schema, add a new migration with the `add-migration` skill and review the generated SQL.
- Never run `dotnet ef database update` against any database; the developer applies migrations.
The three files together come to about 2 KB, far below the 32 KiB limit. AGENTS.override.md, on the other hand, is not a team file. The documentation describes it as a temporary global or per-directory override; if a directory has an override, that directory's AGENTS.md is not read at all. That is why Bookstore added it to .gitignore; a developer trying something out can write their own override and delete it afterwards. According to the documentation Codex also copies an AGENTS.override.md that git ignores into the worktrees it manages. The quickest way to see that the chain is built correctly is the check from the documentation:
codex -a never "Summarize the current instructions."
codex --cd web/bookstore-web -a never "Show which instruction files are active."
Shared Instructions for Two Tools: Claude Code and Codex
The Bookstore team also uses Claude Code. As we saw in the second post of the Claude Code series (/blog/claude-code-claude-md-memory-rules), Claude Code can read AGENTS.md when there is no CLAUDE.md, and on Windows the most portable route is a short CLAUDE.md that starts with an @AGENTS.md line. There are two options:
AGENTS.mdis the source andCLAUDE.mdimports it: Codex reads its own file the natural way, and the few lines specific to Claude Code stay inCLAUDE.md. The cost is that details specific to Claude Code, such as path-specific rules, stay in separate files.CLAUDE.mdis the source and Codex reads it withproject_doc_fallback_filenames = ["CLAUDE.md"]: nothing changes on the Claude Code side. The cost is that instructions specific to Claude Code reach Codex too; the Codex documentation has no import mechanism with@, so those lines are read as plain text.
Bookstore chose the first route, because other tools on the team also read AGENTS.md. For anyone moving an existing Claude Code setup, Codex has a shortcut: /import in the CLI, Settings > Import in the desktop app. According to the documentation instruction files are imported into AGENTS.md, settings.json into config.toml, slash commands into skills, and MCP and hook definitions into their Codex equivalents, while the setup on the Claude Code side stays unchanged. Read what was imported as a diff before you commit it; the two tools' permission models are not identical (post three).
config.toml: Layers and Trust
Codex settings are in TOML format and come from several layers. The precedence order in the documentation, from strongest to weakest, is: command-line flags and values passed with -c; the project's .codex/config.toml files (from the root down to the working directory, the closest one wins); the profile file selected with --profile; the user file ~/.codex/config.toml; defaults delivered from the cloud for the workspace; the system file; built-in defaults. The desktop app, the CLI and the IDE extension share these layers.
The project layer has a condition: Codex loads the project .codex/ folder only when the project is marked as trusted. In an untrusted project the project configuration, project hooks and project rules files are skipped; the user and system layers still load. According to the documentation the project file also cannot change keys that redirect credentials or run machine-specific commands: keys such as model_provider, openai_base_url, notify, profile and otel are ignored in a project file, with a warning at startup. Cloning a repo does not mean letting that repo send your identity to another server.
Emre's personal file sets the default model and reasoning effort and keeps the sign-in in the operating system's credential store. The line Codex saves when you trust the project also lives here:
#:schema https://developers.openai.com/codex/config-schema.json
# Personal defaults: %USERPROFILE%\.codex\config.toml on Windows
model = "gpt-6.1-sol"
model_reasoning_effort = "medium"
cli_auth_credentials_store = "keyring"
# Codex writes this when you trust the folder
[projects.'C:\src\bookstore']
trust_level = "trusted"
The #:schema comment on the first line is the documentation's suggestion: with this schema the Even Better TOML extension provides completion and error highlighting in Visual Studio Code and Cursor. The same schema is defined with additionalProperties: false, so it also catches a misspelled key; the files in this post were validated with it. On the command line the --strict-config flag makes Codex fail when it sees a field it does not recognize.
Since 0.134 profiles are separate files. codex --profile deep-review loads the user file first and then the deep-review.config.toml next to it; in the profile file you write only the values that differ. The old [profiles.x] tables and the profile = "x" selector are no longer read. Inside a session, /debug-config shows which value comes from which layer.
# %USERPROFILE%\.codex\deep-review.config.toml; usage: codex --profile deep-review
model = "gpt-6-astra"
model_reasoning_effort = "high"
Skills: Packaging Repeated Work
Instead of writing a workflow into the prompt every time, you can package it as a skill. A skill is a folder with a SKILL.md inside; name and description are required in the frontmatter, and scripts, reference documents and templates can sit next to it. Codex uses the open agent skills standard. Repo skills are read from the .agents/skills folder in every directory from the working directory up to the repo root, personal skills from $HOME/.agents/skills. Codex also ships two skills of its own, skill-creator and skill-installer.
To protect the context, Codex initially sees only the name, description and file path of each skill; by default this list takes at most 2 percent of the context window. When it decides to use a skill, it reads the whole SKILL.md. A skill comes into play in two ways: explicitly (/skills or $add-migration in the prompt) or implicitly, when the task matches its description. We don't want a risky job like a migration to start on its own, so Bookstore's skill turns implicit invocation off in agents/openai.yaml:
---
name: add-migration
description: Create a new EF Core migration in src/Bookstore.Api, review the generated SQL and write rollback notes. Use only when the user explicitly asks for $add-migration with a migration name.
---
# Add an EF Core migration
The user gives the migration name in the prompt, for example `$add-migration AddLowStockAlerts`.
1. If the name is missing or not PascalCase, ask for a name and stop.
2. Build the solution: `dotnet build Bookstore.slnx`. Stop and report if the build fails.
3. Find the latest existing migration: `dotnet ef migrations list --project src/Bookstore.Api`.
4. Create the migration:
`dotnet ef migrations add <Name> --project src/Bookstore.Api --output-dir Data/Migrations`
5. Generate the SQL from the previous migration to the new one:
`dotnet ef migrations script <Previous> <Name> --project src/Bookstore.Api --output artifacts/migrations/<Name>.sql`
6. Read the migration and the SQL, then report:
- tables and columns that are added, changed or dropped
- anything that can lose data: dropped columns, narrowed types, NOT NULL without a default
- indexes the new queries need that the migration does not create
7. Write `artifacts/migrations/<Name>.rollback.md` with the previous migration name and the command
`dotnet ef database update <Previous> --project src/Bookstore.Api`.
Never apply the migration to a database and never edit an existing migration.
interface:
display_name: "Add EF Core migration"
short_description: "Create a migration, review its SQL and write rollback notes"
policy:
allow_implicit_invocation: false
The custom prompts under ~/.codex/prompts/ that you see in old blog posts are deprecated. They work only with explicit invocation and live in a personal folder, so they are not shared with the repo; that is why the documentation recommends skills instead. If you want to distribute a skill to other teams, you put it in a plugin; a plugin can carry several skills and MCP connections as one package.
Defining an MCP Server
MCP servers are also defined in config.toml, with [mcp_servers.<name>] tables; personal ones in the user file, the ones the team shares in the .codex/config.toml of the trusted project. Because the desktop app, the CLI and the IDE extension share these definitions on one machine, setting them up once is enough. To test Bookstore's Angular UI in a browser, the Playwright MCP server was added to the project file:
#:schema https://developers.openai.com/codex/config-schema.json
# Bookstore project settings for Codex. Codex loads this file only when the project is trusted.
[mcp_servers.playwright]
command = "npx"
args = ["-y", "@playwright/mcp@0.0.85"]
startup_timeout_sec = 30
default_tools_approval_mode = "prompt"
The package version is pinned on purpose; @latest means different code may run on every start. startup_timeout_sec defaults to 10 seconds, and on the first start npx downloading the package can take longer. default_tools_approval_mode = "prompt" puts every call to the server's tools behind an approval; writes asks only for tools that are not marked read-only. You can switch specific tools on and off with enabled_tools and disabled_tools. On the command line codex mcp add, codex mcp list and, for servers that require OAuth, codex mcp login do the same job; inside a session /mcp lists the active servers.
Writing an MCP server itself was covered in the AI Agents and MCP series, and the Claude Code equivalent in "Connecting MCP Servers to Claude Code: The Bookstore MCP Server, the Database and the Browser" (/blog/claude-code-mcp-server-baglamak). Codex has one cost point to watch: according to the Pricing page every MCP server adds context to your messages and uses up your usage limit; turn off a server you don't need with enabled = false.
In Production
Review AGENTS.md like code. A single line added to the root file goes into every session of everyone on the team. Keep it short, keep the commands current, and when a rule is applied wrongly twice, make the text clearer; adding more rules is often not the fix.
The project .codex/ folder needs review too. The config.toml of a repo you trust brings in MCP servers, hooks and rules files that start commands on your machine. When you clone an unfamiliar repo, look at this folder first, then trust it.
Don't write secrets into configuration. The documentation says that for a confidential OAuth client codex mcp add saves the client secret into config.toml and that the file must be kept private; such a value must never go into the project's committed file. For HTTP servers that need a token, giving the environment variable name with bearer_token_env_var is safer.
Common Pitfalls
Going over 32 KiB. Everything after the limit is silently dropped. Split the file, and write the path of the architecture document instead of copying it.
Conflicting nested files. If the root says "npm" and a subfolder says "pnpm", the closer one wins, but everyone who reads them stays confused. Remove the conflict and write the exception explicitly.
Writing a project rule into the global file. ~/.codex/AGENTS.md is for personal working preferences; it applies in other repos too.
The old profile syntax. [profiles.x] tables have not been read since 0.134; a profile is a separate x.config.toml file.
Expecting .codex/ to work in an untrusted project. If the project is not trusted, the MCP server, hooks and rules files are not loaded at all; /debug-config shows this.
A Small Experiment
★☆☆ Generate an AGENTS.md scaffold in your own repo with /init, delete the lines you don't need and note its size in bytes. Then run the "Summarize the current instructions." prompt and see which rules come back.
★★☆ Put an AGENTS.md in a subfolder and start Codex once at the root and once in that folder with --cd. How does the answer to "Show which instruction files are active." differ between the two?
★★★ Write a repeated job on your team (a migration, a release note, a new endpoint scaffold) as a skill, turn implicit invocation off and use it with $skill for two weeks. Which steps needed the most corrections?
Codex now knows Bookstore's rules, but knowing a rule is no guarantee that it will apply it. In post three we look not at rules but at technical boundaries: sandbox modes, the approval policy, auto-review, the Windows sandbox and rules files.