You ask OpenAI Codex / Codex CLI to “add a user settings page.” It produces code that runs, but the file lands at src/UserSettings.tsx instead of src/pages/settings/index.tsx where every other page in the project lives; it’s named UserSettings instead of the project’s consistent SettingsPage; it uses useState even though the project standardizes on Zustand. Codex (Codex CLI, the Codex agent, and ChatGPT Code Interpreter-style subtasks) defaults to “generic best practice” output and doesn’t automatically mimic your project’s existing conventions. This page covers AGENTS.md + explicit references + plan-first prompting to keep it inside your style.
Common causes
Ordered by hit rate, highest first.
1. No AGENTS.md / CLAUDE.md / .cursorrules in the repo
Codex reads one or two fixed files at startup (OpenAI Codex reads AGENTS.md, Claude Code reads CLAUDE.md, Cursor reads .cursorrules). Without them, it scans a few recently edited files and guesses.
You: add a user settings page
Codex: (no AGENTS.md, README doesn't mention directory layout)
→ creates src/UserSettings.tsx
Your project: every page lives at src/pages/<feature>/index.tsx
How to spot it: check the repo root. If none of AGENTS.md, CLAUDE.md, or .cursorrules exist, this is it.
2. Codex never read a sibling file
Even with a guide present, if the prompt doesn’t point at a concrete reference sample, Codex falls back to “standard React project” patterns from its training set instead of your local conventions.
How to spot it: have Codex list which files it read before generating. Run codex --verbose or check the agent tool-call log; if there’s no read_file on a sibling file, this is the cause.
3. The prompt didn’t say “match existing style”
A default prompt like “implement feature X” gives Codex full freedom. It uses generic React + axios + useState patterns and ignores your Zustand / SWR / TanStack Query / shadcn-ui choices.
How to spot it: compare the libraries imported in the generated code to package.json. If it imports something you don’t have installed (or ignores a state library you do have), the prompt was too loose.
4. The project itself is internally inconsistent
If half the files are kebab-case and half PascalCase, half live in pages/ and half in routes/, Codex randomly mimics one — and looks wrong half the time.
How to spot it: run find src -name '*.tsx' | sort. If naming is mixed, the project itself is the underlying problem.
5. In a monorepo, Codex picked the wrong workspace root
In monorepos, Codex sees the root package.json and assumes that’s the entry point, writing files to the root when they should live in apps/web or packages/ui.
How to spot it: generated files land at the root or in the wrong workspace instead of next to similar code.
Shortest path to fix
Ordered by ROI. Steps 1+2 usually get Codex to produce code that’s on-style on the first try.
Step 1: Write AGENTS.md with paths, naming, and stack spelled out
Place it at the repo root — Codex CLI reads it on launch:
# AGENTS.md
## Project structure
- Pages: src/pages/<feature>/index.tsx
- Shared components: src/components/<PascalName>.tsx
- API calls: src/lib/api/<resource>.ts
- Types: src/types/<resource>.ts
- Monorepo entry is apps/web. Do NOT write to repo root.
## Naming
- Component files: PascalCase (SettingsPage.tsx)
- Hook files: useXxx.ts
- Route segments: kebab-case (user-settings)
## Stack (do NOT introduce substitutes)
- State: Zustand (no Redux / Recoil / bare useState for global)
- Data fetching: TanStack Query (no raw axios)
- Forms: react-hook-form + zod
- Styling: Tailwind + shadcn-ui
## Workflow
- After edits run `pnpm typecheck && pnpm lint && pnpm test`
- Ask before adding any new dependency
Step 2: Every prompt should reference a concrete sibling file
Have Codex read a similar existing file before writing:
Add a "Notifications Settings" page.
First, use read_file on these two files and copy their structure and style:
- src/pages/account-settings/index.tsx (sibling page)
- src/components/SettingsCard.tsx (card component usage)
Then generate the new page following AGENTS.md's naming and directory rules.
Do not add new dependencies — reuse Zustand + TanStack Query.
An explicit read_file call is much more effective than vague “follow existing style.”
Step 3: Demand plan-first — confirm structure before writing code
Make Codex output a plan first; you approve, then it edits:
Before writing any code, output a plan with:
1. List of file paths to create or modify
2. One-line purpose for each
3. Any new dependencies (if any)
4. Which existing modules this touches
Wait for me to say "go" before starting any edits.
If a path is wrong, the plan stage catches it — no rollback needed.
Step 4: Self-check with tree + a naming validator
Add a self-verify instruction at the end of AGENTS.md:
# After creating new files, run:
tree src/pages -L 2
# Confirm new page path matches src/pages/<feature>/index.tsx
Or provide a validator script:
node scripts/verify-structure.mjs
# Outputs OK or lists violating files
Step 5: In a monorepo, pin the working directory
Prevent Codex from writing to the root:
# Codex CLI
codex --working-dir apps/web "add a user settings page"
# Or be explicit at the top of the prompt:
"Working directory is apps/web. All new files must live under apps/web/src.
Do not touch the repo root or any other workspace."
In agent mode, start with cd apps/web before any other tool calls.
Prevention
- Keep AGENTS.md (Codex) / CLAUDE.md (Claude Code) /
.cursorrules(Cursor) at the repo root; symlink or sync them so they stay aligned - When introducing a new file type, update AGENTS.md first, write the first sample, then let the AI mimic
- Bake “read_file a sibling sample first, then write” into your prompt template
- Add a
scripts/verify-structure.mjsand run it in CI; block PRs that violate naming/path rules - In monorepos, always launch Codex from the workspace subdir, never the root
- Quarterly, review AGENTS.md and codify the same mistakes the AI keeps making (e.g. “always picks useState”) as explicit bans