From craft
Detection lens for Fowler's five smell families — names the smell, states the change-cost, and hands the fix to `refactoring-patterns`. Use when reviewing a diff, auditing a module, or deciding whether to gate a merge. Triggers: "does this code have smells", "review for smells", "is this clean", "what's wrong with this design", "this class is getting big", "why is every change touching 12 files", "switch on type", "this method is too long", "is this AI slop".
How this skill is triggered — by the user, by Claude, or both
Slash command
/craft:code-smellsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Purpose**: a code smell is a surface symptom of a deeper change-cost problem —
Purpose: a code smell is a surface symptom of a deeper change-cost problem —
the code runs, but it will cost more to modify than it should. This skill is the
detection lens: it names the smell, states the economic cost, and hands the fix
to refactoring-patterns. The two signature AI-slop smells are Duplicate Code
(agents clone instead of consolidating) and Speculative Generality (agents add
abstraction "just in case"). Hunt these first on any AI-generated diff.
Relationship:
code-smells(detect / judge severity) →refactoring-patterns(apply the fix) →dependency-analyzer(confirm coupling reach) →complexity-analysis(quantify cognitive load). Don't apply fixes in this skill; route them.
Scan the diff by Fowler family. One tell each:
Bloaters (grown too large)
null or false for half the params.string/int standing in for a domain concept (email, money, userId). Tell: repeated validation of the same raw value at every call site.OO Abusers (OO used wrongly)
6. Switch-on-type — a switch/if-chain on a type tag, repeated in multiple places. Tell: adding a new type means hunting for every switch in the codebase.
Change Preventers (one change → many edits) 7. Divergent Change — one class changes for many unrelated reasons. Tell: the git log for this file touches pricing, auth, and email in the same commits. 8. Shotgun Surgery — one logical change means edits scattered across many files. Tell: a single PR touches 10 files to add one feature.
Dispensables (code that should not exist)
9. Duplicate Code — the same structure in multiple places. Tell: identical or near-identical blocks; same bug fixed in two places. AI signature smell.
10. Speculative Generality — "we might need it" hooks, abstract base with one implementation, config option never varied. Tell: deleting the abstraction loses nothing. AI signature smell.
11. Dead Code — unused vars, params, methods, branches. Tell: grep finds no callers; IDE grays it out.
Couplers (too much coupling)
12. Feature Envy — a method that uses another object's data more than its own. Tell: most lines in the method start with other.get….
13. Message Chains — a.getB().getC().getD(). Tell: a chain you can't mock without building half the object graph. Violates Law of Demeter.
Rank findings by job-damage × fix-cheapness — don't dump everything equally:
A smell is a prompt to investigate, not an automatic defect. Sometimes the smelly
code is the right code — a switch on an external enum you don't own, duplication
that's cheaper than a wrong abstraction. Name the smell, state the cost, then let
severity decide whether it blocks the merge.
switch (event.type) or if (user.role === 'admin') repeated in three files.order.getCustomer().getAddress().getCity() — Law of Demeter chain.boolean parameter (processOrder(order, true, false, null)).lat, lng, zoom) passed in separate params everywhere.abstract/interface with exactly one implementing class, or an Optional-style base with one consumer.file:line — be specific. "Long Method" at order_service.py:87 is actionable. "The code is messy" is not.# BEFORE — smell: Switch-on-type (OO Abuser) repeated in renderer and serializer
def render(shape):
if shape.type == 'circle':
return draw_circle(shape.radius)
elif shape.type == 'rect':
return draw_rect(shape.w, shape.h)
elif shape.type == 'triangle':
return draw_triangle(shape.points)
# every new shape type → edit this function AND the serializer
# AFTER — polymorphic dispatch; adding a shape touches one place
RENDERERS = {
'circle': lambda s: draw_circle(s.radius),
'rect': lambda s: draw_rect(s.w, s.h),
'triangle': lambda s: draw_triangle(s.points),
}
def render(shape):
renderer = RENDERERS.get(shape.type)
if renderer is None:
raise ValueError(f"Unknown shape type: {shape.type!r}")
return renderer(shape)
Fix via refactoring-patterns: Replace Conditional with Polymorphism (or dict dispatch
for simple cases). If this switch appears in three files, that's Shotgun Surgery layered
on top — escalate severity.
For each smell found, emit a tagged finding:
[code-smells · shotgun-surgery · SEV:HIGH] order_service.py:87 and email_sender.py:34
and pdf_export.py:112 all change when a new OrderStatus is added. Consolidate status
handling into one module. → refactoring-patterns: Move Method + Extract Class.
Tag format: [code-smells · <smell-kebab-case> · SEV:(HIGH|MED|LOW)]. SEV:HIGH =
Change Preventers and AI-slop core. SEV:MED = Bloaters and Couplers on hot paths.
SEV:LOW = cosmetics and isolated dispensables.
Lead every review with the highest-SEV finding. Close with a one-line verdict: "3 findings: 1 HIGH (Shotgun Surgery), 1 MED (Long Method), 1 LOW (Dead Code). HIGH blocks merge."
../../references/SMELLS.md../../references/PRINCIPLES.md../../RULES.mdrefactoring-patterns skill — this skill detects; that skill applies.npx claudepluginhub manutej/craftProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.