Understanding an unfamiliar codebase with Codex
Codex maps an unfamiliar codebase through a read-only sandbox: an interactive CLI session for the top-down overview and one traced flow, subagents for parallel investigations, codex exec for a map saved to a file, and Codex cloud for very large repositories. The map is trustworthy only after its path:line citations pass a script and its central claim passes a test.
You inherited a payments service with no architecture document, and the engineer who understood the webhook handling left six months ago. Your first ticket says “fix the webhook retry logic”, and you cannot yet say where webhooks are processed. This page is for that developer, and for the tech lead who wants every new hire to reach a first safe change without a week of shadowing.
What you get from mapping a codebase with Codex
Section titled “What you get from mapping a codebase with Codex”- A read-only Codex setup that can inspect everything and change nothing, with a stricter variant for code you do not trust.
- Six copy-paste prompts: the overview, a flow trace, convention discovery, git archaeology, a parallel subagent fan-out, and an adversarial check of the map.
- A headless
codex execcommand and acodex cloud execcommand that each leave the map in a file instead of a chat transcript. - A shell check that proves every
path:linecitation exists, and a characterization test that turns the key claim into something CI re-checks. - An
ARCHITECTURE.mdfor people and anAGENTS.mdupdate for every future Codex session.
Which Codex surface fits which exploration question?
Section titled “Which Codex surface fits which exploration question?”Pick the surface by the question, not by habit. Every row below except the IDE extension leaves an artifact you can check.
| Question | Surface | How you start it | What you keep |
|---|---|---|---|
| “What is this system, and where does my ticket live?” | Interactive CLI, read-only | codex -s read-only | A draft ARCHITECTURE.md |
| “What does this function I have open do?” | IDE extension (VS Code and its forks, such as Cursor) | Select code, ask in the Codex panel | Nothing durable; promote findings to the map |
| “Give me the same map every sprint” | Headless CLI | codex exec -s read-only -o … | A dated report file |
| “Explore a repository too big for my laptop, or a branch I have not checked out” | Codex cloud | codex cloud exec --env … --branch … | A cloud task whose diff holds the report |
| “Keep several threads of inquiry side by side” | Codex desktop app (codex app or /app, macOS and Windows only) | Continue the CLI session with /app | The same files, reviewed in the app |
According to Neowin (secondary source), the Codex desktop app shipped inside the ChatGPT desktop app as a Codex mode on 2026-07-09; the Codex CLI still calls it the Desktop app. The desktop workflow is covered in Codex desktop app: parallel threads, worktrees and review. This page uses the CLI, because every step there produces a file.
Start a read-only Codex session
Section titled “Start a read-only Codex session”Exploration should never edit files, so choose the sandbox on purpose. Run this in a terminal at the repository root:
codex -s read-only -c model_reasoning_effort="high"-s read-only lets Codex read files and run read-only commands such as git log, and blocks writes to the workspace. Codex’s bundled default model, GPT-6 Astra, runs at low reasoning effort by default (the server can override it for signed-in accounts; /status shows the model you actually got); mapping rewards more reasoning, so raise effort before you consider another model (see the models hub for current defaults). Both flags are in codex --help 0.157.1.
OpenAI’s preferred control is a permission profile, which is in beta: codex -c default_permissions=":read-only". Use either the profile or -s, not both, because OpenAI states that the profile and legacy sandbox systems “do not compose”. Inside a running session, /permissions changes what Codex is allowed to do, and /status shows the current configuration and token usage.
For a repository you do not trust, such as a vendor drop or an acquired codebase, two protections apply. Since Codex 0.150.0, a project you have not marked as trusted does not supply its AGENTS.md, so do not trust the project when Codex asks. Hooks run only after you grant them persisted trust, so decline that too. For stronger isolation, run the session inside a container.
Map the codebase from the top down
Section titled “Map the codebase from the top down”The order matters. Each step narrows the question, so Codex reads fewer files at every step and the answers get more specific.
-
Get the overview. Codex reads the manifests, the directory tree, configuration and entry points, then returns a short summary. That summary is your index, not your understanding.
-
Trace the one flow you must change. Scope the trace to your ticket. One path followed end to end is worth more than a tour of every module. Type
@in the composer, or run/mention, to attach files you already suspect. -
Read the conventions before you write code. Conventions are the unwritten rules a reviewer will reject your first pull request for.
-
Ask git why the strange code exists. Commit history explains decisions the code cannot, such as a retry loop that looks redundant or a “do not change” comment.
Keep the main thread clean with subagents
Section titled “Keep the main thread clean with subagents”Every file Codex reads stays in the session’s context, and answers get vaguer as it fills. Subagents are on by default in Codex 0.157.1 (multi_agent is stable in codex features list): each one explores in its own context and returns a summary. Use /subagents to switch between them, and /side to ask a quick question in an ephemeral fork without polluting the main thread.
When /status shows the context filling up, run /compact to summarize the conversation, or /new to start fresh from the saved map. Context budgets across long sessions are covered in context management across Codex surfaces.
On a very large repository, text search is the most expensive part of exploration. A code-intelligence MCP server answers “who calls this function” through a language server instead. Serena, a community server from Oraios, is one option (PyPI serena-agent 1.7.0, checked 2026-09-26). Its maintainers warn against installing it from an MCP or plugin marketplace because those listings carry outdated commands, so install it from upstream and register it with Codex:
uv tool install -p 3.13 serena-agentserena initcodex mcp add serena -- serena start-mcp-server --project-from-cwd --context=codexSerena’s own Codex setup (serena setup codex) also raises startup_timeout_sec to 15 in config.toml; do the same if the server times out on first start.
Compare it with the alternatives in code-intelligence MCP servers.
Save the map to a file with codex exec
Section titled “Save the map to a file with codex exec”A map in a chat transcript cannot be checked or diffed. Run the overview headless so the result lands in a file. Put the overview prompt from the first step in prompts/architecture-map.md, then run this in a terminal at the repository root:
mkdir -p docscodex exec -s read-only -c model_reasoning_effort="high" \ -o docs/ARCHITECTURE.md \ "$(cat prompts/architecture-map.md)"-s read-only keeps the agent from writing anything, and -o (--output-last-message) makes the CLI itself write Codex’s final message to the file. Both are in codex exec --help 0.157.1. Scripted runs, JSON output and CI authentication are covered in running Codex non-interactively.
Hand a very large repository to Codex cloud
Section titled “Hand a very large repository to Codex cloud”When the repository is too large to explore comfortably on your machine, or the code you need is on a branch you have not checked out, submit the analysis as a cloud task. The environment must exist first; see Codex cloud environments.
codex cloud exec --env ENV_ID --branch release/2026-09 \ "Map the authentication subsystem under src/auth/: every entry point, the \middleware chain and session handling, with path:line citations. Write the \result to docs/analysis/auth-map.md and change no other file."Replace ENV_ID with your environment’s identifier; codex cloud with no subcommand lets you browse them. --branch defaults to your current branch, so name it whenever you mean another one. codex cloud status TASK_ID reports progress, and codex cloud diff TASK_ID shows the report as a diff you read without applying. --attempts runs best-of-N, which pays off for code changes more than for reports. The codex cloud command is marked experimental in 0.157.1.
Prove the map before you trust it
Section titled “Prove the map before you trust it”A fluent summary is not a correct one. The agent can cite a renamed file, describe a middleware that is registered but disabled, or smooth over a dispatch it never resolved. You do not fix that by rereading every file. You make each claim checkable and let machines check it. Run these three checks in order, cheapest first.
-
Check every citation mechanically. The prompts above demand
path:linefor each claim. Run this in a terminal at the repository root. It prints every citation whose file is missing or whose line is past the end of the file:Terminal window grep -oE '[A-Za-z0-9_./-]+\.[A-Za-z0-9]+:[0-9]+' docs/ARCHITECTURE.md \| sort -u | while IFS=: read -r f l; doif [ ! -f "$f" ]; then echo "missing file: $f"elif [ "$l" -gt "$(wc -l < "$f")" ]; then echo "line out of range: $f:$l"fidoneEmpty output means every citation points at real code. Citations of extensionless files such as
Dockerfileare not checked, and ahost:portshows up as a missing file you can ignore. The check proves the claims are anchored, not that they are right. -
Attack the map from a fresh context. A reviewer that did not write the map has no stake in defending it. Run the check below as a separate
codex exec -s read-only --ephemeralcall, or in a new session after/new, so it does not inherit the first pass’s assumptions. -
Turn the central claim into a test. Pick the claim your ticket depends on, for example “a webhook event already marked processed is acknowledged without a second database write”. Start a session with write access (
codex -s workspace-write), ask Codex for a characterization test that asserts exactly that current behaviour, and run it. A passing test is evidence that the map matches the code; a failing one is the most valuable finding of the week. Once merged, CI re-checks the claim on every commit. The technique is covered in characterization tests.
Who signs off. The developer signs off the map for the area they are about to change, after all three checks pass. ARCHITECTURE.md and AGENTS.md changes go through a normal pull request, where the code owner of that area reviews a diff of a few dozen lines of documentation, not the code behind it. That is the shift from reading code to reviewing evidence described in evidence, not diffs.
Save what you learned for the next session
Section titled “Save what you learned for the next session”Exploration that is not written down gets repeated by the next person and by your own next session. Keep two files, with different readers.
| File | Reader | What goes in it |
|---|---|---|
docs/ARCHITECTURE.md | People | The checked map: subsystems, traced flows, dependency direction, open questions |
AGENTS.md | Every future Codex session | Build and test commands, confirmed conventions and traps, in as few lines as possible |
If the repository has no AGENTS.md, run /init to create one, then tighten it with this prompt in a session that can write:
To keep the map current, schedule a drift check. The desktop app’s automations “schedule recurring tasks to run in the background”; a CI schedule running codex exec works the same way and leaves a log. Either way, have the job report drift rather than rewrite the file, and run the citation check from the previous section in CI so a stale citation fails a build. Setup and guardrails for both are in scheduled Codex automations.
Where codebase exploration with Codex goes wrong
Section titled “Where codebase exploration with Codex goes wrong”| Symptom | Likely cause | Recovery |
|---|---|---|
| The overview is generic (“uses a layered architecture”) | The prompt asked for a summary, not citations | Re-ask with “cite path:line for every claim, mark inferences”. Prose without citations is a guess. |
| Codex maps the wrong service in a monorepo | It latched onto the first manifest or entry file it found | Name the scope: “The service is packages/billing-api/. Ignore every other package.” Or start with codex -C packages/billing-api -s read-only. |
| Citations fail the shell check | Files were renamed, or the model reconstructed a path | Tell Codex which citations failed and ask it to re-open those files. Never repair a citation by hand without re-reading the code. |
| Answers get vaguer as the session goes on | The context is full of file contents | Check /status. Move broad reading to subagents, then /compact, or /new and continue from docs/ARCHITECTURE.md. |
| Codex describes the system in the README, not the one in the code | Stale documentation was treated as ground truth | Say “when documentation and code disagree, the code wins; list every disagreement”. Those disagreements are useful output. |
| A trace stops at dependency injection or a plugin registry | Static reading cannot resolve runtime wiring | Ask for the registration site, then confirm with a characterization test or a debug log in a local run. |
| The cloud report describes the wrong code | The task ran on your current branch, or the environment’s repository is stale | Pass --branch explicitly, and check the environment’s setup before re-running. |
| A write was blocked mid-exploration | The read-only sandbox is doing its job | Keep it. Switch to a writable session only for the test and the AGENTS.md update. |
How Claude Code and Cursor handle the same job
Section titled “How Claude Code and Cursor handle the same job”This page covers Codex only. The workflow of map, trace, prove and save carries over, but the controls differ: Claude Code uses plan mode, --restricted and built-in Explore subagents; Cursor works from the editor. See understanding an unfamiliar codebase with Claude Code and Cursor’s large-codebase strategies. For tool-neutral advice on monorepos and million-line repositories, see strategies for very large codebases, and for the repository properties that make every map easier to check, see making a codebase agent-ready.
Where to go next after mapping the codebase
Section titled “Where to go next after mapping the codebase”Once the map passes its checks, design or plan the change against it. Tech leads measuring how fast new engineers reach a first safe change can use the developer onboarding metric.