refactor-codebase
Refactor a whole codebase in one run, tuned to clear the layered debt AI-written code piles up, so a typical change lands in one place. Worth running regularly.
Try your first task
A source-grounded starter task has not been verified for this skill yet.
SKILL.md
name: refactor-codebasedescription: Refactor a whole codebase in one run, tuned to clear the layered debt AI-written code piles up, so a typical change lands in one place. Worth running regularly.disable-model-invocation: trueRefactor Codebase
Refactor this whole codebase until a typical change lands in one place. Treat this as a goal and run it to the end. If I named an area, start there.
Ask one question of everything: should these pieces change together? The code gets the answer wrong in three ways:
- Hidden links — pieces that must change together, where nothing shows it: copied logic or values, a module reading state another module sets, one feature spread across folders by layer, a call order callers just have to know.
- Needless links — pieces tied together that change for different reasons: callers reaching into internals, stable code importing volatile code, a general function with a parameter only one caller understands, a shallow module whose interface changes whenever its internals do.
- Surplus — pieces with no reason of their own to change: pass-through wrappers, extension points and config for things that never vary, dead code.
Workflow
-
List every problem before changing anything. Go through the whole codebase and write down each place it gets the question wrong. List every special case too: an
iffor one value, a parameter for one caller, a swallowed exception, a retry or sleep, a disabled test. Each one is a requirement the design never accounted for. Have subagents run the specialist hunts and add what they report, changing nothing yet: find-state-machines for one lifecycle spread across flags, effects and callbacks, find-overengineering for guards and fallbacks nothing needs, and ratchet-files for files too big to read whole. To reason across all of it at once, script a skeleton with the function bodies stripped and a graph of what imports what, and use git history as evidence of what really changes together. Keep the list in a file so it survives compaction. -
Redesign from the list. Work out the system as if it had known today's requirements from the start. Look for the one fix behind several problems; it often looks nothing like them. Never patch special cases one by one. Write each fix above the problems it removes:
- Make `Dialog` give focus back to whatever had it before it opened. - `LogoutDialog` waits 100ms after closing and hopes the input can take focus. - `SettingsDialog` sets a global `skipRefocus` flag to stop that refocus. - Make every user action one command with a name, a handler and an undo. - Toolbar and menu call the same actions, each with its own disabled check. - The keymap has a switch with one case per action. - The command palette keeps its own action list, missing the newer ones. - Undo has a special case for every action.Each fix is one mechanism that lands as one commit. Land nothing until the list is only fixes: every problem and special case sits under the fix that removes it, or under Kept with the reason the system still needs it.
-
Land one fix at a time, each time the one that removes the most of what is left; it often makes smaller ones moot. Follow refactor-change for each, then audit its diff with code-review and fix what it finds. Commit each fix on its own with the project's checks passing, and name any behavior it changes in the commit message, so a behavior change traces to one fix. Tests are the safety net here, so leave them alone until step 5.
-
Search again. Have fresh subagents hunt for hidden links, needless links, surplus and special cases, rerun the specialist hunts, and return to step 1 with what they find.
-
Audit the tests. Once the search comes back empty, run audit-tests over the suites the refactor touched, and land what it finds the same way.
Done when subagents find nothing worth fixing, a typical change lands in one place, nothing imports anything more volatile than itself, every test earns its keep, and behavior is the same as when you started, apart from bugs the refactor fixed. The number of special cases left is the best measure of how close you are.