Skip to content
Back to skills

Refactor

ASecurity

Clean up and improve already-written code — simplification, reuse/DRY extraction, efficiency, language modernization, and architecture/layer hygiene. QUALITY-ONLY: this skill does NOT hunt for correctness bugs — use /code-review for that. It applies edits then verifies via format + test. TRIGGER when: the user wants to tidy, simplify, modernize, de-duplicate, or make changed code more reusable or efficient. DO NOT TRIGGER when: the user wants to hunt correctness/security/crash bugs (use /code...

  • 2 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 5, 2026
ai-agentsgobashawsrefactoringcode-reviewgitsecurityperformance

Security analysis

A100/100

Scanned September 24, 2026

npx -y skills add mik2win/foureyes --skill refactor --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Refactor?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Refactor
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/mik2win-refactor/badge)](https://www.skillsdirectory.com/skills/mik2win-refactor)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: refactor
disable-model-invocation: true
description: >-
  Clean up and improve already-written code — simplification, reuse/DRY extraction,
  efficiency, language modernization, and architecture/layer hygiene. QUALITY-ONLY: this
  skill does NOT hunt for correctness bugs — use /code-review for that. It applies edits
  then verifies via format + test.
  TRIGGER when: the user wants to tidy, simplify, modernize, de-duplicate, or make changed
  code more reusable or efficient.
  DO NOT TRIGGER when: the user wants to hunt correctness/security/crash bugs (use
  /code-review), scan the WHOLE codebase for rot/ball-of-mud hotspots (use /arch-health),
  or design a module's interface from scratch (use /codebase-design).
allowed-tools: Read, Grep, Glob, Bash, Edit, Agent
effort: high
---

# Refactor

Improve the quality of changed code WITHOUT changing its behavior. Pure refactor: same
inputs produce the same outputs. This skill APPLIES the cleanups, then runs the project's
`format` and `test` commands to confirm nothing broke. It does NOT look for bugs — for
correctness/security/crash analysis run `/code-review`.

---

## Phase 0 — Load profile

Read these before touching any code. They define every project fact this skill needs:

1. `.claude/PROJECT.md` — Commands (`format`, `lint`, `test`), Architecture (layers,
   boundaries, composition root), and any project-specific conventions.
2. `.claude/rules/_generic/*` — stack-agnostic rules (code quality, comments, naming). If
   `CONTEXT.md` exists, align names toward its ubiquitous language (a rename to the canonical
   term is behaviour-preserving and in scope).
3. Stack rule packs in `.claude/rules/*` whose `paths` (front-matter glob) match the
   target files. These carry the language- and framework-specific modernization and
   anti-pattern checks — do not hardcode any here; defer to them.

If `PROJECT.md` is missing or still `TEMPLATE`, fall back to the root `CLAUDE.md` (always
in context) when it carries the commands/architecture above — proceed on it, noting you're
running without a kit profile. Only if *neither* has those facts, tell the user to run
`/bootstrap` first, then stop.

---

## Phase 1 — Resolve target

`$ARGUMENTS` selects what to refactor:

- **file path** — that file.
- **directory** — all source files under it.
- **`staged`** — `git diff --cached --name-only` files.
- **range** (e.g. `main..HEAD`) — `git diff --name-only <range>` files.
- **plan/card file** — the files it scopes; the log goes back into it (see *Persist to the artifact*).
- **(empty, default)** — changed files: `git diff --name-only` plus
  `git diff --cached --name-only`. If none, ask the user what to refactor.

Read every target file in full before judging it. Match each file against the rule packs'
`paths` so you apply the right stack-specific checks per file.

---

## Phase 2 — Refactor dimensions

Apply these in order. Each is QUALITY-only; never alter observable behavior. Give every
candidate a verdict before it can become an edit: FIRST — it makes the change you are about to
make cheaper; AFTER — that change is done and this area is due again soon; LATER — real, no
payoff attached to today's work; NEVER — this behaviour is not changing again. Only FIRST and
AFTER are applied; the rest go to Output § Deferred. A first-of-its-kind mess is never LATER.

### D1 — Language modernization (per installed rules)
Apply the modern-idiom and anti-pattern checks defined in the matched stack rule packs
(control flow, data containers, I/O, exception/error handling, etc.). Do not invent
idioms — use only what the installed rules prescribe for this stack.

### D2 — Architecture & layer hygiene (per PROJECT.md)
- **Boundaries**: imports point inward only; no sibling-to-sibling coupling; cross-boundary
  wiring lives in the composition root named in PROJECT.md.
- **SRP**: each unit has one reason to change. If describing it needs "and" → split. First
  answer aloud whether a second use site exists and whether an alternative implementation does;
  neither → the split buys an interface and no depth, so leave it and say why.
- **Layer purity**: domain/business logic stays free of I/O, rendering, and framework calls
  per the layering in PROJECT.md; orchestration and presentation stay in their layers.
- **Boundary conversion**: external/raw responses are mapped to domain types at the adapter
  edge, not passed raw into inner layers.
- **Irremovable dependencies**: one you cannot remove is exposed in a single place, not buried —
  construction lifted into the constructor or one lazy accessor, a fragile external call wrapped.

### D3 — Function quality (per code-quality rule)
- **Size**: a limit passed is a look, not a cut — extract only at a seam where meaning and
  mechanics part ways and the split test holds (the piece reads without its caller, the caller
  without opening the piece); otherwise keep the function long and say why. Outputs include side
  effects: list the mutations before choosing the cut. Extract into the SAME unit first with an
  awkward name; moving it elsewhere is a separate step, and a branch moves with its condition.
- **Naming**: names state intent; rename the unclear.
- **Parameters**: 0–2 ideal; 3 acceptable; 4+ → group into a parameter object, and replacing two
  or more fields still pays. A flag is any argument every caller passes as a literal and the body
  branches on — enums and strings too, not a computed value; split the function. For an Extract
  Class cut, remove one member and note what became nonsense: that list, not the count, is it.
- **Guard clauses**: flatten nesting with an early return only when one leg is the unusual case
  AND nothing runs after the block — an audit call or a log after the `if` makes the flattening a
  behaviour change (Phase 3 rule 2 applies: confirm first).
- **Command/Query separation**: a unit either does something or returns something. The test is
  *observable* side effects — caching, memoisation and lazy initialisation pass it and are not
  violations; do not flag them.
- **Conditionals**: one that picks which object handles a case is fine; one that inspects a value
  and supplies behaviour on its behalf means a type is missing (a switch on the receiver's class,
  a `respond_to?` chain, an attribute named type/kind). Report what is missing, not "simplify".

### D4 — Duplication extraction (DRY)
Same logic, computation, or construction in 2+ places → extract to one shared unit at the lowest
layer both callers reach, per the architecture in PROJECT.md. Extract only what changes for the
same reason: identical bodies encoding two rules are coincidence, and two cases do not show the
axis of variation — name it, or wait for the third. Derive the abstraction, do not invent it: take
the two most alike cases, remove the single smallest difference, run the suite, repeat. Gates —
what does the merged version simplify (removing duplication is not itself a reason); which error
can it no longer raise loudly; does it read harder than the copies, and then stop. Judge by
result: one place to edit per behaviour, and a wrong abstraction gets dearer with every caller.
An abstraction already proved wrong is undone by procedure: inline it back into EVERY caller,
delete in each what its arguments show it never runs, then re-extract with all cases visible.
Before a stand-in object replaces a repeated null check, say what the absence means — "there is
none" and "there is one but unknown" differ; a site still asking "is this real?" guards instead.

### D5 — Dead-code removal
Delete unused imports/symbols, unreachable branches, commented-out code, and stale
TODO/FIXME/legacy/back-compat shims (MVP-stage projects keep no re-export stubs). Replace
magic numbers with named constants. Delete comments that merely narrate the code; keep only
non-obvious WHY. Confirm before deleting anything that could be a public/exported symbol or
a back-compat shim callers may rely on — never remove user-visible behaviour silently
(Phase 3 rule 2 applies). Before deleting an override or a field that may shadow a base one,
text-search the tree for a base definition of the same name: found → the deletion is a behaviour
change, not cleanup, and a green build proves nothing. When the complaint is "I can't follow
this", subtract before explaining and comment only what survives removal.

### D6 — Stack-specific dimensions
Apply every additional check defined in the installed stack rule packs matched in Phase 0
(framework patterns, data/ORM patterns, concurrency, domain invariants, etc.). These are
the source of truth for stack specifics — reference them generically, never duplicate them.

---

## Phase 3 — Apply & verify

0. **Confirm before writing.** Phases 1–2 produce a *proposed* cleanup list; this phase is the
   first that touches files. Show the list — file, what changes, why — and get the user's go
   before the first `Edit`. A refactor is a multi-site, judgment-bearing edit whose diff the user
   is expected to review as a whole, so the gate is *"apply these N?"*, not a per-edit prompt.
   Skip it only when the user's own request already named the exact change ("rename X to Y here").
1. **Apply** the cleanups with Edit, smallest safe steps first, running the tests after each
   step, never once at the end and never from a red bar. A step that reddens the suite and is not
   obvious in seconds is reverted to the last green and redone smaller — never debugged forward;
   a reverted step is a result, not a failure. The red reads exactly two ways: behaviour changed
   (revert), or the test asserted an interaction the refactor dissolved (fix the test, say so).
   Merge two units by making them textually identical first, one micro-change at a time; replace
   a stored value by running new beside old and asserting they agree at every read before
   deleting the old. Name each move before making it and its mirror after; name its abort
   condition first (`docs/decision-craft.md` §1). Replacing working code wholesale runs as the
   reversible sequence in `skills/tdd/refactoring.md` §Changing structure safely.
2. **Stay pure**: if a change could alter behavior, is ambiguous, or needs a judgment call
   (e.g. removing code that might be used by reflection, changing a public signature),
   STOP and ask the user instead of guessing. Defer rather than risk semantics.
3. **Format**: run the `format` command from PROJECT.md. If `format` is `n/a` (no
   formatter), skip and note it in the output.
4. **Test**: run the `test` command from PROJECT.md (scope to affected tests when the
   project supports it). If tests fail, the refactor changed behavior — revert the
   offending edit and report it. If a risky refactor lacks coverage, suggest `/test` first.
   If `test` is `n/a` (no suite at all), say so and lean harder on staying pure —
   recommend `/test` before any non-trivial refactor, since nothing else pins behavior.
   If the unit will not instantiate in a harness at all, read `skills/refactor/LEGACY.md` and
   follow it instead of widening this pass.

For large or multi-file targets, fan out reading/analysis with the Agent tool, then apply
edits yourself so changes stay coordinated.

---

## Output

Report concisely:

- **Changes by dimension** — what was cleaned up under each of D1–D6 (one line each).
- **Files touched** — absolute paths.
- **Verification** — `format` result and `test` result (pass/fail + summary).
- **Deferred** — anything skipped as risky/ambiguous or verdicted LATER/NEVER, with the reason.
- **Price** — what the pass cost as well as bought: more indirection, a worse metric, debts left.
  More complex than the problem it removed → revert; an invisible concept made visible still wins.

## Persist to the artifact

*(Mandatory when `$ARGUMENTS` or the session brief names a plan, card or spec file.)* Follow [`../implement/reference/work-log.md`](../implement/reference/work-log.md). Keep a ledger on disk from the first phase and record deviations the moment they are decided. Before the final reply, append `## Refactor Log — <date> — <verdict>` to that file; its `### Result` is the changes by dimension, each candidate's verdict (FIRST / AFTER / LATER / NEVER) with applied / left, and the price line. Anything you could not observe yourself goes under `Re-check later`, with its command and today's baseline: a post-deploy log grep, a soak count, a UI gesture. The chat output is a copy of the log, never the only record. No planning artifact → skip this section.

---

## Hard rules

- **Behaviour-preserving only.** Same inputs → same outputs. If a change could alter
  observable behaviour or is ambiguous, STOP and ask — defer rather than guess.
- **Never hunt bugs here.** Correctness/security/crash analysis is `/code-review`'s job.
- **Confirm destructive removals.** Don't silently delete exported symbols or back-compat
  shims callers may rely on.
- **Never trade structure for a guessed cost.** A cleanup that "looks slower" still ships —
  finish it, then take the doubt to `/perf` with a baseline, not to a watered-down move.
- **Verify, never publish.** Run `format` + `test`; never `git add`/`commit` — suggest the
  command, the user runs it.

---

## Cross-reference

- **`/code-review`** — finds correctness, security, and crash bugs. This skill does NOT;
  run it for bug hunting. The split mirrors the built-in taxonomy (`/code-review` = bugs,
  built-in `/simplify` = quality-only): this skill is the kit's PROJECT.md-aware
  counterpart of `/simplify`. When both passes run on the same diff, quality findings
  belong HERE and correctness findings there — never report the same issue from both.
- **`/test`** — add coverage BEFORE attempting a risky refactor so behavior is pinned.
- **`/perf`** — where a suspected performance cost goes, after the structure is clean.
- **`/arch-health`** — scans the WHOLE codebase for shallow modules & ball-of-mud
  hotspots and routes the one you pick here; this skill cleans the current diff on demand.
- **`/codebase-design`** — the deep-module vocabulary D2's architecture hygiene draws on
  when a boundary needs redesigning, not just tidying.
- **`/clean-mvp`** — whole-codebase cruft sweep (dead code, unused files, legacy shims);
  this skill's D5 removes dead code only within the current target.
- **`/distill`** — mines the whole repo's implicit conventions into project rules; this
  skill then *applies* those installed rules to the target diff (D1/D6 read them).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…