Kipt

Refactoring prompts for ChatGPT, Claude and Codex

13 refactoring prompts for ChatGPT, Claude and Codex: extract functions, rename, remove duplication, tame legacy code and run safe migrations step by step.

By the Kipt team · Updated 24 October 2026

These 13 refactoring prompts help ChatGPT, Claude, Claude Code and Codex change the structure of code without changing what it does: finding what to refactor, extracting and renaming, removing duplication, getting legacy code under test, and migrating interfaces safely.

The general "refactor this without changing behavior" prompt lives in the coding prompts collection. The prompts here are narrower, and each one targets a specific move.

How do you use these prompts?

Copy a prompt and fill the blanks in double braces, or keep the default after the colon. {{language:TypeScript}} means TypeScript unless you change it.

Three rules make AI refactoring safe:

  • Tests first. A refactor is only safe if something tells you behavior didn't change. If tests are missing, start with prompt 2.
  • Small steps. The Claude Code common workflows page advises doing refactoring in small, testable increments and asking for backward compatibility when needed.
  • Name the move. "Extract function" or "introduce parameter object" gets a more predictable result than "clean this up". Martin Fowler's refactoring catalog lists the standard moves by name.

For multi-file changes, plan before editing. In Claude Code, plan mode lets the agent read and propose without touching files.

Review each step's diff before moving to the next. If a refactor changes the expected value in a test, it changed behavior, whatever the commit message says.

How do you decide what to refactor?

1. Rank refactoring candidates

Not every smell is worth fixing. This prompt weighs payoff against risk.

Review this {{language:TypeScript}} module for refactoring opportunities.

For each one give: the problem (long function, unclear name, duplication,
deep nesting, too many parameters, mixed responsibilities), where it is,
the named refactoring that fixes it, the payoff, and the risk. Rank them
by payoff divided by risk. Skip anything that's only a style preference.

{{code}}

2. Pin current behavior with characterization tests

Before touching code with no tests, record what it does today, bugs included. Then any change in behavior shows up as a failing test.

I need to refactor the code below but it has no tests. Write
characterization tests in {{framework:Vitest}} that record what it does
now, including behavior that looks wrong. Don't fix anything.

Cover each branch and the edge cases you can find. Where current
behavior looks like a bug, keep the assertion but add a comment starting
with "Current behavior:" so I can decide later.

{{code}}

3. Plan a refactor as small commits

For changes that touch many files. Each step should leave the code working.

I want to {{goal:split the OrderService class into smaller services}}.

Relevant code:
{{code}}

Write a plan as a numbered list of small commits. Each commit must
compile, pass the tests, and be reviewable on its own. For each commit
give the commit message, the files it touches, and the risk. Put the
safest, most mechanical steps first. Point out any step that changes
behavior, so I can do it separately.

How do you extract and rename code safely?

4. Break up a long function

The most common refactor. The names of the new functions matter more than the split.

This function is too long. Use Extract Function to break it into smaller
functions in {{language:TypeScript}}.

Rules: same behavior, same signature for the outer function, same error
handling. Each new function does one thing and its name says what. Keep
helpers private unless something else needs them. Show the result, then
list each new function with one line on why it exists.

{{code}}

5. Choose better names

Bad names cost every future reader time. Use AI to pick names, then use your editor's rename tool to apply them.

Suggest better names for the functions, variables, types and parameters
in this code. Our naming conventions:
{{conventions:camelCase, verbs for functions, no abbreviations}}.

Give a table: current name, suggested name, reason. Mark any name that
is part of a public API, appears in config, logs or a database, or might
be used from another repo, because those need a migration, not a rename.

{{code}}

6. Shorten a long parameter list

Functions with many parameters are easy to call wrong. Introduce Parameter Object groups the ones that travel together.

These functions take long parameter lists, and several parameters
always travel together:

{{code}}

Propose parameter objects or types that group related values. Show the
new signatures, one updated call site, and the order to change call
sites so the code works after each step. If a boolean flag changes what
the function does, suggest splitting it into two functions instead.

7. Flatten nested conditionals

Deep if/else chains hide the main path. Guard clauses, lookup tables or polymorphism each fit different cases.

Simplify the conditional logic in this {{language:TypeScript}} code
without changing behavior.

Consider: guard clauses for early returns, a lookup table for mapping
values, or Replace Conditional with Polymorphism if branches switch on a
type. Pick the simplest option that fits and say why you rejected the
others. Show a table of inputs and outputs that are the same before and
after.

{{code}}

How do you remove duplicated code?

8. Merge duplicated logic

Some duplication is real, and some only looks alike today. Merging the second kind creates a worse problem than it solves.

These pieces of code look duplicated:

{{code}}

For each pair or group, decide whether it's the same rule (it should
change together) or a coincidence (it may diverge). For real
duplicates, propose one shared function, where it should live, and its
signature. For coincidences, say why to leave them alone. Don't create
an abstraction with flags for each caller's special case.

How do you refactor legacy code?

9. Find seams for testing

Legacy code is hard to test because it reaches straight for the clock, the network or a global. A seam is a place to swap that out in a test.

This {{language:TypeScript}} code is hard to test. Find the hidden
dependencies: current time, randomness, network calls, file system,
environment variables, globals and singletons.

For each one, propose the smallest change that lets a test replace it
(pass it as a parameter, inject it, wrap it), without changing behavior
for existing callers. Order the changes from least to most invasive.

{{code}}

10. Plan a strangler fig replacement

For replacing a legacy module gradually instead of in one rewrite. Martin Fowler describes the Strangler Fig approach: build the new part alongside the old one and move behavior over piece by piece.

I want to replace {{legacy:the legacy billing module}} with a new
implementation, gradually, while the app stays live.

What it does today: {{responsibilities}}
Who calls it: {{callers}}

Propose: where to put a routing layer so calls can go to old or new code,
the order to move features (lowest risk first), how to compare old and
new results during the move, and the point at which the old code can be
deleted. Include how to roll back each step.

How do you migrate code safely?

11. Change an interface with expand and contract

For breaking changes to a function, API or schema that other code depends on. Parallel Change splits it into three phases: expand, migrate, contract.

I need to make a breaking change:
{{change:rename the userId field to accountId in our API}}.

Callers: {{callers}}

Plan it as a parallel change:
1. Expand: add the new form alongside the old one. Show the code.
2. Migrate: move callers one by one. List them in a safe order.
3. Contract: remove the old form. Say how to confirm nothing still uses it.
For each phase, say what to deploy and how to roll back.

12. Upgrade a dependency across a major version

Major upgrades break in small, scattered ways. Working from the release notes keeps the list complete.

I'm upgrading {{package:a library}} from {{from:v4}} to {{to:v5}}.

Breaking changes from the release notes or migration guide:
{{release_notes}}

How we use it (search results or key files):
{{usage}}

Map each breaking change to the places in our code it affects. Order the
work so the app builds and tests pass at each step, and flag changes that
tests won't catch, like changed defaults. Only use APIs that appear in
the notes I pasted; mark anything else with "Check:".

13. Write a codemod for a mechanical change

When the same edit is needed in hundreds of files, a script is more consistent than an agent editing each file.

Write a codemod using {{tool:jscodeshift}} that does this change across
our codebase: {{change}}.

Before:
{{before}}

After:
{{after}}

Handle these variations: {{variations:aliased imports, multi-line calls}}.
Leave any case it can't handle safely untouched and print its file and
line. Include a few before and after test fixtures and the command to run
it on one folder first.

Which refactoring prompts should you turn into skills?

If you run prompt 2 or prompt 11 often, turn it into a skill so Claude Code or Codex applies it whenever the task matches. Paste the prompt into the free SKILL.md generator to get a valid SKILL.md. For a broader scan, the improve codebase architecture skill looks for refactor candidates across a repo. Before you merge the result, the code review prompts help check the diff, and the unit test prompts help fill gaps the refactor exposed.

Kipt stores prompts like these as Markdown in a private GitHub repo you own, keeps blanks such as {{language:TypeScript}} as fill-in fields, and finds any prompt with Cmd+K. Skills saved there install into Claude Code or Codex with one command.

Questions

How do I ask AI to refactor code without breaking it?

Tell it the behavior and public interface must not change, ask for small steps you can test one at a time, and have tests in place before it starts. If there are no tests, ask for characterization tests that pin the current behavior first.

Can ChatGPT refactor legacy code?

It can explain legacy code, suggest seams for testing and propose a step-by-step plan, which is where most of the value is. For large changes, an agent like Claude Code or Codex that can read the whole repo and run the tests is safer than pasting files into a chat.

Should AI do a large refactor in one go?

No. Ask for a sequence of small commits that each leave the code working and the tests green. Big-bang rewrites are hard to review and hard to roll back.

How do I rename something across a whole codebase with AI?

For a local rename, your editor's rename tool is faster and exact. Use AI to choose better names and to plan renames that cross a public API, config files, database columns or other repos, where a plain rename would break callers.

Do these refactoring prompts work in Claude Code and Codex?

Yes. In an agent, name the files instead of pasting code and ask it to run the tests after each step. Plan mode in Claude Code or /plan in Codex is useful for the planning prompts.

More in Coding

All prompts

Keep your prompts and skills in one place, in your own GitHub. Install every skill with one command.

Get started

Kipt is an independent product, not affiliated with or endorsed by Anthropic, OpenAI, Cursor or GitHub. Claude, ChatGPT, Codex, Cursor and GitHub are trademarks of their owners.