Use when refactoring code - test-preserving transformations in small steps, running tests between each change
/plugin marketplace add withzombies/hyperpowers/plugin install withzombies-hyper@withzombies-hyperThis skill inherits all available tools. When active, it can use any tool Claude has access to.
resources/example-session.mdresources/refactoring-patterns.md<skill_overview> Refactoring changes code structure without changing behavior; tests must stay green throughout or you're rewriting, not refactoring. </skill_overview>
<rigidity_level> MEDIUM FREEDOM - Follow the change→test→commit cycle strictly, but adapt the specific refactoring patterns to your language and codebase. </rigidity_level>
<quick_reference>
| Step | Action | Verify |
|---|---|---|
| 1 | Run full test suite | ALL pass |
| 2 | Create bd refactoring task | Track work |
| 3 | Make ONE small change | Compiles |
| 4 | Run tests immediately | ALL still pass |
| 5 | Commit with descriptive message | History clear |
| 6 | Repeat 3-5 until complete | Each step safe |
| 7 | Final verification & close bd | Done |
Core cycle: Change → Test → Commit (repeat until complete) </quick_reference>
<when_to_use>
Don't use for:
<the_process>
BEFORE any refactoring:
# Use test-runner agent to keep context clean
Dispatch hyperpowers:test-runner agent: "Run: cargo test"
Verify: ALL tests pass. If any fail, fix them FIRST, then refactor.
Why: Failing tests mean you can't detect if refactoring breaks things.
Track the refactoring work:
bd create "Refactor: Extract user validation logic" \
--type task \
--priority P2
bd edit bd-456 --design "
## Goal
Extract user validation logic from UserService into separate Validator class.
## Why
- Validation duplicated across 3 services
- Makes testing individual validations difficult
- Violates single responsibility
## Approach
1. Create UserValidator class
2. Extract email validation
3. Extract name validation
4. Extract age validation
5. Update UserService to use validator
6. Remove duplication from other services
## Success Criteria
- All existing tests still pass
- No behavior changes
- Validator has 100% test coverage
"
bd update bd-456 --status in_progress
The smallest transformation that compiles.
Examples of "small":
NOT small:
Example:
// Before
fn create_user(name: &str, email: &str) -> Result<User> {
if email.is_empty() {
return Err(Error::InvalidEmail);
}
if !email.contains('@') {
return Err(Error::InvalidEmail);
}
let user = User { name, email };
Ok(user)
}
// After - ONE small change (extract email validation)
fn create_user(name: &str, email: &str) -> Result<User> {
validate_email(email)?;
let user = User { name, email };
Ok(user)
}
fn validate_email(email: &str) -> Result<()> {
if email.is_empty() {
return Err(Error::InvalidEmail);
}
if !email.contains('@') {
return Err(Error::InvalidEmail);
}
Ok(())
}
After EVERY small change:
Dispatch hyperpowers:test-runner agent: "Run: cargo test"
Verify: ALL tests still pass.
If tests fail:
git restore src/file.rsNever proceed with failing tests.
Commit each safe transformation:
Dispatch hyperpowers:test-runner agent: "Run: git add src/user_service.rs && git commit -m 'refactor(bd-456): extract email validation to function
No behavior change. All tests pass.
Part of bd-456'"
Why commit so often:
Repeat steps 3-5 for each small transformation:
1. Extract validate_email() ✓ (committed)
2. Extract validate_name() ✓ (committed)
3. Extract validate_age() ✓ (committed)
4. Create UserValidator struct ✓ (committed)
5. Move validations into UserValidator ✓ (committed)
6. Update UserService to use validator ✓ (committed)
7. Remove validation from OrderService ✓ (committed)
8. Remove validation from AccountService ✓ (committed)
Pattern: change → test → commit (repeat)
After all transformations complete:
# Full test suite
Dispatch hyperpowers:test-runner agent: "Run: cargo test"
# Linter
Dispatch hyperpowers:test-runner agent: "Run: cargo clippy"
Review the changes:
# See all refactoring commits
git log --oneline | grep "bd-456"
# Review full diff
git diff main...HEAD
Checklist:
Close bd task:
bd edit bd-456 --design "
... (append to existing design)
## Completed
- Created UserValidator class with email, name, age validation
- Removed duplicated validation from 3 services
- All tests pass (verified)
- No behavior changes
- 8 small transformations, each tested
"
bd close bd-456
</the_process>
<examples> <example> <scenario>Developer changes behavior while "refactoring"</scenario> <code> // Original code fn validate_email(email: &str) -> Result<()> { if email.is_empty() { return Err(Error::InvalidEmail); } if !email.contains('@') { return Err(Error::InvalidEmail); } Ok(()) }// "Refactored" version fn validate_email(email: &str) -> Result<()> { if email.is_empty() { return Err(Error::InvalidEmail); } if !email.contains('@') { return Err(Error::InvalidEmail); } // NEW: Added extra validation if !email.contains('.') { // BEHAVIOR CHANGE return Err(Error::InvalidEmail); } Ok(()) } </code>
<why_it_fails>
What you gain:
$ cargo test ... 23 test failures ...
<why_it_fails>
If test fails:
What you gain:
// Developer refactors without tests: // - Extracts 5 methods // - Renames variables // - Simplifies conditionals // - "Looks good to me!"
// Deploys to production // 💥 Payments fail for amounts over $1000 // Edge case handling was accidentally changed </code>
<why_it_fails>
Write tests FIRST (using hyperpowers:test-driven-development)
Then refactor with tests as safety net
Tests catch any behavior changes immediately
What you gain:
<refactor_vs_rewrite>
Rule: If you need to change test assertions (not just add tests), you're rewriting, not refactoring.
When to use:
How it works:
Example:
Legacy: Monolithic user service (50K LOC)
Goal: Microservices architecture
Step 1 (Transform):
- Create new UserService microservice
- Implement user creation endpoint
- Tests pass in isolation
Step 2 (Coexist):
- Add routing layer (façade)
- Route POST /users to new service
- Route GET /users to legacy service (for now)
- Monitor both, compare results
Step 3 (Eliminate):
- Once confident, migrate GET /users to new service
- Remove user creation from legacy
- Repeat for remaining endpoints
Benefits:
Use refactoring within components, Strangler Fig for replacing systems. </refactor_vs_rewrite>
<critical_rules>
All of these mean: Stop and return to the change→test→commit cycle
<verification_checklist> Before marking refactoring complete:
Can't check all boxes? Return to process and fix before closing bd task. </verification_checklist>
<integration> **This skill requires:** - hyperpowers:test-driven-development (for writing tests before refactoring if none exist) - hyperpowers:verification-before-completion (for final verification) - hyperpowers:test-runner agent (for running tests without context pollution)This skill is called by:
Agents used:
When stuck:
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.