summaryrefslogtreecommitdiff
path: root/dotfiles/common/.claude/commands/refactor.md
blob: 57acd5ee3bedf3bb47f3d4d50a9d51c677937f5b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
---
description: Scan code for refactoring opportunities or perform targeted refactoring operations
argument-hint: "[scope: full|quick|complexity|duplication|dead-code|rename old new]"
---

# /refactor — Code Refactoring Skill

Parse `$ARGUMENTS` to determine the operation:

| Argument | Description |
|----------|-------------|
| `full` (default) | Run all scans: complexity + duplication + dead code |
| `quick` | High-severity issues only (critical/high across all scans) |
| `complexity` | Analyze code complexity: nesting, length, parameters, boolean expressions |
| `duplication` | Detect duplicated logic, clone blocks, repeated patterns |
| `dead-code` | Find unused imports, exports, unreachable code, dead feature flags |
| `rename old new` | Codebase-wide symbol rename with verification |

If a file or directory path is included in the arguments, scope the scan to that path. Otherwise scan the project source directories (exclude vendored code, node_modules, build output, test fixtures).

---

## General Rules (All Modes)

- Refactoring changes structure, not behavior. If behavior changes, that is a fix, not a refactoring.
- Never refactor and add features in the same step.
- Run tests after each change to confirm behavior preservation.
- If tests are missing for the code being refactored, write characterization tests first.
- Commit each refactoring step individually with a message naming the specific transformation.
- Present findings to the user before making changes. Do not auto-apply without confirmation.

---

## Mode: Complexity

Scan for code that is too complex to maintain, test, or understand.

### What to Check

**Function length:**

| Lines | Severity | Action |
|-------|----------|--------|
| 1-30 | OK | — |
| 31-50 | Medium | Consider splitting |
| 51-100 | High | Split recommended |
| 101+ | Critical | Split required |

**Nesting depth:**

| Levels | Severity | Action |
|--------|----------|--------|
| 1-2 | OK | — |
| 3 | Medium | Consider flattening |
| 4+ | High | Refactor: guard clauses, extract method |

**Cyclomatic complexity** (count decision points: if, else if, else, case, for, while, catch, &&, ||):

| Score | Severity | Action |
|-------|----------|--------|
| 1-5 | OK | — |
| 6-10 | Medium | Consider simplifying |
| 11-15 | High | Refactor recommended |
| 16+ | Critical | Refactor required |

**Parameter count:**

| Params | Severity | Action |
|--------|----------|--------|
| 0-3 | OK | — |
| 4-5 | Medium | Consider parameter object |
| 6+ | High | Use parameter object or split function |

**Complex boolean expressions** (count operators in a single condition):

| Operators | Severity | Action |
|-----------|----------|--------|
| 1-2 | OK | — |
| 3-4 | Medium | Extract to named predicate |
| 5+ | High | Extract required |

### Detection Heuristics

Use Grep to find candidates:

- Long functions: Search for function/method definitions, then count lines to closing brace/end
- Deep nesting: Search for lines with 4+ levels of indentation inside control structures
- Complex conditions: Search for lines with 3+ `&&` or `||` operators
- Long parameter lists: Search for function signatures spanning 60+ characters in the parameter area

### Refactoring Strategies

Apply the simplest effective technique:

1. **Guard clauses** — Flatten nested if/else by returning early
2. **Extract method** — Pull a named function from a block that has a comment explaining it or that does a distinct sub-task
3. **Extract predicate** — Replace complex boolean expression with a named function returning bool
4. **Parameter object** — Group related parameters into a struct/type/alist
5. **Decompose conditional** — Replace if/else branches with named functions for each branch

---

## Mode: Duplication

Scan for duplicated code that violates DRY.

### What to Check

**Clone blocks** (nearly identical code in multiple places):

| Lines | Severity | Action |
|-------|----------|--------|
| 5-10 | Low | Consider extraction |
| 11-25 | Medium | Should extract |
| 26-50 | High | Must extract |
| 51+ | Critical | Extract immediately |

**Logic duplication** — Same algorithm with minor variations (different variable names, different field access, different types).

**Constant duplication** — Same magic number or string literal in 3+ places.

**Pattern repetition** — Same structural pattern (setup-execute-teardown, validate-process-respond) repeated across files.

**Error handling duplication** — Same try/catch or condition-case pattern repeated in many functions.

### Detection Heuristics

- Search for identical or near-identical multi-line blocks across files
- Search for the same string literal appearing in 3+ locations
- Search for functions with very similar names that suggest copy-paste origin
- Search for the same error message string in multiple places

### Refactoring Strategies

1. **Extract function** — Pull the duplicated block into a shared function with parameters for the varying parts
2. **Extract constant** — Replace magic numbers/strings with named constants
3. **Parameterize** — If two functions differ only in one value, merge into one function with a parameter
4. **Template method / higher-order function** — If the structure is the same but the operations differ, extract the structure and accept operations as arguments

---

## Mode: Dead Code

Find code that is never executed or referenced.

### Step-by-step

1. **Unused imports** — Use available tooling or grep for imports, then search for usage of each imported symbol. Language hints:
   - TypeScript/JS: `tsc --noUnusedLocals --noEmit`, or ESLint `no-unused-vars`
   - Python: `ruff check --select F401` or `pyflakes`
   - Go: compiler catches these automatically
   - Emacs Lisp: search for `(require 'X)` then grep for symbols from X
   - Rust: compiler warns on dead code

2. **Unused exports / public functions** — For each exported or public symbol, search the codebase for references. If zero references and not a public API entry point, flag it.

3. **Unreachable code** — Look for:
   - Code after unconditional return/throw/break/signal
   - Branches with conditions that are always true or always false
   - Functions defined but never called
   - Commented-out code blocks (these should be deleted; version control has the history)

4. **Dead feature flags** — Search for feature flag checks or environment variable guards. If the flag is always true/false in all environments, remove the dead branch.

5. **Unused dependencies** — Compare declared dependencies against actual imports. Flag packages with zero import references.

### Presentation

Group findings by category with confidence levels:
- **High confidence** — Definitely unused, safe to remove
- **Medium confidence** — Likely unused, needs manual review
- **Low confidence** — Possibly unused, dynamic references may exist

### Rules

- Never remove code used via dynamic imports, reflection, metaprogramming, or string-based references
- Preserve public API exports in libraries
- Skip test utilities, fixtures, and dev-only code unless explicitly asked
- Remove code in small, focused commits — one category per commit
- Never remove error handling or fallback code just because it hasn't triggered yet
- Run the full test suite after each removal batch

---

## Mode: Rename

Perform a codebase-wide symbol rename.

Parse `$ARGUMENTS` for: `rename <old-name> <new-name>`

### Step-by-step

1. **Determine symbol type** — Variable, function, class, type, file, directory, CSS class, config key.

2. **Find all references:**
   - Source code: imports, exports, usages, type references
   - Tests: descriptions, assertions, mocks, fixtures
   - Configuration: env vars, config files, build scripts
   - Documentation: comments, README, API docs, org files

3. **If renaming a file:**
   - Update all import/require paths referencing the old filename
   - Update dynamic imports or autoloads
   - Update config references (tsconfig paths, Makefile targets, load-path entries)

4. **Preview changes** — Show every file that will be modified with the specific line changes. Highlight ambiguous matches that might be false positives.

5. **Get confirmation** — Do not apply until the user approves.

6. **Apply changes** across all files in a single atomic commit.

7. **Verify** — Run tests and type checker / byte-compiler to confirm nothing broke.

### Rules

- Always preview before applying
- Handle case sensitivity: distinguish `myFunc`, `MyFunc`, `MY_FUNC`, `my-func`
- Do not rename inside vendored/dependency directories
- Preserve casing conventions (camelCase, PascalCase, snake_case, kebab-case)
- Check string literals that may reference the symbol (routes, error messages, logging)
- Update related names when appropriate (renaming `User` should prompt about `UserProps`, `UserSchema`, etc.)

---

## Output Format

For every finding in any scan mode, use this format:

```
[SEVERITY] Category — Title
File: path/to/file:line
Metric: specific measurement (e.g., "cyclomatic complexity: 18", "47 duplicated lines")
Issue: what the problem is (1-2 sentences)
Suggestion: recommended refactoring technique
```

Severity levels: `CRITICAL`, `HIGH`, `MEDIUM`, `LOW`

### After All Findings

Present a summary:

```
Refactoring Scan Summary
========================
Critical: N
High:     N
Medium:   N
Low:      N

Quick wins (low effort, high impact):
1. ...
2. ...
3. ...

Shall I apply any of these? (specify by number, or "all quick wins")
```

Do not generate a separate report file unless the user asks for one. Present findings inline in the conversation.