You asked Codex to add a feature module. The PR puts it in /src/features/billing/. Your repo uses /app/(dashboard)/billing/ (Next.js App Router). The diff is plausible — it just doesn’t match your codebase at all. Or: Codex adds vitest deps to the root package.json of a pnpm workspace where each package has its own package.json. Or: it writes tests with jest when the rest of the repo uses vitest.
Codex isn’t guessing maliciously — it’s defaulting to generic patterns when your repo’s conventions aren’t visible. The fix is AGENTS.md with a directory map + canonical examples to point at, plus naming target paths explicitly in the task.
Common causes
Ordered by hit rate, highest first.
1. No AGENTS.md (or it’s stale)
Without AGENTS.md at the repo root, Codex reads a sample of files and generalizes — but it can’t see structural conventions from a few file reads. The first directory it lands in becomes “the project layout.”
How to spot it: ls AGENTS.md — missing means the agent is guessing structure from file samples. If it exists, check git log AGENTS.md — last update >6 months ago and many features added since means it’s stale.
2. Task didn’t name target paths
“Add a billing feature” lets Codex pick. “Add a billing feature in apps/web/src/features/, following the layout of apps/web/src/features/auth/” pins it. The first is a coin flip; the second is determinate.
How to spot it: Re-read your prompt. If no specific directory is named, Codex chose its own.
3. Codex generalized from the wrong example file
It read legacy/v1/UserService.ts first because it appears earlier in alphabetical traversal, decided “this is the project style,” and ignored your modern src/services/UserService.ts. Both exist; Codex picked the wrong canonical.
How to spot it: The new code matches a deprecated/legacy area in style/imports/structure. Codex was reading the wrong subtree.
4. Monorepo treated as one package
Codex didn’t realize your repo is a pnpm/yarn workspace. Adds dependencies to root package.json, imports across packages without using the workspace alias, runs pnpm install at the wrong level.
How to spot it: New imports cross package boundaries directly (relative paths or top-level package names). Check pnpm-workspace.yaml / lerna.json / nx.json — if any exists, Codex must respect the workspace.
5. Test framework / linter mismatch
Repo uses vitest; Codex writes jest-style tests because it’s the more common pattern in its training data. Tests look correct but never run because the framework isn’t installed.
How to spot it: New test file imports a framework not in package.json dependencies. Run pnpm test path/to/new-file.test.ts — Cannot find module 'jest' confirms.
6. Codex created a folder where one already existed under a different name
Your repo has src/Components/ (capital C). Codex made src/components/ (lowercase). On case-insensitive filesystems (macOS default) this is a confusing duplicate. On case-sensitive (Linux CI) it breaks imports unexpectedly.
How to spot it: Two directories differing only in case. ls -la src/ | sort reveals.
Shortest path to fix
Ordered by ROI. Step 1 alone eliminates 70% of structure mismatches.
Step 1: Create AGENTS.md with a directory map
In your repo root:
# AGENTS.md
## Directory map
- `apps/web/` — Next.js 14 App Router (NOT pages router)
- `apps/web/src/features/` — feature modules, one folder per feature
- `apps/web/src/components/` — shared UI primitives (lowercase!)
- `apps/web/app/` — routes, group folders use `(name)` syntax
- `packages/ui/` — shared component library, build with tsup
- `packages/db/` — Prisma client + migrations
- `scripts/` — Node CLI utilities
## Canonical examples
- Feature module layout: see `apps/web/src/features/auth/`
- Shared component pattern: see `packages/ui/src/button/`
- API route convention: see `apps/web/app/api/users/route.ts`
## Conventions
- Package manager: **pnpm** (workspace). Never use `npm` or `yarn`.
- Test framework: **vitest** with `@testing-library/react`. Never use jest.
- Linter: ESLint config in `packages/eslint-config-acme/`.
- Imports: use workspace aliases (`@acme/ui`), not relative `../../`.
## Do not
- Create folders in `src/` — features go in `apps/web/src/features/`.
- Add dependencies to root `package.json` — add to the package that uses them.
- Mix `Components/` (capital) with `components/` (lowercase) — we use lowercase.
Codex reads this on every task. Most structural mistakes evaporate.
Step 2: Point at a canonical example in the task
For new features:
Add the billing feature. Follow the structure of `apps/web/src/features/auth/`:
- index.ts (public API)
- types.ts
- components/
- hooks/
- billing.test.tsx (vitest, not jest)
Place new files at `apps/web/src/features/billing/`.
A pointer to a specific real example beats any amount of prose convention.
Step 3: Tell Codex which package to work in (monorepo)
Working directory: apps/web
- All file paths in this task are relative to apps/web.
- Add dependencies via `pnpm --filter=@acme/web add <pkg>`.
- Use the workspace alias `@acme/ui` when importing shared components.
- Do not touch root `package.json` or other packages.
Step 4: Reject mismatched structure early, re-prompt
If Codex creates the wrong directory, don’t fix it manually — delete the wrong location, re-prompt:
Your previous patch created `src/billing/`. That's wrong — see AGENTS.md.
Correct path: `apps/web/src/features/billing/`.
Delete `src/billing/`. Re-implement under the correct path, following
`apps/web/src/features/auth/` as the canonical example.
This trains the session, not just fixes one mistake.
Step 5: For large repos, narrow Codex’s “starting view”
In repos with many top-level dirs, Codex’s first reads dominate its mental model. Pin the read:
Before writing any code, read these three files:
1. apps/web/src/features/auth/index.ts
2. apps/web/src/features/auth/billing.test.tsx
3. apps/web/src/features/auth/components/LoginForm.tsx
These are the canonical patterns for this codebase. Apply them to the new feature.
Step 6: Per-package AGENTS.md for big monorepos
For a 30-package repo, one root AGENTS.md can’t cover everyone’s conventions. Add apps/web/AGENTS.md, packages/ui/AGENTS.md, each with package-specific rules. Codex picks up the closest one.
apps/web/AGENTS.md
└── "This package uses App Router, Server Components by default."
packages/ui/AGENTS.md
└── "All components are client components; use 'use client' at top of file."
Prevention
- Maintain
AGENTS.mdas a living doc — refresh whenever architecture changes, not just at project start - Always include a “canonical examples” section pointing at real folders Codex can read
- In task prompts, name the target path explicitly; “in the right place” never works
- For monorepos, set working directory or filter in every prompt
- Per-package
AGENTS.mdfiles for big repos — closest file wins - Audit existing duplicate-case folders (
Components/vscomponents/) quarterly and consolidate
Related
- Codex output does not fit the project
- Codex misses project-specific conventions
- Codex-generated code does not fit the existing style
- Codex beginner guide
- Codex code review workflow
- Codex vs Claude Code
Tags: #Codex #Coding agent #Troubleshooting #Debug #Project structure