refactor
Refactor ไฟล์, workspace, หรือ codebase ตาม context — SRP, boundaries, style, consistency
SKILL.mdrefactor/SKILL.md
GitHubGoal
Restructure without changing observable behavior — every target carries file:line evidence, green before and green after, with the ### 1 baseline re-measured at ### 5
Scope
One scope at a time; several match → priority
skills>architecture>concerns/srp>structure(fix the boundary before the layout)
| Argument | Seen When | Run |
|---|---|---|
(none), @files..., srp |
file >250 lines, one unit holds several reasons to change, or new code that must start SRP-shaped | ### 3 file/SRP |
concerns |
one file mixes UI + logic + IO + config | ### 3 concerns |
structure |
naming, wrong folder, deep relative imports, barrel gaps | ### 3 structure |
workspace, monorepo (batch work), codebase |
many files, member boundaries, whole-repo pass | ### 2 plan → ### 3 batches |
shared |
duplication across packages | ### 3 shared |
orm |
raw SQL, scattered queries, N+1 | ### 3 orm |
architecture, clean, layered, monorepo (layout) |
wrong layers, boundaries, dependency direction, repo-level layout | ### 3 architecture → /follow-architecture |
skills |
the target is a skill package | /update-devin-global-skills refactor |
Out of scope here — handed off; every /skill mention below is either the related pipeline or this table:
| Out of scope | Owner |
|---|---|
| config drift | /update-config |
| hardcoded secret, URL, or magic string | /no-hard-code |
| ignore comment to remove | /no-use-ignore |
| shorter/clearer file, boundaries untouched | /simplify |
| event semantics, queue operations, transport | /improve events, /improve queues, /improve realtime |
| test suite work | /update-tests |
| pure file move, pure naming, batch pattern rewrite | /relocation, /rename, /use-astgrep rewrite |
| performance tuning | /deep-optimize |
| circular dependency graph | /follow-tool-madge |
| ORM setup, payload/schema validation boundary | /follow-lib-drizzle, /follow-tool-data-validation |
AGENTS.md, ast-grep rules, .devin/rules persistence |
/update-agents-md, /update-astgrep-rules, /update-devin-project-rules |
| error recovery, user decision, single-source convention | /resolve-errors, /ask-me, /follow-single-of-source |
Execute
1. Baseline And Evidence
Goal: start from green and name the targets with
file:line— never refactor on a broken or unmeasured baseline, never on a hunch
- Read the project
AGENTS.mdconventions (line cap, import alias, folder layout) before judging any structure; confirm a clean tree (git status) — pre-existing changes → record them first, so every diff below shows only this refactor - Run
/run-verify(lint, typecheck, test, build) FIRST — red → resolve to green before touching anything - Collect candidates into one table
file:line | smell | technique | scope:/check-long-files(size),/deep-reviewdimensioncode-quality(SRP, duplication, dead exports, complexity — it owns the detectors) and dimensionarchitecturefor a repo/package scope (itsN/A conditionis a single-file scope) - Read the table before planning: empty table and no new code → nothing to refactor, report and stop; new code only → jump to
### 3file/SRP with no baseline - Safety net: target's public behavior has no tests → run
/update-teststo lock current behavior with characterization tests - Record the baseline for the after-comparison:
git rev-parse HEAD(the sha### 5diffs against),/check-long-filesline counts,/deep-reviewfinding count, suite and lint status
2. Plan
Goal: know what moves and in what order before moving it
- Bulk scope (workspace/monorepo/codebase or several asks at once) → run
/create-plan-in-dot-devinwith the### 1table; a preparatory refactor before a feature goes in its own commit - Order the work before moving it: foundation → dependents within a chain, smallest reversible unit first, each item ending green on its own
- Not bulk but irreversible or wide-reaching (moves, splits, renames across call sites) → run
/report-before-afterfor the plan and expected before→after, which confirms before any edit - While planning run
/use-lib-effectiveto reuse existing deps and patterns before writing anything new — the### 1table is the evidence, plan from it instead of re-scanning - Before designing the target shape run
/follow-best-practicefor the stack the target lives in — the manifest's owner skills'best-practices/define the layout, API style, and error handling a refactored module must land on; cite the practice each structural decision follows - Architecture decision needed → plan it through
/follow-architecture(the architecture SSOT — pattern selection, Clean/Layered guides, monorepo layout, workspace file structures); still unclear → run/ask-me
3. Refactor
Goal: one unit = 1 reason to change; one technique per step →
/run-checkgreen → checkpoint commit; red → revert that step only
Technique matrix → ## Guide; take the technique from the ### 1 table before touching code:
file/SRP— group responsibilities by reason to change → Extract Method → Extract Class/Module → Move Method/Field; one content kind per file (types.ts/constants.ts/schema.tsor the domain name); keep the public API through a barrel so consumers don't change; new or just-written code (global rules## 1sends every create/update here) → judge the shape directly (1 reason to change, ≤250 lines, one content kind) with no baseline table; no real violation → stop (/dont-over-engineer)concerns— classify each block withfile:lineevidence (presentation/domain/data/io/config/orchestration) → extract leaf-first, one concern at a time, callers keep only orchestrationstructure— naming via/rename; >250-line or multi-responsibility files → item 1; folder >10–15 flat files → group by domain; relocate via/relocation(dry-run + confirm); public API through the barrel, alias imports instead of../../../workspace/monorepo/codebase— order foundation → dependents → applications; work one workspace/batch at a time with verify + checkpoint after each; independent files → parallel via/use-subagents(read in parallel, edit sequentially, no overlapping scope); nothing skipped silently — report anything not done with the reasonshared— extract only with ≥2 real consumers → the project's shared package or folder (packages/shared,src/shared), layer-correct leaf-first; rewire consumers one at a time via/update-references; verify the package is a leaf (/follow-tool-madge); coincidental similarity stays duplicatedorm— move data access onto the project's one type-safe ORM behind a repository boundary (interfaces use business types, never import the ORM); drizzle →/follow-lib-drizzle; boundary validation →/follow-tool-data-validationarchitecture— do not restructure layers here; run/follow-architectureand return for the file-level passes it exposes
4. Update References
Goal: no broken path or name remains after the restructure
- Run
/update-referencesfor paths/imports and global references, then prove the result:rg "<old-path>|<old-name>"returns no hit - Layout changed → run
/update-agents-md; a broken reference → run/resolve-errors
5. Verify After
Goal: prove behavior is unchanged vs the
### 1baseline
- Run
/run-verify+/deep-validateagainst the### 1baseline; red → back to### 3, max 3 rounds → stop and report the remaining gap - Prove the public surface did not move:
git diff <baseline-sha>on every barrel/indexin the change set, plus any new one fromgit status --short— an added, removed, or re-signatured export is a behavior change, not a refactor - Persist what was learned: a structural rule to keep → run
/update-astgrep-rules; a project convention → run/update-devin-project-rules; nothing reusable → say so and skip - Run
/reporton scope, changes and status with the before→after table against the### 1baseline — its### 4. Finalizealready routes the next action, so the next-action call is never duplicated
Guide
Smell → technique matrix. Detect with
file:lineevidence only; fix the cause, never mask the symptom; architecture-level smells →/deep-review+/follow-architectureinstead of a file refactor
| Smell | Technique |
|---|---|
| Long Method | Extract Method, Replace Loop with Pipeline |
| Large/God Class, Divergent Change | Extract Class/Module per reason to change |
| Duplicated Code | Extract Function/Module (rule of three) |
| Shotgun Surgery | Move to one owner — canonical source (/follow-single-of-source) |
| Feature Envy / Message Chain | Move Method/Field, Hide Delegate, Introduce Facade |
| Long Parameter List / Data Clumps | Introduce Parameter Object |
| Primitive Obsession / Data Class / Anemic Model | Replace with domain type, move behavior onto it |
| Switch Sprawl | Replace Conditional with Polymorphism / dispatch table |
| Speculative Generality / Lazy Class / Middle Man | Inline / collapse, call the real collaborator |
| Refused Bequest | Replace Inheritance with Composition |
| Temporal Coupling / Hidden Sequence | Combine into one unit, or make the order explicit at a single entry point |
| Comment Explains Bad Code | Extract Method / Rename so the comment becomes unnecessary |
| Dead Code | Remove after the code-quality dimension confirms no consumer |
Rules
- Evidence Before Structure — every target enters the work from the
### 1table withfile:line; a hunch is not a target, and an empty table ends the task - Preserve Behavior — structure only, never observable behavior; public API stays identical (proven at
### 5; Two Hats: a bug found mid-refactor gets its own fix commit first) - Safety Net First — never refactor uncovered code (enforced at
### 1); Small Steps — one technique per step, checkpoint every green batch - Minimal Change —
/dont-over-engineer; reuse > extend > extract > create (/use-lib-effective### 5internal reuse + dep leverage); no abstraction without a real consumer; no new dependency; never tune performance in a refactor pass - SRP And Consistency — 1 unit = 1 reason to change, 1 file = 1 concern ≤250 lines, 1 folder = 1 domain; naming/patterns/structure consistent across the scope; member public API is its barrel
- Best-Practice Shaped — the target shape comes from
/follow-best-practicefor the libs/framework in the change set (manifest owner skills'best-practices/), never from a personal preference; an invented pattern mid-refactor is a finding, not a refactor - Simple Design Order — works → communicates intent → no duplication → minimal elements, in that order
- Context Aware — never guess the scope: unclear →
/ask-me; destructive actions → dry run + confirm; every refactor ends green at### 5
Expected Outcome
- Every target traced to
file:lineevidence and closed: files/members sized right, one responsibility each, naming/patterns/structure consistent, imports/exports clean; code that global rules route here already starts that shape - Public surface identical — no barrel or index in the change set gains, loses, or re-signatures an export
- Architecture (when requested) applied through
/follow-architecture— pattern real in code, no circular deps; resulting shape matches the stack'sbest-practices/(via/follow-best-practice), every structural decision citing the practice it follows - No broken references;
/run-verify+/deep-validategreen vs baseline; recurring smells persisted as rules; before/after report delivered