Multi-File Refactor
Quick Start
Systematic, token-efficient multi-file refactoring with safety checks. Enforces MultiEdit for 2+ changes per file (30-50% token savings vs sequential Edit).
Most common use case:
User: "Rename function search_code to find_code across the codebase" → Discover all occurrences (Grep) → Plan changes (group by file) → Execute with MultiEdit (2+ changes per file) → Update imports/references → Validate (run tests, quality gates) Result: Clean refactor with no broken references
When to Use This Skill
Primary triggers:
- •"Rename function/class/variable across codebase"
- •"Refactor pattern X to pattern Y"
- •"Extract common code to shared module"
- •"Move functionality from A to B"
- •"Update all usages of X"
Contextual triggers (agent detection):
- •Multiple files need same change
- •Function/class used in 3+ files
- •Pattern repeats across modules
- •Cross-file dependency changes
When NOT to use:
- •Single file changes (use Edit directly)
- •Simple find-replace (use Edit with replace_all)
- •Trivial changes (1-2 total edits)
What This Skill Does
Core capabilities:
- •Discovery & Analysis - Find all affected files using Grep/Glob
- •Change Planning - Group changes by file, identify dependencies
- •Token-Efficient Execution - Use MultiEdit for 2+ changes (30-50% savings)
- •Import/Reference Updates - Fix broken imports and references
- •Validation - Run tests and quality gates
- •Reporting - Document changes and validation results
Refactoring Workflow
Phase 1: Discovery & Analysis
Find all affected files:
# Search for function/class usage grep -r "search_code" src/ --include="*.py" # Or use Grep tool pattern: "search_code" path: src/ output_mode: files_with_matches
Analyze impact:
- •Count occurrences per file
- •Identify import statements
- •Find documentation references
- •Check test files
Phase 2: Change Planning
Group changes by file:
File: src/handlers.py (3 changes) - USE MULTIEDIT File: src/repository.py (2 changes) - USE MULTIEDIT File: tests/test_search.py (5 changes) - USE MULTIEDIT File: README.md (1 change) - USE EDIT
Determine execution order:
- •Core implementation files first
- •Dependent files next
- •Tests last
- •Documentation last
Phase 3: Execution
Token optimization rules:
Rule 1: ALWAYS Use MultiEdit for 2+ Edits
# ❌ BAD: Sequential Edit (wastes tokens)
Edit(file="handlers.py", old_string="search_code(query)", new_string="find_code(query)")
Edit(file="handlers.py", old_string="def search_code", new_string="def find_code")
Edit(file="handlers.py", old_string="search_code_handler", new_string="find_code_handler")
# ✅ GOOD: Single MultiEdit (30-50% token savings)
MultiEdit(file="handlers.py", edits=[
{"old_string": "search_code(query)", "new_string": "find_code(query)"},
{"old_string": "def search_code", "new_string": "def find_code"},
{"old_string": "search_code_handler", "new_string": "find_code_handler"}
])
Rule 2: Group Changes by File
- •One MultiEdit call per file
- •Include ALL changes for that file
- •Read file first to verify changes
Rule 3: Read Before Modifying
# Always read first Read(file_path="src/handlers.py") # Then modify MultiEdit(file="src/handlers.py", edits=[...])
Rule 4: Batch Independent Operations
- •Run Read calls in parallel
- •Run MultiEdit calls in parallel (if files independent)
- •Run validation commands sequentially
Phase 4: Import & Reference Updates
Update import statements:
# If function moved or renamed
# OLD: from src.handlers import search_code
# NEW: from src.handlers import find_code
MultiEdit(file="src/app.py", edits=[
{"old_string": "from src.handlers import search_code",
"new_string": "from src.handlers import find_code"}
])
Check for broken references:
# Verify old name doesn't exist grep -r "search_code" src/ --include="*.py" # Should return empty or only comments/strings
Phase 5: Validation
Run quality gates:
# Type checking mypy src/ # Linting ruff check src/ # Tests pytest tests/ # All must pass before considering refactor complete
Manual verification:
- •Test in running application
- •Check logs for errors
- •Verify documentation updated
Phase 6: Reporting
Generate refactor report:
## Refactor Report: search_code → find_code ### Files Modified: 8 - src/handlers.py (3 changes) - src/repository.py (2 changes) - src/models.py (1 change) - tests/test_search.py (5 changes) - tests/test_repository.py (2 changes) - tests/conftest.py (1 change) - README.md (1 change) - docs/API.md (1 change) ### Changes Made: - Function renamed: search_code → find_code - Imports updated: 6 files - Tests updated: 3 files - Documentation updated: 2 files ### Validation: ✅ mypy: 0 type errors ✅ ruff: 0 linting errors ✅ pytest: 42/42 tests passing ✅ grep verification: No old references found Status: COMPLETE
Common Refactoring Patterns
Pattern 1: Function/Method Rename
# 1. Find all usages grep -r "old_function_name" src/ # 2. Plan changes (group by file) # 3. Execute with MultiEdit per file # 4. Update imports # 5. Run tests
Pattern 2: Class Rename
# Additional considerations: # - Update class definition # - Update all instantiations # - Update type hints # - Update docstrings # - Update imports
Pattern 3: Module/File Move
# 1. Move file: mv old/path.py new/path.py # 2. Update all imports referencing old path # 3. Update relative imports in moved file # 4. Run tests
Pattern 4: Extract Common Code
# 1. Create new shared module # 2. Move common code to new module # 3. Update original files to import from new module # 4. Remove duplicate code # 5. Run tests
Pattern 5: API Signature Change
# Example: Add parameter to function # 1. Update function definition # 2. Update all call sites (add new parameter) # 3. Update tests # 4. Update documentation
Language-Specific Guidance
Python
- •Update
__init__.pyimports - •Fix relative imports (from . import X)
- •Update type hints
- •Check for dynamic imports (importlib)
JavaScript/TypeScript
- •Update named imports:
import { oldName } from 'module' - •Update default imports:
import oldName from 'module' - •Update require statements:
const oldName = require('module') - •Update type definitions (.d.ts files)
Java
- •Update package imports
- •Update fully qualified names
- •Rebuild project (Maven/Gradle)
- •Update XML configuration files
Go
- •Update package imports
- •Run
go mod tidy - •Update interface implementations
- •Run
go build
Validation Checklist
After refactoring, verify:
- • All quality gates passing (mypy, ruff, pytest)
- • No grep results for old name (except comments/strings if intended)
- • All imports updated
- • Tests passing (unit, integration, E2E)
- • Documentation updated (README, API docs)
- • No broken references in other files
- • Application runs without errors
- • Logs show no warnings/errors
Anti-Patterns to Avoid
- •Sequential Edit on Same File - Use MultiEdit for 2+ changes (30-50% token savings)
- •Blind Editing Without Reading - Always Read file first to verify context
- •Skipping Tests - Tests catch broken references immediately
- •Ignoring Quality Gates - Type errors indicate missed references
- •Forgetting Imports - Broken imports cause runtime errors
- •Incomplete Refactoring - Leaving old name in some files creates confusion
- •Wrong Dependency Order - Update core files before dependent files
Edge Cases & Troubleshooting
Pattern in Strings/Comments
Issue: Grep finds occurrences in strings/comments that shouldn't be changed
Solution:
- •Review grep results manually
- •Exclude string/comment matches from changes
- •Use more specific search patterns (e.g.,
def search_codeinstead of justsearch_code)
Partial Matches
Issue: "search_code" also matches "search_code_advanced"
Solution:
- •Use word boundaries in grep:
\bsearch_code\b - •Review all matches before changing
- •Use more specific old_string in Edit/MultiEdit
Tests Failing After Refactor
Issue: Tests fail with "NameError" or "ImportError"
Diagnosis:
# Check for old references grep -r "old_name" tests/ # Check import statements grep -r "from.*import.*old_name" tests/
Solution:
- •Update test imports
- •Update test fixture names
- •Update mock/patch references
MultiEdit Conflicts
Issue: MultiEdit fails with "overlapping edits" or "string not found"
Diagnosis:
- •Edits are in wrong order
- •String changed between Read and MultiEdit
- •old_string not unique
Solution:
- •Ensure old_strings are unique
- •Order edits top-to-bottom in file
- •Re-read file if it changed
Expected Outcomes
Successful Refactor
## Refactor Complete Files Modified: 12 Total Changes: 37 Token Efficiency: 45% savings (MultiEdit vs Edit) Validation: ✅ Type checking: 0 errors ✅ Linting: 0 issues ✅ Tests: 87/87 passing ✅ Verification: No old references Status: READY TO COMMIT
Failed Validation
## Refactor Failed Validation Files Modified: 12 Total Changes: 37 Validation: ❌ Tests: 3 failures - test_search_handler: ImportError: cannot import 'search_code' - test_repository: NameError: 'search_code' not defined ❌ Grep verification: 2 old references found - src/cache.py:45: search_code_cache - tests/conftest.py:12: mock_search_code Action Required: 1. Fix remaining imports in test files 2. Update cache.py reference 3. Update conftest.py fixture 4. Re-run validation Status: BLOCKED
Supporting Files
- •references/refactoring-patterns.md - Comprehensive guidance:
- •Detailed refactoring patterns (10+ scenarios)
- •Language-specific best practices (Python, JS/TS, Java, Go, Rust)
- •Token optimization calculations and examples
- •Advanced edge cases and solutions
- •Quality gate configuration details
Red Flags to Avoid
- •Using Edit for 2+ changes - Wastes 30-50% tokens
- •Skipping Read before Edit - Causes edit failures
- •Incomplete refactoring - Partial changes break codebase
- •Ignoring test failures - Broken references in production
- •Not verifying old references gone - grep should return empty
- •Forgetting documentation - README/API docs out of sync
- •Skipping quality gates - Type errors indicate missed updates
- •Wrong execution order - Dependencies before dependents causes failures
Key principle: Token-efficient refactoring uses MultiEdit for 2+ changes (30-50% savings) while maintaining safety through validation.
Remember: 10 minutes of systematic refactoring prevents hours of debugging broken references.