Coding · Improving code
The Best Prompt for Refactoring Code
The best prompt for refactoring makes "do not change behavior" something the model has to demonstrate. This prompt has it write down what the code observably does (return values, side effects, errors, ordering) before touching anything, then plan the refactor as a sequence of small named steps, apply them, and check the result against that inventory. Suspected bugs are reported, not quietly fixed. You get the refactored code, a step list you can commit one at a time, and an equivalence table.
Behavior-Preserving Refactoring Prompt
Restructures code in small, named steps while holding its observable behavior fixed, and reports anything it could not prove equivalent.
- Works with
- ChatGPT, Claude, Gemini, Cursor
- Difficulty
- Intermediate
- Complexity
- Multi-part reply
- Variables
- 6
- Version
- 1.0
Customize this prompt
Fill in what you know. Anything left blank stays as a [bracketed placeholder]. Nothing you type leaves your browser.
6 variables · fields marked * matter most
I want this code refactored without changing what it does. You are acting as a careful senior engineer: structure may change, observable behavior may not. <code language="[Language]"> [Code to refactor] </code> Refactoring goal: [Refactoring goal] Must stay exactly as it is: [What must stay exactly as it is] Test coverage today: [Test coverage today] Project conventions to follow: [Project conventions] Work through four phases and show each one. PHASE 1 - BEHAVIOR INVENTORY List everything a caller or the outside world can observe about this code: inputs accepted, return values, mutations of arguments or shared state, I/O and its order, exceptions and when they are raised, and behavior on empty, null or malformed input. Include behavior that looks accidental or wrong. This list is the contract for the rest of the task. PHASE 2 - PLAN Name the specific problems that stand in the way of the goal, with line references. Then give an ordered list of refactoring steps. Each step must be one recognizable move (extract function, rename, inline variable, replace conditional with guard clause, introduce parameter object, and so on) and small enough to commit and test alone. If test coverage is partial or missing, make step 0 a short set of characterization tests that pin current behavior, and write them. PHASE 3 - REFACTORED CODE Apply the plan and show the complete result. Keep public names, signatures, argument order, return shapes and error types unchanged unless I listed them as open to change. Do not add features, new dependencies, logging or extra validation. Do not reformat lines you have no other reason to touch. PHASE 4 - EQUIVALENCE CHECK Go through the Phase 1 inventory item by item in a table: behavior, preserved (yes / no / uncertain), reason. Anything marked no or uncertain must be explained. Rules - If you see a likely bug, leave its behavior intact and report it under "Suspected bugs (not fixed)". - If the goal cannot be reached without a behavior change, stop after Phase 2 and tell me which behavior would change. - If the code depends on something not shown, state what you assumed about it. - Prefer the smallest refactor that reaches the goal. A rewrite is not a refactor. End with: a one-paragraph summary of what is better now, the list of suspected bugs, and the tests you would run before merging.
Use it when you are
- Breaking a long function into named pieces before adding a feature to it
- Removing duplicated logic across a few functions in the same module
- Making code testable by separating calculations from database or network calls
- Cleaning up inherited code whose behavior you have to keep, quirks included
- Preparing a small, reviewable pull request that changes structure only
Why this prompt works
Behavior is written down before structure is touched
A model asked to "clean up" code tends to improve it in ways nobody requested: tightening a loose comparison, raising a different error, reordering two writes. The Phase 1 inventory fixes the contract in plain language first, including the awkward parts, so later phases have something concrete to be checked against and you can see whether the model understood the code at all.
Named steps instead of one large diff
A refactor delivered as a single before-and-after is hard to review and impossible to bisect. Asking for recognizable moves such as extract function or introduce guard clause, each small enough to commit alone, gives you a sequence you can apply and test incrementally, and it discourages the wholesale rewrite that is the main risk in this task.
Missing tests change the plan
Refactoring is only safe when something would tell you that behavior changed. The test coverage field feeds straight into the plan: when coverage is partial or absent, the first step becomes characterization tests that record what the code currently does. That gives you a safety net before any structural edit is applied.
Bugs are reported, not fixed in passing
Fixing a defect during a refactor mixes two kinds of change in one commit, and some callers may depend on the faulty behavior. The prompt keeps suspected bugs in a separate list with their behavior preserved, so you decide what to fix, when, and in which pull request.
The final table has an "uncertain" column
Equivalence cannot always be established by reading code, particularly around shared state, ordering and code that was not shown. Allowing "uncertain" as an answer, and requiring a reason, produces a short list of places to test by hand instead of a blanket assurance that nothing changed.
How to use it
- Paste one coherent unit: a function, a class or a small module. Several hundred lines at once makes the inventory shallow.
- Choose a single goal. If you want both shorter functions and less duplication, run the prompt twice and commit in between.
- List what must not change in concrete terms: signatures, return shapes, error types, database writes, output order.
- Read the behavior inventory and correct it before trusting anything that follows. A wrong inventory means an unsafe refactor.
- Apply the steps one at a time and run your tests after each, starting with the characterization tests if the prompt wrote any.
- Review every row marked no or uncertain in the equivalence table, and open separate tickets for the suspected bugs.
AI model compatibility
| Model | Status | Notes |
|---|---|---|
| ChatGPT | Expected to work | For long files, ask for Phases 1 and 2 first and review the plan, then request Phases 3 and 4 in a second message. It keeps each reply short enough to finish. |
| Claude | Expected to work | The prompt already wraps your code in a <code> tag, in line with Anthropic's advice to separate material from instructions. Add further tags, one per file, if you paste more than one. |
| Gemini | Expected to work | No model-specific adjustment needed. Paste the prompt as written. |
| Cursor | Expected to work | With an assistant that edits files in your repository, ask it to apply one step from the plan at a time and run your test command between steps, so each change can be reviewed and reverted on its own. |
“Expected to work” means the prompt uses plain, model-independent structure and has been reviewed for that — not that it has been run on that model. A model is marked Tested only when a test record is published below.
Worked example
Scenario: A developer has inherited a 90-line order-processing function and needs to add a new discount type without breaking existing ones.
I want this code refactored without changing what it does. You are acting as a careful senior engineer: structure may change, observable behavior may not. <code language="JavaScript (Node.js)"> A single processOrder(order, user) function that validates the order, applies three kinds of discount in nested if/else blocks, calculates tax, writes to the database and sends a confirmation email </code> Refactoring goal: Break up a long function or class Must stay exactly as it is: The processOrder signature and the object it returns, the order of the database write and the email, and the error messages thrown for invalid orders Test coverage today: Partly covered Project conventions to follow: Async/await, no classes, Prettier defaults Work through four phases and show each one. PHASE 1 - BEHAVIOR INVENTORY List everything a caller or the outside world can observe about this code: inputs accepted, return values, mutations of arguments or shared state, I/O and its order, exceptions and when they are raised, and behavior on empty, null or malformed input. Include behavior that looks accidental or wrong. This list is the contract for the rest of the task. PHASE 2 - PLAN Name the specific problems that stand in the way of the goal, with line references. Then give an ordered list of refactoring steps. Each step must be one recognizable move (extract function, rename, inline variable, replace conditional with guard clause, introduce parameter object, and so on) and small enough to commit and test alone. If test coverage is partial or missing, make step 0 a short set of characterization tests that pin current behavior, and write them. PHASE 3 - REFACTORED CODE Apply the plan and show the complete result. Keep public names, signatures, argument order, return shapes and error types unchanged unless I listed them as open to change. Do not add features, new dependencies, logging or extra validation. Do not reformat lines you have no other reason to touch. PHASE 4 - EQUIVALENCE CHECK Go through the Phase 1 inventory item by item in a table: behavior, preserved (yes / no / uncertain), reason. Anything marked no or uncertain must be explained. Rules - If you see a likely bug, leave its behavior intact and report it under "Suspected bugs (not fixed)". - If the goal cannot be reached without a behavior change, stop after Phase 2 and tell me which behavior would change. - If the code depends on something not shown, state what you assumed about it. - Prefer the smallest refactor that reaches the goal. A rewrite is not a refactor. End with: a one-paragraph summary of what is better now, the list of suspected bugs, and the tests you would run before merging.
What a good response should contain
- An inventory that notes non-obvious behavior, such as which discount wins when two apply and that the email is sent only after the write succeeds
- A step 0 containing characterization tests for the discount paths that lack coverage
- A plan of small moves, for example extracting validateOrder, calculateDiscount and calculateTax, with database and email calls left in processOrder
- Refactored code with the same exported signature and thrown messages, and no new dependencies
- An equivalence table with at least one honest "uncertain", such as rounding order in the tax calculation, and a separate list of suspected bugs
This is an illustrative scenario showing how to fill in the prompt and what to look for. It is not a recorded model output. Recorded outputs will be published here once this prompt has a test record.
Testing and editorial review
Status: Untested. Reviewed for structure and clarity by the editorial team. No recorded model test yet.
No test record has been published for this prompt yet. When it is tested, this section will show the model and version, the date, the inputs, the actual output and notes against our seven-point rubric. We do not publish numerical scores.
| Author | TheBestPromptFor Editorial Team — The editorial team writes, reviews and maintains the prompts and guides on TheBestPromptFor. Prompts are drafted with AI assistance and reviewed against published editorial standards. |
|---|---|
| Published | November 15, 2026 |
| Last reviewed | November 15, 2026 |
| Last tested | Not yet tested |
| Version history |
|
Limitations and things to check
- The equivalence check is reasoning about code, not running it. Only your tests, or characterization tests you run before and after, can establish that behavior is unchanged.
- Behavior that depends on code outside what you pasted, such as global state, decorators, middleware or monkey-patching, is invisible to the model.
- Performance characteristics can shift after a refactor even when outputs are identical. Measure if the code is on a hot path.
- Taste varies. The result reflects common conventions for the language unless you state your team's own.
- Very large files exceed what a single reply can restructure well. Work one unit at a time.
Alternative prompts
Coding
Unit Test Writing Prompt
Produces a case inventory first, then readable tests that check behavior at the boundaries, with suspected bugs flagged instead of encoded as passing.
- ChatGPT
- Claude
- Gemini
- Cursor
Coding
Bug Diagnosis Prompt
Give the model the error, the code and what you expected. It ranks likely causes by evidence, tells you how to confirm each, and proposes a minimal fix.
- ChatGPT
- Claude
- Gemini
- Cursor
Web Development
Pull Request Code Review Prompt
Reviews a diff the way a careful senior engineer would: intent first, findings ranked by severity, each tied to a line with a suggested fix.
- ChatGPT
- Claude
- Gemini
- Cursor
Related resources
Technical guide
Prompt Chaining: Breaking a Task Into Linked Prompts
How to split a large task into a sequence of focused prompts, design the handoffs between them, and debug the chain when a step goes wrong.
Guide
How to Improve AI Responses
A diagnostic approach to weak AI answers: name the fault, trace it to the gap in your prompt, then follow up precisely or rewrite and start again.
Frequently asked questions
How is this different from asking for a code review?
A review tells you what is wrong and leaves the changes to you. This prompt makes the structural changes and holds itself to a behavior contract while doing so. If you want opinions on correctness, security or design before deciding what to change, start with the code review prompt and refactor afterwards.
What if I do want a bug fixed along the way?
Do it as a separate step. Run the refactor first with behavior preserved, commit it, then ask for the fix against the cleaner code. Keeping structure changes and behavior changes in different commits makes each easier to review and easier to revert if something goes wrong.
I have no tests at all. Is it still safe to use?
Select "No tests" and the plan will begin with characterization tests that capture current behavior. Run them against the original code first to confirm they pass, then against each refactoring step. Without that, you are relying on reading alone, which is risky for anything important.
Sources and references
- How to do a code review — Google Engineering Practices
- Prompt engineering overview — Anthropic
Was this prompt useful?
No account needed. Do not include personal information.