# Migrate a pattern across a codebase

Move every use of an old API, library or pattern to its replacement: Claude Code lists each place first, then changes them in checked batches.

Paste into: **Claude Code**, started in your project folder

## Prompt template

How the builder on the page fills in this template, so you can do the same:

- `{{key}}` becomes the text entered for that field, exactly as typed. Empty text, or text that is only whitespace (spaces, tabs or line breaks), counts as empty: a required field then becomes `[fill in: <label>]` with its label, and an optional field becomes nothing.
- For a choice field, `{{key}}` becomes the text of the chosen option, or of the default when none is chosen.
- Text between `{{#key}}` and `{{/key}}` stays only when that field is not empty; a choice field always counts as filled. The markers themselves are removed, and a marker that stands alone on its line takes its line break with it.
- Each value is inserted once, as it is: `{{…}}` inside a value stays as typed.

```text
{{#example}}
<example>
{{example}}
</example>

{{/example}}
Migrate everything from {{from}} to {{to}}.
{{#scope}}
Limit the migration to: {{scope}}
{{/scope}}
{{#example}}
Use the converted use in <example> as the model for the mapping.
{{/example}}

Step 1: identify every place that needs to change. Write the list to MIGRATION.md, grouped by directory with a count for each, and mark any use that does not map cleanly onto the replacement. Show me the summary and wait for my go-ahead before changing code.

Step 2: after I confirm, make the changes in batches, one directory at a time. After each batch, run the tests that cover it, and do not move on while they fail. Tick off each batch in MIGRATION.md.

Rules:
- Keep behavior the same. If the replacement cannot express something the old code did, leave that use unchanged and list it as an exception with the reason.
- Do not mix unrelated cleanup into the migration.
- When you are done, search again for remaining uses of the old pattern and report each one with a reason.
```

## Fields

- `{{from}}` (required): Old pattern or API.
- `{{to}}` (required): Replacement.
- `{{scope}}`: Limit the migration to. Optional. A directory or package. Leave empty to cover the whole project.
- `{{example}}`: One call converted by hand. Optional. A before and after pair shows the intended mapping more precisely than a description. It goes first in the prompt, inside <example> tags.

This site doesn't run Claude or show model output. Results depend on your input and the model you use.

## When to use this template

- A library, API or internal helper is being replaced, and its uses are spread across many files.
- The change is repetitive but not quite mechanical, so a plain search and replace would miss variants or break edge cases.
- You want a written inventory of what will change before any code changes, so you can size the work and spot awkward cases early.

## When not to use it

- Only a handful of uses exist. Ask Claude to change them directly; the inventory step is overhead at that size.
- The replacement behaves differently in ways that need product decisions, such as different defaults or error handling. Settle those first, then migrate.
- The migration spans thousands of files. Use the inventory from step 1, then split the work across several sessions or run Claude Code non-interactively per file, testing the prompt on a few files first.

## Why this structure

- The work is split into two steps with a stop in between. The inventory in step 1 is written to a planning file and shows the real size of the migration and its awkward cases before any code changes; you decide whether to go ahead.
- Writing the list to a file gives both of you a shared checklist that survives a long session or a fresh one, and makes progress visible as batches are ticked off.
- The optional before and after example goes first, inside `<example>` tags, so it is kept apart from the instructions. It pins down the mapping more precisely than a description of the two APIs.
- Batches by directory, each followed by its tests, keep any breakage small and easy to locate. "Do not move on while they fail" gives Claude a clear signal to stop and repair.
- The exceptions rule keeps behavior unchanged where the replacement does not fit, and turns those places into a list for you to decide on instead of silent rewrites.
- The final search for remaining uses closes the loop, so the migration ends with evidence that nothing was missed rather than an assumption.

## Example input (fictional)

Old pattern or API:

```
the old logging helper in utils/log.js
```

Replacement:

```
the structured logger in lib/logger.ts
```

Limit the migration to:

```
the services/ directory
```

One call converted by hand:

```
log("user created", id)
→ logger.info({ userId: id }, "user created")
```

## Follow-ups to send Claude

- Go ahead with step 2, but start with the smallest directory so I can review the first batch before the rest.
- For each exception in MIGRATION.md, suggest how the replacement could support it, or confirm it should stay on the old API.
- Now that nothing uses the old helper, remove it and check that the build and tests still pass.

## Common mistakes

- Skipping the inventory and asking for everything at once. Large unreviewed diffs are hard to check and hard to roll back in part.
- Leaving out the scope in a large repository. Claude may spend most of the session cataloguing code you did not mean to touch.
- Mixing in "while you are there" cleanups. They make the migration diff harder to review and harder to revert.

## Related templates

- [Plan a code change before editing](https://awesomeclaudeprompts.com/prompts/plan-code-change/): Have Claude Code read the relevant code and propose a file-by-file plan for a multi-file change, without editing anything until you approve it.
- [Build something new from an existing pattern](https://awesomeclaudeprompts.com/prompts/follow-code-pattern/): Point Claude Code at code that already works the way you want, so the new feature matches its structure, naming, tests and error handling.
- [Port code to another language](https://awesomeclaudeprompts.com/prompts/port-code-language/): Have Claude Code port a module to another language while keeping the API and behavior you name, with the tests ported and run against the new code.

## Sources

- [Claude Code docs: Prompt library](https://code.claude.com/docs/en/prompt-library) (Anthropic documentation)
- [Claude Code docs: Common workflows, refactor code](https://code.claude.com/docs/en/common-workflows#refactor-code) (Anthropic documentation)
- [Claude Code best practices: Fan out across files](https://code.claude.com/docs/en/best-practices#fan-out-across-files) (Anthropic documentation)

---

Awesome Claude Prompts is an independent project. It is not affiliated with, endorsed by, or sponsored by Anthropic. Claude is a trademark of Anthropic, PBC.
