Swift refactor plan
Produce a complete written refactor plan for Swift or Objective-C code — rename, signature change, type extraction, protocol split, API migration — listing every site that will change (grouped by file with line numbers), the risks (overrides, conformances, @objc bridging, cross-module public API, test coverage), and the recommended execution path. Pure planning — makes zero edits. Use whenever the user wants to scope, preview, or estimate a Swift change before committing to it.From its SKILL.md
npx -y skills add drewalth/claude-xcindex --skill swift-refactor-planAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
8.4 KB, as published. Nobody here has run it
What this skill does
Builds a written plan for a Swift refactor. It does not edit code. The plan is what you hand to the user (or to swift-rename-symbol) so the actual edits can happen with full context.
A good plan answers four questions:
- What's the target? A specific symbol, or a file as a unit.
- What sites will change? Every reference, grouped by file and line.
- What can go wrong? Overrides, conformances,
@objcbridging, public API crossing module boundaries, missing test coverage. - How should it be executed? A specific recommended path —
swift-rename-symbol, manual edits in N files, or "this needs more design work first."
The xcindex MCP tools provide the raw data; this skill orchestrates the queries and turns the result into a plan.
How to use
Step 1 — Decide the target shape
The user's phrasing tells you whether the unit is a symbol or a file.
- "Rename
fetchUsertoloadUser" → symbol. - "What if I split
NetworkClient.swiftinto two files" → file. - "Migrate from
OldAuthAPItoNewAuthAPI" → multiple symbols (treat each separately, then aggregate).
If the user named only a file but the change is really about a symbol inside it
(e.g. "what if I change the signature of the function in Auth.swift"),
disambiguate before querying.
Step 2 — Gather data
Run only the queries that match the target shape. Skip anything irrelevant.
Symbol target:
find_symbol(symbolName: <name>)→ resolve to a USR. If multiple results, pick the one matching the user's stated module/kind, or ask.find_definition(usr: <usr from step 1>)→ confirm the definition site.find_references(symbolName: <name>, maxResults: 200)→ every reference.- If the symbol is a method or property:
find_overrides(usr: <usr from step 1>)— subclass overrides break silently if missed. - If the symbol is a protocol or protocol requirement:
find_conformances(usr: <usr from step 1>)— every conformer must update.
File target:
blast_radius(filePath: <abs path>)→directDependents,affectedFiles,coveringTests.- Optionally narrow per-symbol with
find_referencesfor the specific symbols inside the file the user is changing.
Step 3 — Surface risks
Walk the results and flag each of these that applies:
| Risk | Signal |
|---|---|
| Overrides | find_overrides returns ≥1 site — subclasses must change in lockstep. |
| Protocol conformances | find_conformances returns ≥1 site — every conformer must update. |
@objc bridging | find_references returns sites with .dynamic role — Objective-C call sites outside the index may exist. |
| Cross-module public API | Reference sites span multiple modules — downstream packages may break. |
| No covering tests | blast_radius.coveringTests is empty for the affected files — regression risk; recommend adding one before the change. |
| Stale index | MCP returned a freshness warning — note that the plan may be incomplete until the user rebuilds. |
A risk-free plan is fine — write "No notable risks" rather than inventing filler.
Step 4 — Write the plan
Use this exact structure so plans are skimmable and the user can act on them directly:
## Refactor plan: <one-line description>
**Target:** <symbol or file, with USR if applicable>
**Type:** <rename | signature change | extraction | migration | other>
**Total impact:** <N files, M reference sites>
### Sites by file
- `path/to/A.swift` (<count>)
- L<line> — <role: call | override | conformance | definition | test>
- L<line> — ...
- `path/to/B.swift` (<count>)
- ...
### Covering tests
- `path/to/ATests.swift`
- ...
(or "None — recommend adding test coverage before proceeding")
### Risks
- ⚠ <risk> — <one-sentence explanation>
- ✓ <thing-that-could-have-been-a-risk-but-isn't>
### Recommended execution
<one of:>
- Use `swift-rename-symbol` — dispatches the rename via the
swift-refactor-specialist subagent. Estimated subagent context: ~Xk tokens
(roughly: site count × 80 tokens/site + 200 tokens/file read).
- Manual edits in <list of files> — recommended when sites need
case-by-case judgment (e.g. some calls need migration shims).
- Pause and decide on <X> first — recommended when the plan surfaces a design
question the rename can't resolve (e.g. an `@objc` requirement, a behavior
change disguised as a rename).
Step 5 — Hand off
End your message by telling the user what's available next:
- "Want me to dispatch this to swift-rename-symbol?" (if the recommendation is the automated path)
- "Want me to start with
<file>so you can review the first edit?" (if manual) - "Want me to look at <X> before we decide?" (if paused)
Don't start editing on your own — this skill's job ends with the plan.
Example
User: "I'm thinking about renaming fetchUser to loadUser. What would
that touch?"
You:
find_symbol(symbolName: "fetchUser")→ one USR, inMyApp.UserService.find_references(symbolName: "fetchUser", maxResults: 200)→ 11 sites across 6 files.find_overrides(usr: "s:9MyApp11UserServiceC9fetchUserSiyF")→ 0 (it's a free function on the class).- Review the role of each site (calls vs definition).
## Refactor plan: rename `UserService.fetchUser` → `loadUser`
**Target:** `s:9MyApp...fetchUserSiF` (UserService.fetchUser)
**Type:** rename
**Total impact:** 6 files, 11 sites
### Sites by file
- `Sources/UserService.swift` (2)
- L42 — definition
- L67 — internal call
- `Sources/AuthFlow.swift` (3)
- L18, L24, L91 — calls
- `Sources/ProfileViewModel.swift` (2)
- L33, L120 — calls
- `Tests/UserServiceTests.swift` (3)
- L12, L45, L88 — calls
- `Tests/AuthFlowTests.swift` (1)
- L23 — call
### Covering tests
- `Tests/UserServiceTests.swift`
- `Tests/AuthFlowTests.swift`
### Risks
- ✓ No subclass overrides.
- ✓ No protocol conformance — it's a concrete method.
- ✓ Not `@objc` — no Objective-C bridging surface.
- ✓ Tests cover both the direct method and one downstream caller.
### Recommended execution
Use `swift-rename-symbol` — straightforward rename, all sites are direct calls,
test coverage is solid. Estimated subagent context: ~2k tokens.
"Want me to dispatch this to swift-rename-symbol?"
When this skill won't help
- The user has already committed and just wants action — go to
swift-rename-symboldirectly. - The change is a pure behavior change inside a single function with no API surface — there's nothing to plan; just edit.
- The user is asking a textual question ("how many places say
TODO?") — that's Grep, not the index.
Related skills
- swift-rename-symbol — the execution path this plan often recommends.
- swift-find-references — the underlying query for symbol-level sites; use it directly when the user only wants the reference list.
- swift-blast-radius — the underlying query for file-level impact; use it directly when the user only wants the affected-files set.