
Code Smell Detector
- 241 installs
- 70 repo stars
- Updated July 26, 2026
- rysweet/amplihack
code-smell-detector is an amplihack Claude Code skill that scans changed code for smells including long methods, duplication, tight coupling, and dead paths, then produces prioritized refactor guidance before merge or re
About
code-smell-detector is an amplihack quality skill that analyzes diffs and changed files for structural problems that inflate maintenance cost. The skill flags long methods, duplicated logic, tight coupling between modules, and unreachable dead paths, then ranks findings so reviewers address the highest-impact refactors first. Engineering teams reach for code-smell-detector before merge or release when automated linting misses architectural debt visible only in change scope. Output is prioritized refactor guidance suitable for pull request comments, pre-merge checklists, and release readiness reviews rather than greenfield feature design.
- Flags common structural and naming anti-patterns
- Prioritizes fixes by maintenance risk
- Suggests targeted refactors over blanket rewrites
- Works across frontend and backend modules
- Supports cleaner merges and long-term velocity
Code Smell Detector by the numbers
- 241 all-time installs (skills.sh)
- +1 installs in the week ending Jul 26, 2026 (Skillselion tracking)
- Ranked #310 of 1,354 Code Review & Quality skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/rysweet/amplihack --skill code-smell-detectorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 241 |
|---|---|
| repo stars | ★ 70 |
| Last updated | July 26, 2026 |
| Repository | rysweet/amplihack ↗ |
How do you detect code smells before merging a PR?
Scan changed code for smells—long methods, duplication, tight coupling, dead paths—and produce prioritized refactor guidance before merge or release.
Who is it for?
Developers reviewing pull requests or pre-release diffs who need prioritized smell detection beyond linter rule violations.
Skip if: Greenfield prototyping with no changed code to scan or teams needing OAuth, infra, or marketing guidance instead of refactor review.
When should I use this skill?
The user wants code smell analysis, refactor prioritization, or pre-merge quality review on changed files.
What you get
Prioritized smell report, refactor recommendations per finding, and merge-readiness quality assessment.
- Prioritized smell report
- Refactor recommendation list
- Merge-readiness assessment
Files
Code Smell Detector Skill
Purpose
This skill identifies anti-patterns that violate amplihack's development philosophy and provides constructive, specific fixes. It ensures code maintains ruthless simplicity, modular design, and zero-BS implementations.
When to Use This Skill
- Code review: Identify violations before merging
- Refactoring: Find opportunities to simplify and improve code quality
- New module creation: Catch issues early in development
- Philosophy compliance: Ensure code aligns with amplihack principles
- Learning: Understand why patterns are problematic and how to fix them
- Mentoring: Educate team members on philosophy-aligned code patterns
Core Philosophy Reference
Amplihack Development Philosophy focuses on:
- Ruthless Simplicity: Every abstraction must justify its existence
- Modular Design (Bricks & Studs): Self-contained modules with clear connection points
- Zero-BS Implementation: No stubs, no placeholders, only working code
- Single Responsibility: Each module/function has ONE clear job
Code Smells Detected
1. Over-Abstraction
What It Is: Unnecessary layers of abstraction, generic base classes, or interfaces that don't provide clear value.
Why It's Bad: Violates "ruthless simplicity" - adds complexity without proportional benefit. Makes code harder to understand and maintain.
Red Flags:
- Abstract base classes with only one implementation
- Generic helper classes that do very little
- Deep inheritance hierarchies (3+ levels)
- Interfaces for single implementations
- Over-parameterized functions
Example - SMELL:
# BAD: Over-abstracted
class DataProcessor(ABC):
@abstractmethod
def process(self, data):
pass
class SimpleDataProcessor(DataProcessor):
def process(self, data):
return data * 2Example - FIXED:
# GOOD: Direct implementation
def process_data(data):
"""Process data by doubling it."""
return data * 2Detection Checklist:
- [ ] Abstract classes with only 1-2 concrete implementations
- [ ] Generic utility classes that don't encapsulate state
- [ ] Type hierarchies deeper than 2 levels
- [ ] Mixins solving single problems
Fix Strategy:
1. Identify what the abstraction solves 2. Check if you really need multiple implementations now 3. Delete the abstraction - use direct implementation 4. If multiple implementations needed later, refactor then 5. Principle: Avoid future-proofing
---
2. Complex Inheritance
What It Is: Deep inheritance chains, multiple inheritance, or convoluted class hierarchies that obscure code flow.
Why It's Bad: Makes code hard to follow, creates tight coupling, violates simplicity principle. Who does what becomes unclear.
Red Flags:
- 3+ levels of inheritance (GrandparentClass -> ParentClass -> ChildClass)
- Multiple inheritance from non-interface classes
- Inheritance used for code reuse instead of composition
- Overriding multiple levels of methods
- "Mixin" classes for cross-cutting concerns
Example - SMELL:
# BAD: Complex inheritance
class Entity:
def save(self): pass
def load(self): pass
class TimestampedEntity(Entity):
def add_timestamp(self): pass
class AuditableEntity(TimestampedEntity):
def audit_log(self): pass
class User(AuditableEntity):
def authenticate(self): passExample - FIXED:
# GOOD: Composition over inheritance
class User:
def __init__(self, storage, timestamp_service, audit_log):
self.storage = storage
self.timestamps = timestamp_service
self.audit = audit_log
def save(self):
self.storage.save(self)
self.timestamps.record()
self.audit.log("saved user")Detection Checklist:
- [ ] Inheritance depth > 2 levels
- [ ] Multiple inheritance from concrete classes
- [ ] Methods overridden at multiple inheritance levels
- [ ] Inheritance hierarchy with no code reuse
Fix Strategy:
1. Use composition instead of inheritance 2. Pass services as constructor arguments 3. Each class handles its own responsibility 4. Easier to test, understand, and modify
---
3. Large Functions (>50 Lines)
What It Is: Functions that do too many things and are difficult to understand, test, and modify.
Why It's Bad: Violates single responsibility, makes testing harder, increases bug surface area, reduces code reusability.
Red Flags:
- Functions with >50 lines of code
- Multiple indentation levels (3+ nested if/for)
- Functions with 5+ parameters
- Functions that need scrolling to see all of them
- Complex logic that's hard to name
Example - SMELL:
# BAD: Large function doing multiple things
def process_user_data(user_dict, validate=True, save=True, notify=True, log=True):
if validate:
if not user_dict.get('email'):
raise ValueError("Email required")
if not '@' in user_dict['email']:
raise ValueError("Invalid email")
user = User(
name=user_dict['name'],
email=user_dict['email'],
phone=user_dict['phone']
)
if save:
db.save(user)
if notify:
email_service.send(user.email, "Welcome!")
if log:
logger.info(f"User {user.name} created")
# ... 30+ more lines of mixed concerns
return userExample - FIXED:
# GOOD: Separated concerns
def validate_user_data(user_dict):
"""Validate user data structure."""
if not user_dict.get('email'):
raise ValueError("Email required")
if '@' not in user_dict['email']:
raise ValueError("Invalid email")
def create_user(user_dict):
"""Create user object from data."""
return User(
name=user_dict['name'],
email=user_dict['email'],
phone=user_dict['phone']
)
def process_user_data(user_dict):
"""Orchestrate user creation workflow."""
validate_user_data(user_dict)
user = create_user(user_dict)
db.save(user)
email_service.send(user.email, "Welcome!")
logger.info(f"User {user.name} created")
return userDetection Checklist:
- [ ] Function body >50 lines
- [ ] 3+ levels of nesting
- [ ] Multiple unrelated operations
- [ ] Hard to name succinctly
- [ ] 5+ parameters
Fix Strategy:
1. Extract helper functions for each concern 2. Give each function a clear, single purpose 3. Compose small functions into larger workflows 4. Each function should fit on one screen 5. Easy to name = usually doing one thing
---
4. Tight Coupling
What It Is: Modules/classes directly depend on concrete implementations instead of abstractions, making them hard to test and modify.
Why It's Bad: Changes in one module break others. Hard to test in isolation. Violates modularity principle.
Red Flags:
- Direct instantiation of classes inside functions (
db = Database()) - Deep attribute access (
obj.service.repository.data) - Hardcoded class names in conditionals
- Module imports everything from another module
- Circular dependencies between modules
Example - SMELL:
# BAD: Tight coupling
class UserService:
def create_user(self, name, email):
db = Database() # Hardcoded dependency
user = db.save_user(name, email)
email_service = EmailService() # Hardcoded dependency
email_service.send(email, "Welcome!")
return user
def get_user(self, user_id):
db = Database()
return db.find_user(user_id)Example - FIXED:
# GOOD: Loose coupling via dependency injection
class UserService:
def __init__(self, db, email_service):
self.db = db
self.email = email_service
def create_user(self, name, email):
user = self.db.save_user(name, email)
self.email.send(email, "Welcome!")
return user
def get_user(self, user_id):
return self.db.find_user(user_id)
# Usage:
user_service = UserService(db=PostgresDB(), email_service=SMTPService())Detection Checklist:
- [ ] Class instantiation inside methods (
Service()) - [ ] Deep attribute chaining (3+ dots)
- [ ] Hardcoded class references
- [ ] Circular imports or dependencies
- [ ] Module can't be tested without other modules
Fix Strategy:
1. Accept dependencies as constructor parameters 2. Use dependency injection 3. Create test doubles (mocks) easily 4. Swap implementations without changing code 5. Each module is independently testable
---
5. Missing __all__ Exports (Python)
What It Is: Python modules that don't explicitly define their public interface via __all__.
Why It's Bad: Unclear what's public vs internal. Users import private implementation details. Violates the "stud" concept - unclear connection points.
Red Flags:
- No
__all__in__init__.py - Modules expose internal functions/classes
- Users uncertain what to import
- Private names (
_function) still accessible - Documentation doesn't match exports
Example - SMELL:
# BAD: No __all__ - unclear public interface
# module/__init__.py
from .core import process_data, _internal_helper
from .utils import validate_input, LOG_LEVEL
# What should users import? All of it? Only some?Example - FIXED:
# GOOD: Clear public interface via __all__
# module/__init__.py
from .core import process_data
from .utils import validate_input
__all__ = ['process_data', 'validate_input']
# Users know exactly what's public and what to useDetection Checklist:
- [ ] Missing
__all__in__init__.py - [ ] Internal functions (prefixed with
_) exposed - [ ] Unclear what's "public API"
- [ ] All imports at module level
Fix Strategy:
1. Add __all__ to every __init__.py 2. List ONLY the public functions/classes 3. Prefix internal implementation with _ 4. Update documentation to match __all__ 5. Clear = users know exactly what to use
---
Analysis Process
Step 1: Scan Code Structure
1. Review file organization and module boundaries 2. Identify inheritance hierarchies 3. Scan for large functions (count lines) 4. Note __all__ presence/absence 5. Check for tight coupling patterns
Step 2: Analyze Each Smell
For each potential issue:
1. Confirm it violates philosophy 2. Measure severity (critical/major/minor) 3. Find specific line numbers 4. Note impact on system
Step 3: Generate Fixes
For each smell found:
1. Provide clear explanation of WHY it's bad 2. Show BEFORE code 3. Show AFTER code with detailed comments 4. Explain philosophy principle violated 5. Give concrete refactoring steps
Step 4: Create Report
1. List all smells found 2. Prioritize by severity/impact 3. Include specific examples 4. Provide actionable fixes 5. Reference philosophy docs
---
Detection Rules
Rule 1: Abstract Base Classes
Check: class X(ABC) with exactly 1 concrete implementation
# BAD pattern detection
- Count implementations of abstract class
- If count <= 2 and not used as interface: FLAGFix: Remove abstraction, use direct implementation
Rule 2: Inheritance Depth
Check: Class hierarchy depth
# BAD pattern detection
- Follow inheritance chain: class -> parent -> grandparent...
- If depth > 2: FLAGFix: Use composition instead
Rule 3: Function Line Count
Check: All function bodies
# BAD pattern detection
- Count lines in function (excluding docstring)
- If > 50 lines: FLAG
- If > 3 nesting levels: FLAGFix: Extract helper functions
Rule 4: Dependency Instantiation
Check: Class instantiation inside methods/functions
# BAD pattern detection
- Search for "= ServiceName()" inside methods
- If found: FLAGFix: Pass as constructor argument
Rule 5: Missing all
Check: Python modules
# BAD pattern detection
- Look for __all__ definition
- If missing: FLAG
- If __all__ incomplete: FLAGFix: Define explicit __all__
---
Common Code Smells & Quick Fixes
Smell: "Utility Class" Holder
# BAD
class StringUtils:
@staticmethod
def clean(s):
return s.strip().lower()Fix: Use direct function
# GOOD
def clean_string(s):
return s.strip().lower()---
Smell: "Manager" Class
# BAD
class UserManager:
def create(self): pass
def update(self): pass
def delete(self): pass
def validate(self): pass
def email(self): passFix: Split into focused services
# GOOD
class UserService:
def __init__(self, db, email):
self.db = db
self.email = email
def create(self): pass
def update(self): pass
def delete(self): pass
def validate_user(user): pass---
Smell: God Function
# BAD - 200 line function doing everything
def process_order(order_data, validate, save, notify, etc...):
# 200 lines mixing validation, transformation, DB, email, loggingFix: Compose small functions
# GOOD
def process_order(order_data):
validate_order(order_data)
order = create_order(order_data)
save_order(order)
notify_customer(order)
log_creation(order)---
Smell: Brittle Inheritance
# BAD
class Base:
def work(self): pass
class Middle(Base):
def work(self):
return super().work()
class Derived(Middle):
def work(self):
return super().work() # Which work()?Fix: Use clear, testable composition
# GOOD
class Worker:
def __init__(self, validator, transformer):
self.validator = validator
self.transformer = transformer
def work(self, data):
self.validator.check(data)
return self.transformer.apply(data)---
Smell: Hidden Dependencies
# BAD
def fetch_data(user_id):
db = Database() # Where's this coming from?
return db.query(f"SELECT * FROM users WHERE id={user_id}")Fix: Inject dependencies explicitly
# GOOD
def fetch_data(user_id, db):
return db.query(f"SELECT * FROM users WHERE id={user_id}")
# Or in a class:
class UserRepository:
def __init__(self, db):
self.db = db
def fetch(self, user_id):
return self.db.query(f"SELECT * FROM users WHERE id={user_id}")---
Usage Examples
Example 1: Review New Module
User: Review this new authentication module for code smells.
Claude:
1. Scans all Python files in module
2. Checks for each smell type
3. Finds:
- Abstract base class with 1 implementation
- Large 120-line authenticate() function
- Missing __all__ in __init__.py
4. Provides specific fixes with before/after code
5. Explains philosophy violationsExample 2: Identify Tight Coupling
User: Find tight coupling in this user service.
Claude:
1. Traces all dependencies
2. Finds hardcoded Database() instantiation
3. Finds direct EmailService() creation
4. Shows dependency injection fix
5. Includes test example showing why it mattersExample 3: Simplify Inheritance
User: This class hierarchy is too complex.
Claude:
1. Maps inheritance tree (finds 4 levels)
2. Shows each level doing what
3. Suggests composition approach
4. Provides before/after refactoring
5. Explains how it aligns with brick philosophy---
Analysis Checklist
Philosophy Compliance
- [ ] No unnecessary abstractions
- [ ] Single responsibility per class/function
- [ ] Clear public interface (
__all__) - [ ] Dependencies injected, not hidden
- [ ] Inheritance depth <= 2 levels
- [ ] Functions < 50 lines
- [ ] No dead code or stubs
Code Quality
- [ ] Each function has one clear job
- [ ] Easy to understand at a glance
- [ ] Easy to test in isolation
- [ ] Easy to modify without breaking others
- [ ] Clear naming reflects responsibility
Modularity
- [ ] Modules are independently testable
- [ ] Clear connection points ("studs")
- [ ] Loose coupling between modules
- [ ] Explicit dependencies
---
Success Criteria for Review
A code review using this skill should:
- [ ] Identify all violations of philosophy
- [ ] Provide specific line numbers
- [ ] Show before/after examples
- [ ] Explain WHY each is a problem
- [ ] Suggest concrete fixes
- [ ] Include test strategies
- [ ] Reference philosophy docs
- [ ] Prioritize by severity
- [ ] Be constructive and educational
- [ ] Help writer improve future code
---
Integration with Code Quality Tools
When to Use This Skill:
- During code review (before merge)
- In pull request comments
- Before creating new modules
- When refactoring legacy code
- To educate team members
- In design review meetings
Works Well With:
- Code review process
- Module spec generation
- Refactoring workflows
- Architecture discussions
- Mentoring and learning
---
Resources
- Philosophy:
~/.amplihack/.claude/context/PHILOSOPHY.md - Patterns:
~/.amplihack/.claude/context/PATTERNS.md - Brick Philosophy: See "Modular Architecture for AI" in PHILOSOPHY.md
- Zero-BS: See "Zero-BS Implementations" in PHILOSOPHY.md
---
Remember
This skill helps maintain code quality by:
1. Catching issues before they become technical debt 2. Educating developers on philosophy 3. Keeping code simple and maintainable 4. Preventing tightly-coupled systems 5. Making code easier to understand and modify
Use it constructively - the goal is learning and improvement, not criticism.
Code Smell Analysis - Real Examples
This document shows how the code-smell-detector skill analyzes real code patterns.
Example 1: User Service Module Analysis
Code Under Review
# user_service.py
from abc import ABC, abstractmethod
from datetime import datetime
class UserProcessor(ABC):
@abstractmethod
def process(self, user):
pass
class BasicUserProcessor(UserProcessor):
def process(self, user):
user.processed = True
return user
class UserService:
def __init__(self):
self.processor = BasicUserProcessor()
def create_user_and_notify(self, name, email, phone, country, notify=True,
validate=True, log=True, audit=True):
if validate:
if not name or len(name) < 2:
raise ValueError("Name too short")
if not email or '@' not in email:
raise ValueError("Invalid email")
if not phone or len(phone) < 10:
raise ValueError("Invalid phone")
if not country or len(country) < 2:
raise ValueError("Invalid country")
if log:
print(f"Creating user: {name}")
user = {
'name': name,
'email': email,
'phone': phone,
'country': country,
'created_at': datetime.now(),
}
if audit:
print(f"AUDIT: User created at {datetime.now()}")
processed_user = self.processor.process(user)
if notify:
email_service = EmailService()
email_service.send(email, f"Welcome {name}!")
if log:
print(f"User {name} created successfully")
return processed_user
class EmailService:
def send(self, email, message):
print(f"Email sent to {email}: {message}")Smell Analysis
Smell 1: Over-Abstraction
Severity: MAJOR Location: Lines 5-14 (UserProcessor ABC)
Issue:
- Abstract base class with exactly ONE concrete implementation
- No indication multiple implementations will ever be needed
- Adds unnecessary layer of indirection
Philosophy Violated: Ruthless Simplicity - "Every abstraction must justify its existence"
Fix:
# BEFORE (has abstraction)
class UserProcessor(ABC):
@abstractmethod
def process(self, user):
pass
class BasicUserProcessor(UserProcessor):
def process(self, user):
user.processed = True
return user
# AFTER (direct implementation)
def process_user(user):
"""Mark user as processed."""
user.processed = True
return userSmell 2: Large Function
Severity: CRITICAL Location: Lines 23-62 (create_user_and_notify)
Issue:
- 40+ lines doing 7 different things
- Mixed concerns: validation, logging, auditing, processing, notification
- Hard to test each concern in isolation
- Difficult to modify one aspect without affecting others
Philosophy Violated: Single Responsibility - "Each function does ONE thing well"
Fix:
# BEFORE - One big function doing everything
def create_user_and_notify(self, name, email, phone, country, notify=True,
validate=True, log=True, audit=True):
# 40 lines of mixed concerns
# AFTER - Separated concerns
def validate_user_data(name, email, phone, country):
"""Validate all user fields."""
if not name or len(name) < 2:
raise ValueError("Name too short")
if not email or '@' not in email:
raise ValueError("Invalid email")
if not phone or len(phone) < 10:
raise ValueError("Invalid phone")
if not country or len(country) < 2:
raise ValueError("Invalid country")
def create_user_dict(name, email, phone, country):
"""Create user data structure."""
return {
'name': name,
'email': email,
'phone': phone,
'country': country,
'created_at': datetime.now(),
}
def create_user_and_notify(self, name, email, phone, country,
notify=True, validate=True, log=True, audit=True):
"""Orchestrate user creation workflow."""
if validate:
validate_user_data(name, email, phone, country)
if log:
print(f"Creating user: {name}")
user = create_user_dict(name, email, phone, country)
if audit:
print(f"AUDIT: User created at {datetime.now()}")
processed_user = process_user(user)
if notify:
self.email_service.send(user['email'], f"Welcome {name}!")
if log:
print(f"User {name} created successfully")
return processed_userSmell 3: Tight Coupling
Severity: MAJOR Location: Lines 37-39 (hardcoded EmailService)
Issue:
EmailServiceinstantiated inside method- Can't test without actually sending emails
- Can't swap implementations
- Hidden dependency
Philosophy Violated: Modular Design - "Dependencies should be explicit and injected"
Fix:
# BEFORE - Hidden dependency
class UserService:
def __init__(self):
self.processor = BasicUserProcessor()
def create_user_and_notify(self, ...):
# ...
email_service = EmailService() # Where'd this come from?
email_service.send(email, f"Welcome {name}!")
# AFTER - Explicit dependencies
class UserService:
def __init__(self, email_service):
self.email_service = email_service
def create_user_and_notify(self, ...):
# ...
self.email_service.send(user['email'], f"Welcome {name}!")
# Usage:
service = UserService(email_service=SMTPEmailService())Smell 4: Missing __all__
Severity: MINOR Location: Module level (entire file)
Issue:
- No explicit public interface
- Users don't know what to import
- Internal classes might be imported by mistake
Philosophy Violated: Modular Design (Studs) - "Clear public interface"
Fix:
# Add at module level
__all__ = ['UserService', 'validate_user_data', 'create_user_dict']
# This tells users:
# - UserService is the main entry point
# - These helpers are available if needed
# - EmailService and process_user are internalRefactored Code (All Smells Fixed)
# user_service.py
"""User management and notification service."""
from datetime import datetime
__all__ = ['UserService']
# Validation
def validate_user_data(name, email, phone, country):
"""Validate all user fields."""
if not name or len(name) < 2:
raise ValueError("Name too short")
if not email or '@' not in email:
raise ValueError("Invalid email")
if not phone or len(phone) < 10:
raise ValueError("Invalid phone")
if not country or len(country) < 2:
raise ValueError("Invalid country")
# User creation
def create_user_dict(name, email, phone, country):
"""Create user data structure."""
return {
'name': name,
'email': email,
'phone': phone,
'country': country,
'created_at': datetime.now(),
}
def process_user(user):
"""Mark user as processed."""
user['processed'] = True
return user
# Service
class UserService:
"""Manage user creation with notifications."""
def __init__(self, email_service):
"""Initialize with email service dependency."""
self.email_service = email_service
def create_user_and_notify(self, name, email, phone, country,
notify=True, validate=True, log=True, audit=True):
"""Orchestrate user creation workflow."""
if validate:
validate_user_data(name, email, phone, country)
if log:
print(f"Creating user: {name}")
user = create_user_dict(name, email, phone, country)
if audit:
print(f"AUDIT: User created at {datetime.now()}")
processed_user = process_user(user)
if notify:
self.email_service.send(user['email'], f"Welcome {name}!")
if log:
print(f"User {name} created successfully")
return processed_userSummary of Improvements
| Smell | Severity | Fix |
|---|---|---|
| Over-Abstraction | MAJOR | Removed UserProcessor ABC, use direct process_user() |
| Large Function | CRITICAL | Split into validate_user_data(), create_user_dict(), process_user() |
| Tight Coupling | MAJOR | Inject email_service as constructor parameter |
Missing __all__ | MINOR | Added explicit __all__ = ['UserService'] |
Benefits of Refactored Code
1. Simpler: No unnecessary abstractions, clear flow 2. Testable: Each function can be tested independently 3. Flexible: Easy to swap email implementations 4. Maintainable: Clear responsibilities for each function 5. Philosophy-Aligned: Follows ruthless simplicity and modular design
---
Example 2: Quick Analysis Template
When reviewing code, use this format:
SMELL: [Name]
SEVERITY: [CRITICAL/MAJOR/MINOR]
LOCATION: [File:Line]
PHILOSOPHY VIOLATED: [Which principle]
ISSUE:
[Explain what's wrong and why]
EXAMPLE:
[Show the problematic code]
FIX:
[Show the fixed code]
IMPACT:
[Why this matters for the project]---
Example 3: Before & After Gallery
Pattern 1: Composition Over Inheritance
# BEFORE: 3-level inheritance
class Entity: pass
class TimestampedEntity(Entity): pass
class User(TimestampedEntity): pass
# AFTER: Composition
class User:
def __init__(self, storage, timestamps):
self.storage = storage
self.timestamps = timestampsPattern 2: Direct Functions Over Utility Classes
# BEFORE: Utility class
class StringUtils:
@staticmethod
def clean(s): return s.strip().lower()
# AFTER: Direct function
def clean_string(s): return s.strip().lower()Pattern 3: Dependency Injection
# BEFORE: Hidden dependency
def fetch_user(id):
db = Database()
return db.query(id)
# AFTER: Explicit dependency
def fetch_user(id, db):
return db.query(id)Pattern 4: Split God Functions
# BEFORE: 100 line function
def complex_workflow(data, ...): pass
# AFTER: Orchestrated workflow
def complex_workflow(data):
step1(data)
step2(data)
step3(data)---
Using This Analysis
1. Learn: Study the examples to understand each smell 2. Apply: Use these patterns when reviewing your code 3. Teach: Share examples with team members 4. Measure: Track improvements over time
Remember: The goal is continuous improvement and learning, not perfection.
Code Smell Detector - Quick Start Guide
How to Use This Skill
Basic Usage
User: Review this module for code smells and philosophy compliance.
Target: /path/to/module/
Claude Code:
1. Loads and analyzes all Python files in module
2. Checks each for the 5 code smell patterns
3. Reports findings with:
- Exact line numbers
- Severity (critical/major/minor)
- Philosophy violation
- Before/after fix examples
4. Provides refactoring guidanceStep-by-Step Analysis
Step 1: Identify the Code
"Check this authentication service for code smells."
→ Claude finds auth_service.pyStep 2: Scan for Smells
Code Smells Found:
1. Over-Abstraction (Line 15)
2. Large Function (Line 42)
3. Tight Coupling (Line 56)Step 3: Get Fixes
For each smell, Claude provides:
- What's wrong and why
- Before code (problematic)
- After code (fixed)
- How to apply the fixStep 4: Learn Philosophy
Why this matters:
- Violates "ruthless simplicity"
- Makes code harder to test
- Increases technical debtCommon Scenarios
Scenario 1: Code Review
User: Review this PR for philosophy compliance.
Claude:
1. Analyzes all changed files
2. Reports code smells found
3. Suggests fixes with examples
4. Explains philosophy principlesScenario 2: Refactoring Session
User: This module is getting complex. Help me refactor it.
Claude:
1. Identifies refactoring opportunities
2. Prioritizes by impact
3. Shows before/after patterns
4. Guides through refactoring stepsScenario 3: Learning
User: Why is this code considered a "smell"?
Claude:
1. Explains the pattern
2. Shows why it's problematic
3. Demonstrates the fix
4. References philosophy principleScenario 4: Team Training
User: Show the team common code smells.
Claude:
1. Demonstrates 5 smell types
2. Shows real examples
3. Explains fixes clearly
4. Provides discussion pointsQuick Reference
What to Ask
Good: "Review this module for code smells"
Good: "Is this function too large?"
Good: "Find tight coupling issues"
Good: "Check for over-abstraction"
Good: "Are there missing __all__ exports?"
Also Good: Show specific code and ask:
- "Is this inheritance hierarchy too deep?"
- "Should I inject this dependency?"
- "Is this class doing too much?"What You Get
For each smell found:
| Item | Detail |
|---|---|
| Location | File and line number |
| Severity | Critical/Major/Minor |
| Description | What's wrong |
| Philosophy | Which principle violated |
| Example | Bad pattern shown |
| Fix | Good pattern shown |
| Steps | How to refactor |
Example Analysis
Example 1: Find Over-Abstraction
User Input:
"Check this UserProcessor class for unnecessary abstraction."
Code:
abstract class UserProcessor:
@abstractmethod
def process(user): pass
class SimpleUserProcessor(UserProcessor):
def process(user): return user
Claude Output:
SMELL: Over-Abstraction
SEVERITY: MAJOR
LOCATION: userservice.py:5-12
ISSUE:
Abstract base class with only 1 concrete implementation.
Adds unnecessary layer without providing value.
Violates "ruthless simplicity" - every abstraction must justify itself.
PHILOSOPHY: Ruthless Simplicity
EXAMPLE - BEFORE:
abstract class UserProcessor:
@abstractmethod
def process(user): pass
class SimpleUserProcessor(UserProcessor):
def process(user): return user
EXAMPLE - AFTER:
def process_user(user):
"""Process user data."""
return user
WHY IT MATTERS:
- Removes unnecessary indirection
- Easier to test and understand
- Clearer code with less to maintain
- One thing does what needs doingExample 2: Find Large Function
User Input:
"This payment processing function seems too big. Help?"
Claude Output:
SMELL: Large Function (>50 lines)
SEVERITY: CRITICAL
LOCATION: payment.py:23-78 (56 lines)
ISSUES FOUND:
- Line count: 56 (target: <50)
- Nesting depth: 4 levels (target: <3)
- Responsibilities: 5 separate concerns
- Parameters: 7 (target: <5)
CONCERNS DETECTED:
1. Validation (lines 25-35)
2. Processing (lines 36-45)
3. Database operations (lines 46-55)
4. Notification (lines 56-65)
5. Logging (lines 66-78)
RECOMMENDATION:
Extract each concern to separate function.
Orchestrate workflow in main function.
[Shows complete refactoring with before/after]Example 3: Find Tight Coupling
User Input:
"Is this service tightly coupled?"
Claude Output:
SMELL: Tight Coupling
SEVERITY: MAJOR
LOCATION: UserService.py:12-28
DEPENDENCIES FOUND:
- Line 15: db = Database() ← Hardcoded
- Line 22: email = Email() ← Hardcoded
- Line 25: cache = Redis() ← Hardcoded
PROBLEMS:
- Can't test without real database
- Can't swap implementations
- Dependencies hidden in code
- Hard to mock for testing
PHILOSOPHY: Modular Design (Studs)
FIX: Dependency Injection
Pass dependencies as constructor arguments.
Makes code testable and flexible.
[Shows complete refactoring]Analysis Output Format
The skill provides consistent output:
SMELL: [Name]
SEVERITY: [CRITICAL/MAJOR/MINOR]
LOCATION: [File:StartLine-EndLine]
ISSUE:
[What's wrong and why]
PHILOSOPHY VIOLATED:
[Which principle and how]
EXAMPLE - BEFORE:
[Bad code]
EXAMPLE - AFTER:
[Good code with explanation]
IMPACT:
[Why this matters for your project]
RECOMMENDED ACTIONS:
1. [Step 1]
2. [Step 2]
3. [Step 3]Integration Patterns
With Code Review
PR Review:
1. Use skill to identify smells
2. Reference specific line numbers
3. Show before/after examples
4. Explain philosophy principle
5. Guide toward fixWith Refactoring
Refactoring Plan:
1. Identify smells to fix (prioritize)
2. Get fixes from skill
3. Apply refactoring
4. Run tests to verify
5. Document changesWith Architecture Review
Design Discussion:
1. Question proposed pattern
2. Check for potential smells
3. Reference philosophy
4. Suggest alternatives
5. Build team consensusTips for Best Results
1. Be Specific: Show exact code when asking 2. Ask Context: Explain what you're trying to do 3. Request Examples: Ask for before/after comparisons 4. Learn Philosophy: Understand WHY each rule exists 5. Share Results: Use findings to build team understanding
Document References
- Full SKILL.md: Complete detection rules and analysis process
- README.md: Overview and core concepts
- examples/smell_analysis_example.md: Real-world analysis examples
Philosophy Foundation
This skill is based on amplihack's core principles:
- Ruthless Simplicity: Keep everything as simple as possible
- Modular Design: Self-contained modules with clear contracts
- Zero-BS Code: Only working implementations, no stubs
- Single Responsibility: Each function/class does ONE thing
See ~/.amplihack/.claude/context/PHILOSOPHY.md for complete philosophy.
Success Indicators
You're using this skill effectively when:
- Code is simpler and easier to understand
- Tests are easier to write and maintain
- Modules can be tested independently
- Team understands philosophy principles
- New code follows patterns naturally
- Refactoring discussions become constructive
- Quality and productivity both improve
Next Steps
1. Use the skill to review a real module 2. Apply the fixes and improvements 3. Share examples with your team 4. Discuss philosophy principles 5. Build shared understanding 6. Continuously improve code quality
Remember: The goal is learning and improvement, not criticism.
Code Smell Detector Skill
A Claude Code Skill that identifies anti-patterns violating amplihack philosophy and provides specific, actionable fixes.
Quick Start
Use this skill when:
- Reviewing code for quality issues
- Refactoring complex or tightly-coupled code
- Ensuring new modules follow amplihack philosophy
- Learning why certain patterns are problematic
- Training team members on code quality
What It Detects
1. Over-Abstraction - Unnecessary base classes, interfaces, and abstraction layers 2. Complex Inheritance - Deep hierarchies (3+ levels), multiple inheritance issues 3. Large Functions - Functions over 50 lines doing multiple things 4. Tight Coupling - Direct dependencies, hardcoded instantiation, hidden dependencies 5. Missing `__all__` - Python modules without explicit public interface
How It Works
The skill analyzes your code and:
1. Identifies specific violations of amplihack philosophy 2. Explains WHY each pattern is problematic 3. Shows BEFORE and AFTER code examples 4. Provides concrete refactoring steps 5. References philosophy principles violated
Examples
Over-Abstraction
Bad Pattern:
class DataProcessor(ABC):
@abstractmethod
def process(self, data):
pass
class SimpleDataProcessor(DataProcessor):
def process(self, data):
return data * 2Good Pattern:
def process_data(data):
"""Process data by doubling it."""
return data * 2Complex Inheritance
Bad Pattern:
class Entity(Base):
pass
class TimestampedEntity(Entity):
pass
class AuditableEntity(TimestampedEntity):
pass
class User(AuditableEntity):
passGood Pattern:
class User:
def __init__(self, storage, timestamp_service, audit_log):
self.storage = storage
self.timestamps = timestamp_service
self.audit = audit_logLarge Functions
Bad Pattern:
def process_user(user_dict, validate=True, save=True, notify=True, log=True):
if validate:
# validation logic (20 lines)
if save:
# save logic (15 lines)
if notify:
# email logic (10 lines)
if log:
# logging logic (10 lines)
# ... more mixed concernsGood Pattern:
def validate_user(user_dict):
"""Validate user data."""
# 5 lines of focused validation
def create_user(user_dict):
"""Create user from data."""
# 5 lines of focused creation
def process_user(user_dict):
"""Orchestrate workflow."""
validate_user(user_dict)
user = create_user(user_dict)
db.save(user)
notify_user(user)
log_creation(user)Tight Coupling
Bad Pattern:
class UserService:
def create_user(self, name, email):
db = Database() # Hardcoded dependency
user = db.save_user(name, email)
email_service = EmailService() # Hardcoded dependency
email_service.send(email, "Welcome!")
return userGood Pattern:
class UserService:
def __init__(self, db, email_service):
self.db = db
self.email_service = email_service
def create_user(self, name, email):
user = self.db.save_user(name, email)
self.email_service.send(email, "Welcome!")
return userMissing __all__
Bad Pattern:
# module/__init__.py
from .core import process_data, _internal_helper
from .utils import validate_input, LOG_LEVEL
# Unclear what users should importGood Pattern:
# module/__init__.py
from .core import process_data
from .utils import validate_input
__all__ = ['process_data', 'validate_input']
# Crystal clear public interfaceCore Philosophy
This skill ensures code follows amplihack's key principles:
- Ruthless Simplicity: Every abstraction must justify its existence
- Modular Design: Self-contained modules with clear connection points (bricks & studs)
- Zero-BS Implementation: Only working code, no stubs or placeholders
- Single Responsibility: Each function/class does ONE thing well
Philosophy Alignment
Each code smell detected:
- Violates one or more amplihack principles
- Creates unnecessary complexity
- Reduces testability or maintainability
- Makes code harder to understand or modify
Best Practices
When using this skill:
1. Be Constructive - Frame findings as learning opportunities 2. Provide Context - Explain which philosophy principle is violated 3. Show Examples - BEFORE and AFTER code samples 4. Suggest Fixes - Concrete refactoring steps 5. Prioritize - List smells by severity and impact
Common Fixes Summary
| Smell | Root Cause | Quick Fix |
|---|---|---|
| Over-Abstraction | "Future-proofing" | Delete the abstraction layer |
| Complex Inheritance | Code reuse attempt | Use composition instead |
| Large Functions | Mixed concerns | Extract helper functions |
| Tight Coupling | Hidden dependencies | Use dependency injection |
Missing __all__ | Unclear API | Explicitly define exports |
Integration
Use this skill during:
- Code Review: Catch issues before merge
- Refactoring: Identify improvement opportunities
- Design Review: Ensure architecture aligns with philosophy
- Onboarding: Help new team members learn patterns
- Architecture Discussion: Guide design decisions
Resources
- Full Philosophy: See
~/.amplihack/.claude/context/PHILOSOPHY.md - Design Patterns: See
~/.amplihack/.claude/context/PATTERNS.md - Detailed SKILL.md: Full detection rules and analysis process
Next Steps
1. Use /skill code-smell-detector when reviewing code 2. Apply detected fixes to improve code quality 3. Share examples with team to build shared understanding 4. Reference philosophy docs when discussing findings 5. Create custom rules if needed for your project
---
Remember: This skill helps maintain quality and teach philosophy - use it to help, not criticize.
Related skills
FAQ
What code smells does code-smell-detector flag?
code-smell-detector flags long methods, duplication, tight coupling, and dead paths in changed code, then outputs prioritized refactor guidance for pull request review before merge or release.
When should I run code-smell-detector?
Run code-smell-detector on pull request diffs or pre-release changes when architectural smells exceed what linters catch and reviewers need ranked refactor priorities.