smell
Detect software architecture bad smells, algorithmic complexity hotspots, and anti-patterns in a codebase. Produces a detailed markdown report identifying violations of architectural principles, design patterns, code quality, and performance complexity. Triggers on: smell, code smell, architecture s
By smallnest · 492 installs
npx skills add smallnest/goal-workflow --skill smell
Source repository · Upstream listing
Smell — Architecture Bad Smell Detector
Analyze a codebase to find violations of software architecture principles, anti patterns, code "bad smells," and algorithmic complexity hotspots. Produce a comprehensive, actionable markdown report.
Knowledge base: This skill encodes architectural patterns, anti patterns, code smells, and algorithmic complexity heuristics drawn from industry research and practice, including the classic code smells catalog by Martin Fowler / Kent Beck (as organized on refactoring.guru: Bloaters, Object Orientation Abusers, Change Preventers, Dispensables, Couplers).
The Job
1. Understand the scope — ask what part of the project to analyze (full project, specific module, or recent changes)
2. Scan the codebase using find , grep , and Agent (Explore subagent) to gather candidate signals and evidence
3. Validate candidates against context, callers, history, workload, and measurements before confirming findings
4. Generate a detailed markdown report saved to tasks/smell report [timestamp].md
5. Present a summary of confirmed findings and separate candidates to the user
Step 1: Scope Clarification
Ask the user:
If the user doesn't specify, default to option A for small projects (< 100 files) or C for large projects.
Step 2: Evidence Gathering
Use the Explore subagent ( Agent with subagent type: "Explore" ) to scan the codebase for architectural patterns and anti patterns. Run multiple parallel explorations:
Exploration Commands
Run these in parallel to gather evidence efficiently:
1. Project Structure Scan: Map the directory tree, identify the architectural style (layered, modular monolith, microservices, etc.)
2. Dependency Analysis: Find import/include patterns, check for circular dependencies, identify coupling hotspots
3. Module/Component Scan: Identify God Objects (files 500 lines), check cohesion, check single responsibility violations
4. Pattern Detection: Look for known anti pattern signatures (static cling, service locator abuse, leaky abstractions)
5. Testing Scan: Check test coverage patterns, test file locations, test to code ratios
6. Naming & Clarity Scan: Flag misleading names, overly generic names (Manager, Helper, Util), inconsistent naming conventions
7. Complexity Scan: Detect algorithmic complexity hotspots — nested loops, N+1 queries, repeated scans, sort in loop, expensive recomputation in render paths
Key Heuristics
Heuristics are candidate signals, not findings . A line count, nesting, naming, or Big O match must be validated against the code's responsibility, callers, change history, workload, and intentional constraints. Do not assign severity from a threshold alone.
Category Smell Detection Heuristic
Architecture Big Ball of Mud No clear directory structure; everything in root or one flat folder; no separation of concerns
Architecture Violated Layer Boundaries Inner layers importing outer layers; infrastructure code in domain/core layer
Architecture Missing Architecture No src/ , lib/ , core/ separation; SQL inline with UI code; HTTP handlers mixed with business logic
Architecture Distributed Monolith Microservices sharing a database; services that can't deploy independently
Architecture Anemic Domain Model Model/entity classes with only getters/setters and no behavior; all logic in services
Architecture CQRS Without Need Separate read/write models for simple CRUD; unnecessary complexity
Architecture Over Layered Architecture Excessive layers/tiers that add pass through code with no real value
Architecture Over Abstraction So many indirections/interfaces/generics that you get lost following the code
Architecture Futuristic Architecture Speculative flexibility for requirements that may never come (predicting the future)
Architecture Technology Enthusiast Architecture Shiny/unproven tech adopted in production because it's new, not because it fits
Architecture Overkill Architecture Heavyweight architecture/tech thrown at a simple problem
Architecture Cloud/Visio Architecture Diagrams disconnected from the actual code and runtime reality
Coupling Circular Dependencies Module A imports B, B imports A; detected via import graph analysis
Coupling Content Coupling One module directly accesses another's internal/private members
Coupling Common Coupling Excessive global variables/shared mutable state; singleton abuse
Coupling Stamp Coupling Passing large data structures when only a few fields are needed
Cohesion God Object Single class/module 500 lines; 20 public methods; handles unrelated concerns
Cohesion Shotgun Surgery A single change requires touching 5+ files across unrelated modules
Cohesion Feature Envy Method calls foreign class methods more than its own class methods
Cohesion Data Clumps Same group of 3+ parameters appearing together in multiple method signatures
Design Leaky Abstractions Implementation details (DB queries, HTTP calls) exposed through interfaces
Design Static Cling Excessive use of static methods; static state that prevents testability
Design Service Locator Abuse DI container passed around instead of proper constructor injection
Design Violated SOLID SRP violations, OCP violations (switch/if else chains on types), ISP violations (fat interfaces)
Design Switch Statements Same switch /if else chain on a type code appearing in multiple places; should be polymorphism
Design Refused Bequest Subclass inherits methods/fields it doesn't use or overrides them to throw/no op
Design Alternative Classes w/ Different Interfaces Two classes do the same thing but have differently named methods
Design Parallel Inheritance Hierarchies Creating a subclass in one hierarchy forces a matching subclass in another
Design Speculative Generality Unused abstract classes, hooks, params, or generics "for future needs" (YAGNI)
Design Incomplete Library Class Wrapping/patching a third party class because it lacks needed methods
Cohesion Divergent Change One module changed for many unrelated reasons (opposite of Shotgun Surgery)
Cohesion Data Class Class with only fields + getters/setters, no behavior (anemic data bag)
Cohesion Lazy Class Class/module that does too little to justify its existence
Coupling Inappropriate Intimacy Two classes access each other's private/internal parts too much
Coupling Message Chains Long call chains a.getB().getC().getD() (Law of Demeter violation)
Coupling Middle Man Class that only delegates every call to another class
Code Temporary Field Instance field set/used only in certain circumstances, empty otherwise
Code Duplicated Code Identical/similar logic appearing in 3+ places; copy paste patterns
Code Long Method Methods 50 lines; deep nesting ( 3 levels)
Code Long Parameter List Methods with 4 parameters
Code Primitive Obsession Using strings/ints instead of domain types (e.g., string email instead of Email type)
Code Magic Numbers/Strings Hardcoded literals without named constants
Code Comments as Deodorant Excessive comments explaining bad code instead of refactoring
Code Dead Code Unused imports, unreachable code, commented out blocks
Testing No Tests Modules with zero test coverage
Testing Test Implementation Coupling Tests that assert internal implementation details instead of behavior
Testing Slow Tests Tests doing real I/O, database calls, network requests without mocking
Naming Vague Names Manager , Handler , Processor , Helper , Util , Service , Data , Info used excessively without context
Naming Inconsistent Naming Snake case and camelCase mixed; different patterns for same concept
Readability Deep Nesting (Arrow Anti Pattern) Loops/conditionals nested 3 levels deep; rightward drifting "arrow" shape hard to trace
Complexity Nested Loops (O(n^2)+) Loop inside loop; forEach inside for; map inside map; nested iteration suggesting polynomial complexity
Complexity Repeated Linear Scan includes() / indexOf() / .find() inside a loop; O(n m) membership check on list instead of Set/Map
Complexity Sort in Loop .sort() or sorted() called inside iterative code; repeated O(n log n) when sort once suffices
Complexity N+1 Query Pattern Database/API/HTTP call inside a loop; fetch / query / execute / findMany per iteration instead of batch
Complexity Render Path Recompute .filter().map().sort() chains in component render body; expensive transforms without memoization
Complexity Pairwise Comparison Nested iteration comparing every element with every other; O(n^2) when sort+two pointer would be O(n log n)
Complexity Unnecessary Recompute Same expensive computation repeated without caching; missing useMemo / memo /lazy eval
Complexity Wrong Data Structure Array used where Set/Map would give O(1) lookup; List where Queue/Heap/Stack is natural fit
Step 3: Report Generation
Finding Identity and Evidence
Process every candidate in three stages:
1. Candidate detection: static patterns, file metrics, and dependency scans produce candidates only.
2. Context validation: read the implementation and relevant callers; check change frequency, input size, runtime frequency, framework constraints, generated/vendor status, and existing mitigations.
3. Finding confirmation: merge candidates with the same root cause, affected path, failure/change scenario, and remediation direction into one finding.
Count findings by independent root cause, never by the number of principles they implicate. Use one Primary principle and optional Related principles . SOLID is an umbrella label; use SRP , OCP , or DIP as the primary label when the evidence supports a specific lens, without also creating a separate SOLID finding.
Canonical 11 Principle Matrix
Principle Confirming evidence Common false positive / constraint
SOLID A design problem spans multiple SOLID lenses or no narrower lens is reliable Do not duplicate a specific SRP/OCP/DIP finding
DRY The same business rule or knowledge must change in multiple places Similar syntax that is expected to evolve independently
KISS Extra layers, indirection, or machinery add cost without observable leverage A small abstraction that removes real complexity
YAGNI Unused extension points, parameters, adapters, or speculative requirements A tested seam required by an existing boundary or change
SRP Multiple independent reasons to change, supported by responsibilities or change history File size or method count alone
Open/Closed (OCP) Adding a known variant repeatedly modifies stable branching logic One simple, local conditional
Dependency Inversion (DIP) High level policy directly depends on concrete infrastructure, harming replacement or testing Adding an interface for a single stable implementation
Composition Inheritance causes unwanted coupling, refused behavior, or inseparable variation axes Replacing every valid inheritance relationship mechanically
Separation of Concerns Business policy, I/O, presentation, or persistence concerns leak across boundaries A deliberately thin boundary adapter
Fail Fast Invalid input, state, or dependency propagates until a distant operation fails Intentional aggregation, retry, or deferred validation semantics
Measure First A performance, scale, or optimization claim lacks a baseline or representative workload Static complexity reported