What this prompt does
A find-and-replace rename breaks the moment a name shows up somewhere it doesn't look like a name: a route alias, a serialized cache key, a string in a config file, a heading in your docs. This prompt forces Claude Code through a discovery-first workflow instead. Step one greps every occurrence across code, tests, docs, and config — so the rename is scoped from real matches, not guesses — before a single line changes.
It works because the order is deliberate. The diff plan is grouped by file with a risk rating per group, so you see the dangerous edits (public exports, shared interfaces, route names) separately from the trivial ones. Only then does it apply the change while explicitly preserving imports, route names, and public API shape, update the tests and docs that referenced the old name, and run the type check and test suite as proof. Anything it can't safely automate comes back as a manual follow-up list.
The hard stop before shared interfaces is the safety valve: a rename that's local to one module is cheap, but one that touches a contract other code depends on gets a confirmation gate instead of a silent edit.
When to use it
- Renaming a class, function, or variable whose name leaked into route names, event names, or cache keys.
- Moving or renaming a file and needing every import path, autoload reference, and test fixture updated with it.
- Retiring confusing domain language (e.g.
Member→Customer) consistently across code, tests, and docs in one pass. - Cleaning up an inconsistent name that exists in several casings —
userId,user_id,UserID— where blind replace is unsafe. - Renaming something exposed in a public API or package export, where you need the risk flagged before you touch the contract.
- Any rename big enough that you want a reviewable plan and a green test run, not a hopeful commit.
Example output
Renaming `fetchUser` → `loadUser` (type: function)
Occurrences found: 23 across 11 files
PLAN (grouped, risk-ranked)
src/api/users.ts 2 [HIGH] exported — public API, callers external
src/services/auth.ts 5 [MED] internal callers, one DI binding
tests/users.test.ts 9 [LOW] test names + assertions
docs/api.md 4 [LOW] code samples, no logic
CHANGELOG.md 3 [SKIP] historical entries — leave as-is
⚠ src/api/users.ts re-exports fetchUser as a public symbol.
Confirm before I touch this shared interface?
After confirm → apply, then:
✔ tsc --noEmit passed
✔ vitest 48 passed
Manual follow-up: add `export { loadUser as fetchUser }` shim if
downstream packages still import the old name.
Pro tips
- Be precise with
[rename_type]—function,class,file,route name,env var. The type tells Claude which references are real (afilerename means import paths and autoload entries; aroute namemeans templates and redirects), which sharpens the grep and cuts false matches. - For a public symbol, decide your compatibility story up front: rename clean and break callers, or keep a deprecated alias/shim. State it in the prompt so the "manual follow-ups" step plans for it instead of surprising you.
- Trust the risk ranking as your review map. Skim the LOW groups, read every line of the HIGH ones — that's where a rename quietly changes a contract.
- Pair it with a clean working tree and a branch. The test-and-type-check step is your proof the rename held; a clean diff makes the review (and the revert, if needed) trivial.
- Watch the casing trap:
OrderIdrarely lives in one form. Ask it to surface every casing variant in the grep step so you choose which to rename, rather than letting one slip through.