Refactoring and Improving Existing Code
On this page
Transforming Legacy Code into Modern Code
Refactoring is one of the most time-consuming tasks in development, and rarely the most rewarded: no one congratulates you for splitting an 800-line file. That’s exactly why it accumulates, sprint after sprint, until it becomes the real cause of your slowdown. Codex reduces hours of manual work to minutes while preserving existing behavior—the only thing that truly matters in a refactor.
Structural Refactoring
The most common case is the catch-all file that no one dares to touch because it’s imported everywhere.
"Refactor src/utils/helpers.ts: this file is 800 lines long.
Split it into thematic modules in src/utils/ (string.ts,
date.ts, validation.ts, formatting.ts). Update all imports
across the project."
Codex handles this family of tasks exceptionally well: it identifies functions, groups them by theme, creates the new files, and then updates every import in the project. That last step is usually what discourages manual refactoring—forty files to fix, one missed import, and the build breaks at the worst possible moment. And the result is objectively verifiable: if tests passed before and still pass, the split is correct.
Code Modernization
The other major case is updating to modern patterns, where the transformation is mechanical but so repetitive that it keeps getting pushed to the backlog.
"Migrate all callbacks in src/lib/database.ts to
async/await. Preserve existing error handling."
The starting point is callback-based JavaScript with its cascading error handling:
function getUser(id, callback) {
db.query("SELECT * FROM users WHERE id = ?", [id],
(err, rows) => {
if (err) return callback(err);
callback(null, rows[0]);
});
}
Here’s what Codex produces:
async function getUser(id: string): Promise<User> {
const rows = await db.query(
"SELECT * FROM users WHERE id = ?",
[id]
);
return rows[0];
}
Three things happened in a single pass: TypeScript types appeared, callbacks gave way to async/await, and error handling simplified since exceptions now propagate naturally. The business logic remains identical—and that’s exactly what you verify in review, not the elegance of the result.
Improving Quality
You can also target a specific quality dimension rather than a syntactic transformation, provided you enumerate the requirements.
"In src/api/, improve error handling:
- Replace generic try/catch blocks with typed errors
- Add appropriate HTTP error codes
- Add logging with request context
- Ensure Prisma errors are mapped correctly"
Phrased this way, the request becomes verifiable point by point during review. A standalone “improve error handling” prompt would produce something plausible but unusable, because neither you nor the agent would know when the objective was met.
Pattern-Based Refactoring
The most powerful variant involves designating an already-compliant file and requesting generalization.
"All React components in src/components/ that use
useState for forms must migrate to react-hook-form.
Apply the same pattern as src/components/LoginForm.tsx,
which is already migrated."
Codex reads the reference component, extracts the pattern, and applies it to the target components while handling edge cases—custom validation, side effects—instead of performing a blind replacement. The practical implication is interesting: the first component, the one you migrate yourself, pays for all the others. Invest care in this model file; it’s worth a specification.
Verifying the Refactor
Codex runs tests after every refactor, but a refactor that passes tests isn’t necessarily shippable. Four checks form the minimum, and each addresses a different risk.
| Check | Command | What it verifies |
|---|---|---|
| Unit tests | npm run test | Behavior preserved |
| Types | npx tsc --noEmit | No type errors |
| Linting | npm run lint | Conventions respected |
| Build | npm run build | Production ready |
The typical case justifying this list: moving files leaves tests green because they import from a barrel file, but breaks the production build on a circular import that nothing else reveals. Add these four commands to your AGENTS.md file, and Codex will run them after every change without you having to think about it or remind it.
Key Takeaways
- Refactoring is the task where Codex delivers the most time savings
- Reference a model file to guide the refactoring pattern
- Codex updates imports and references across the entire project
- Always verify with tests, type checking, and build after refactoring
- Document verification commands in AGENTS.md