Prompt template · Code
Refactoring prompt template
Restructure code toward one stated goal without changing behaviour, with risky steps flagged. Free to copy, or open it in the prompt builder to fill the variables and get the exact API request.
196 tokens unfilled · 304 with the example below · o200k_base (GPT-4o and later)
Template
The prompt
Paste this into a chat window and replace each {{variable}}, or open it in the prompt builder to fill them in a form. Sections are marked with XML tags, which every major model reads well.
You are a senior {{language}} engineer who refactors in small, safe steps and keeps behaviour identical.
<context>
<code>
{{code}}
</code>
</context>
<constraints>
- Preserve the public interface: names, parameters, return values, errors raised and side effects, unless the goal says otherwise.
- Make the minimum change that achieves the goal. Don’t add abstractions, options or files that the goal doesn’t need.
- Keep the project’s existing conventions: {{conventions}}.
- If a step could change behaviour (error order, evaluation order, floating-point results, timing), flag it instead of doing it silently.
</constraints>
<output_format>
The refactored code in one block. Then a numbered list of the changes, one line each, with any risky step marked “check:”.
</output_format>
<task>
Refactor this code to {{goal}}. Keep its behaviour exactly the same for every caller.
</task>For an API call: system prompt and user message
With a system prompt, the role, constraints and output format stay fixed across calls (and can be cached), while the context and task go in the user message.
You are a senior {{language}} engineer who refactors in small, safe steps and keeps behaviour identical.
<constraints>
- Preserve the public interface: names, parameters, return values, errors raised and side effects, unless the goal says otherwise.
- Make the minimum change that achieves the goal. Don’t add abstractions, options or files that the goal doesn’t need.
- Keep the project’s existing conventions: {{conventions}}.
- If a step could change behaviour (error order, evaluation order, floating-point results, timing), flag it instead of doing it silently.
</constraints>
<output_format>
The refactored code in one block. Then a numbered list of the changes, one line each, with any risky step marked “check:”.
</output_format><context>
<code>
{{code}}
</code>
</context>
<task>
Refactor this code to {{goal}}. Keep its behaviour exactly the same for every caller.
</task>Variables
What to put in each variable
- {{language}}
- The language, such as Java or Python.
- {{code}}
- The code to refactor. Include its callers if the interface might change.
- {{goal}}
- One concrete goal, such as “split the 200-line handler into functions that can be tested separately” or “remove the duplicated retry logic”. One goal per run works far better than “clean this up”.
- {{conventions}}
- Rules from your codebase the result must follow, such as “dataclasses, not dicts; no new dependencies”. Write “none in particular” if you have none.
Use
When to use it
Use it when you know what better looks like but the change is tedious: extracting functions, removing duplication, replacing a long conditional with a lookup, moving from callbacks to async. Give it one goal per run and review each result before asking for the next step.
Have tests in place first. A refactor is only safe if you can show the behaviour didn’t change, so if the code has no tests, run the unit test template before this one.
Structure
Why it’s structured this way
The goal is a variable on purpose. “Refactor this” gives the model no target, so it rewrites everything to its own taste. A single concrete goal produces a reviewable diff, and Anthropic’s guide makes the general point that precise instructions beat vague ones.
The constraints fight scope creep. Anthropic notes that some Claude models tend to overengineer, adding extra files, abstractions or flexibility nobody asked for, and suggests asking for minimal solutions; other models do the same. Listing what counts as the public interface (including errors and side effects) closes the gap where code looks equivalent but isn’t.
Flagging risky steps instead of doing them silently covers the subtle cases: reordering two calls that both write to a log, or changing a loop that sums floats. These are rarely caught in review because the code looks cleaner.
Example
A filled-in example
- {{language}}
Python
- {{code}}
def price(order): if order["country"] == "GB": tax = order["subtotal"] * 0.2 elif order["country"] == "DE": tax = order["subtotal"] * 0.19 elif order["country"] == "FR": tax = order["subtotal"] * 0.2 else: tax = 0 return round(order["subtotal"] + tax, 2)- {{goal}}
replace the country conditional with a lookup table so new countries are a one-line change
- {{conventions}}
type hints on public functions; no new dependencies
What to look for. A careful result uses a dict of rates with a default of 0 and keeps the final round exactly where it was. Moving the rounding, or rounding the tax separately, would change some totals by a penny, which is the kind of step the template asks to be flagged.
The complete filled-in prompt (304 tokens)
You are a senior Python engineer who refactors in small, safe steps and keeps behaviour identical.
<context>
<code>
def price(order):
if order["country"] == "GB":
tax = order["subtotal"] * 0.2
elif order["country"] == "DE":
tax = order["subtotal"] * 0.19
elif order["country"] == "FR":
tax = order["subtotal"] * 0.2
else:
tax = 0
return round(order["subtotal"] + tax, 2)
</code>
</context>
<constraints>
- Preserve the public interface: names, parameters, return values, errors raised and side effects, unless the goal says otherwise.
- Make the minimum change that achieves the goal. Don’t add abstractions, options or files that the goal doesn’t need.
- Keep the project’s existing conventions: type hints on public functions; no new dependencies.
- If a step could change behaviour (error order, evaluation order, floating-point results, timing), flag it instead of doing it silently.
</constraints>
<output_format>
The refactored code in one block. Then a numbered list of the changes, one line each, with any risky step marked “check:”.
</output_format>
<task>
Refactor this code to replace the country conditional with a lookup table so new countries are a one-line change. Keep its behaviour exactly the same for every caller.
</task>Models
Tips by model family
- Claude
Anthropic’s guide reports that Claude Opus 4.5 and 4.6 can overengineer and suggests asking for minimal changes. If you’re on those models and see new helper classes appear, repeat the minimal-change rule in stronger terms.
- OpenAI GPT
Non-reasoning GPT models need very precise instructions, according to OpenAI’s guide. Spell out the goal as an end state (“each function under 30 lines”) rather than a direction (“make it shorter”).
- All models
Compare the before and after with the prompt diff or your usual diff tool, and run the tests. A refactor that changes behaviour is a bug, however tidy it looks.
Related
Related templates and tools
- Write unit testsTests for normal cases, edge cases and errors in your framework, focused on behaviour rather than implementation.
- Code reviewReview a diff for bugs, risky changes and missing tests, ranked by severity with line references.
- Convert code to another languageTranslate code idiomatically into another language, map libraries, and list every behaviour difference.
Edited the template? Compare your version with this one in the prompt diff, and count it for your model with the token counter. Browse all 29 prompt templates.