
Code Antipatterns Analysis
- 79 installs
- 49 repo stars
- Updated August 4, 2026
- laurigates/claude-plugins
Helps with ai & agent building tasks.
About
code-antipatterns-analysis is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- code-antipatterns-analysis
- AI & Agent Building
- AI-coding skill
Code Antipatterns Analysis by the numbers
- 79 all-time installs (skills.sh)
- +1 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #5,262 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/laurigates/claude-plugins --skill code-antipatterns-analysisAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 79 |
|---|---|
| repo stars | ★ 49 |
| Last updated | August 4, 2026 |
| Repository | laurigates/claude-plugins ↗ |
What it does
Helps with ai & agent building tasks.
Files
Code Anti-patterns Analysis
When to Use This Skill
| Use this skill when... | Use something else instead when... |
|---|---|
| You need the catalog of ast-grep anti-pattern queries to author a scan | Running the user-invocable scanner directly → code-antipatterns |
| Designing or extending parallel-delegated anti-pattern detection | Looking up ast-grep pattern syntax itself → ast-grep-search |
| Auditing for swallowed errors specifically | Use the dedicated scanner → code-error-swallowing |
| Cataloging quality issues for a broader review | Running a full code review → code-review |
Expert knowledge for systematic detection and analysis of anti-patterns, code smells, and quality issues across codebases using ast-grep and parallel agent delegation.
Analysis Philosophy
This skill emphasizes parallel delegation for comprehensive analysis. Rather than sequentially scanning for issues, launch multiple specialized agents to examine different categories simultaneously, then consolidate findings.
Analysis Categories
1. JavaScript/TypeScript Anti-patterns
Callback Hell & Async Issues
# Nested callbacks (3+ levels)
ast-grep -p '$FUNC($$$, function($$$) { $FUNC2($$$, function($$$) { $$$ }) })' --lang js
# Missing error handling in async
ast-grep -p 'async function $NAME($$$) { $$$ }' --lang js
# Then check if try-catch is present
# Unhandled promise rejection
ast-grep -p '$PROMISE.then($$$)' --lang js
# Without .catch() - use composite ruleMagic Values
# Magic numbers in comparisons
ast-grep -p 'if ($VAR > 100)' --lang js
ast-grep -p 'if ($VAR < 50)' --lang js
ast-grep -p 'if ($VAR === 42)' --lang js
# Magic strings
ast-grep -p "if ($VAR === 'admin')" --lang jsEmpty Catch Blocks
ast-grep -p 'try { $$$ } catch ($E) { }' --lang jsConsole Statements (Debug Leftovers)
ast-grep -p 'console.log($$$)' --lang js
ast-grep -p 'console.debug($$$)' --lang js
ast-grep -p 'console.warn($$$)' --lang jsUse let/const for Variable Declarations
ast-grep -p 'var $VAR = $$$' --lang js2. Vue 3 Anti-patterns
Props Mutation
# YAML rule for props mutation detection
id: vue-props-mutation
language: JavaScript
message: Use computed properties or emit events to update props
rule:
pattern: props.$PROP = $VALUE# Direct prop assignment
ast-grep -p 'props.$PROP = $VALUE' --lang jsMissing Keys in v-for
# Search in Vue templates
ast-grep -p 'v-for="$ITEM in $LIST"' --lang html
# Check if :key is present nearbyOptions API in Composition API Codebase
# Find Options API usage
ast-grep -p 'export default { data() { $$$ } }' --lang js
ast-grep -p 'export default { methods: { $$$ } }' --lang js
ast-grep -p 'export default { computed: { $$$ } }' --lang js
# vs Composition API
ast-grep -p 'defineComponent({ setup($$$) { $$$ } })' --lang jsReactive State Issues
# Destructuring reactive state (loses reactivity)
ast-grep -p 'const { $$$PROPS } = $REACTIVE' --lang js
# Should use toRefs
ast-grep -p 'const { $$$PROPS } = toRefs($REACTIVE)' --lang js3. TypeScript Quality Issues
Excessive `any` Usage
ast-grep -p ': any' --lang ts
ast-grep -p 'as any' --lang ts
ast-grep -p '<any>' --lang tsNon-null Assertions
ast-grep -p '$VAR!' --lang ts
ast-grep -p '$VAR!.$PROP' --lang tsType Assertions Instead of Guards
ast-grep -p '$VAR as $TYPE' --lang tsMissing Return Types
# Functions without return type annotations
ast-grep -p 'function $NAME($$$) { $$$ }' --lang ts
# Check if return type is present4. Async/Promise Patterns
Unhandled Promises
# Promise without await or .then/.catch
ast-grep -p '$ASYNC_FUNC($$$)' --lang js
# Context: check if result is used
# Floating promises (no await)
ast-grep -p '$PROMISE_RETURNING()' --lang tsNested Callbacks (Pyramid of Doom)
ast-grep -p '$F1($$$, function($$$) { $F2($$$, function($$$) { $F3($$$, function($$$) { $$$ }) }) })' --lang jsPromise Constructor Anti-pattern
# Wrapping already-async code in new Promise
ast-grep -p 'new Promise(($RESOLVE, $REJECT) => { $ASYNC_FUNC($$$).then($$$) })' --lang js5. Code Complexity
Long Functions (Manual Review)
# Find function definitions, then count lines
ast-grep -p 'function $NAME($$$) { $$$ }' --lang js --json | jq '.[] | select(.range.end.line - .range.start.line > 50)'Deep Nesting
# Nested if statements (4+ levels)
ast-grep -p 'if ($A) { if ($B) { if ($C) { if ($D) { $$$ } } } }' --lang jsLarge Parameter Lists
ast-grep -p 'function $NAME($A, $B, $C, $D, $E, $$$)' --lang jsCyclomatic Complexity Indicators
# Multiple conditionals in single function
ast-grep -p 'if ($$$) { $$$ } else if ($$$) { $$$ } else if ($$$) { $$$ }' --lang js6. React/Pinia Store Patterns
Direct State Mutation (Pinia)
# Direct store state mutation outside actions
ast-grep -p '$STORE.$STATE = $VALUE' --lang jsMissing Dependencies in useEffect
ast-grep -p 'useEffect(() => { $$$ }, [])' --lang jsx
# Check if variables used inside are in dependency arrayInline Functions in JSX
ast-grep -p '<$COMPONENT onClick={() => $$$} />' --lang jsx
ast-grep -p '<$COMPONENT onChange={() => $$$} />' --lang jsx7. Memory & Performance
Event Listeners Without Cleanup
ast-grep -p 'addEventListener($EVENT, $HANDLER)' --lang js
# Check for corresponding removeEventListenersetInterval Without Cleanup
ast-grep -p 'setInterval($$$)' --lang js
# Check for clearIntervalLarge Arrays in Computed/Memos
ast-grep -p 'computed(() => $ARRAY.filter($$$))' --lang js
ast-grep -p 'useMemo(() => $ARRAY.filter($$$), [$$$])' --lang jsx8. Security Concerns
eval Usage
ast-grep -p 'eval($$$)' --lang js
ast-grep -p 'new Function($$$)' --lang jsinnerHTML Assignment (XSS Risk)
ast-grep -p '$ELEM.innerHTML = $$$' --lang js
ast-grep -p 'dangerouslySetInnerHTML={{ __html: $$$ }}' --lang jsxHardcoded Secrets
ast-grep -p "apiKey: '$$$'" --lang js
ast-grep -p "password = '$$$'" --lang js
ast-grep -p "secret: '$$$'" --lang jsSQL String Concatenation
ast-grep -p '"SELECT * FROM " + $VAR' --lang js
ast-grep -p '`SELECT * FROM ${$VAR}`' --lang js9. Python Anti-patterns
Bare Except
ast-grep -p 'except: $$$' --lang pyMutable Default Arguments
ast-grep -p 'def $FUNC($ARG=[])' --lang py
ast-grep -p 'def $FUNC($ARG={})' --lang pyGlobal Variable Usage
ast-grep -p 'global $VAR' --lang pyType: ignore Without Reason
# Search in comments via grep
grep -r "# type: ignore$" --include="*.py"Parallel Analysis Strategy
When analyzing a codebase, launch multiple agents in parallel to maximize efficiency:
Agent Delegation Pattern
1. **Language Detection Agent** (Explore)
- Detect project languages and frameworks
- Identify relevant file patterns
2. **JavaScript/TypeScript Agent** (code-analysis or Explore)
- JS anti-patterns
- TypeScript quality issues
- Async/Promise patterns
3. **Framework-Specific Agent** (code-analysis or Explore)
- Vue 3 anti-patterns (if Vue detected)
- React anti-patterns (if React detected)
- Pinia/Redux patterns (if detected)
4. **Security Agent** (security-audit)
- Security concerns
- Hardcoded values
- Injection risks
5. **Complexity Agent** (code-analysis or Explore)
- Code complexity metrics
- Long functions
- Deep nesting
6. **Python Agent** (if Python detected)
- Python anti-patterns
- Type annotation issuesConsolidation
After parallel analysis completes: 1. Aggregate findings by severity (critical, high, medium, low) 2. Group by category (security, performance, maintainability) 3. Provide actionable remediation suggestions 4. Prioritize fixes based on impact
YAML Rule Examples
Complete Anti-pattern Rule
id: no-empty-catch
language: JavaScript
severity: warning
message: Empty catch block suppresses errors silently
note: |
Empty catch blocks hide errors and make debugging difficult.
Either log the error, handle it specifically, or re-throw.
rule:
pattern: try { $$$ } catch ($E) { }
fix: |
try { $$$ } catch ($E) {
console.error('Error:', $E);
throw $E;
}
files:
- 'src/**/*.js'
- 'src/**/*.ts'
ignores:
- '**/*.test.js'
- '**/node_modules/**'Vue Props Mutation Rule
id: no-props-mutation
language: JavaScript
severity: error
message: Never mutate props directly - use emit or local copy
rule:
all:
- pattern: props.$PROP = $VALUE
- inside:
kind: function_declaration
note: |
Props should be treated as immutable. To modify data:
1. Emit an event to parent: emit('update:propName', newValue)
2. Create a local ref: const local = ref(props.propName)Integration with Commands
This skill is designed to work with the /code:antipatterns command, which: 1. Detects project language stack 2. Launches parallel specialized agents 3. Consolidates findings into prioritized report 4. Suggests automated fixes where possible
Best Practices for Analysis
1. Start with language detection - Run appropriate patterns for detected languages 2. Use parallel agents - Don't sequentially analyze; delegate to specialized agents 3. Prioritize by severity - Security issues first, then correctness, then style 4. Provide fixes - Don't just identify problems; suggest solutions 5. Consider context - Some "anti-patterns" are acceptable in specific contexts 6. Check test files separately - Different standards may apply to test code
Severity Levels
| Severity | Description | Examples |
|---|---|---|
| Critical | Security vulnerabilities, data loss risk | eval(), SQL injection, hardcoded secrets |
| High | Bugs, incorrect behavior | Props mutation, unhandled promises, empty catch |
| Medium | Maintainability issues | Magic numbers, deep nesting, large functions |
| Low | Style/preference | var usage, console.log, inline functions |
Resources
- ast-grep Documentation: https://ast-grep.github.io/
- ast-grep Playground: https://ast-grep.github.io/playground.html
- OWASP Top 10: https://owasp.org/www-project-top-ten/
- Clean Code Principles: https://clean-code-developer.com/
Code Anti-patterns Reference
Comprehensive ast-grep pattern library for detecting anti-patterns across languages.
JavaScript/TypeScript Patterns
Async Anti-patterns
# Unhandled Promise - missing catch
id: unhandled-promise
language: JavaScript
severity: high
message: Promise chain missing error handler
rule:
pattern: $EXPR.then($HANDLER)
not:
follows:
pattern: .catch($$$)
note: Add .catch() or use try/catch with await
---
# Promise constructor anti-pattern
id: promise-constructor-antipattern
language: JavaScript
severity: medium
message: Unnecessary Promise wrapper around async code
rule:
pattern: new Promise(($RESOLVE, $REJECT) => { $ASYNC_CALL.then($$$) })
fix: $ASYNC_CALL
---
# Floating promise (missing await)
id: floating-promise
language: TypeScript
severity: high
message: Promise result not awaited or handled
rule:
pattern: $ASYNC_FUNC($$$)
not:
any:
- inside:
pattern: await $$$
- inside:
pattern: return $$$
- inside:
pattern: $VAR = $$$Error Handling
# Empty catch block
id: no-empty-catch
language: JavaScript
severity: warning
message: Empty catch block silently swallows errors
rule:
pattern: try { $$$ } catch ($E) { }
fix: |
try { $$$ } catch ($E) {
console.error($E);
throw $E;
}
---
# Catch without error parameter
id: catch-without-error
language: JavaScript
severity: info
message: Consider logging the caught error
rule:
pattern: catch { $$$ }
---
# Generic error catch
id: generic-error-catch
language: TypeScript
severity: info
message: Consider catching specific error types
rule:
pattern: catch ($E: Error) { $$$ }Code Smell Patterns
# Magic numbers
id: no-magic-numbers
language: JavaScript
severity: info
message: Consider extracting magic number to named constant
rule:
any:
- pattern: if ($VAR > 100)
- pattern: if ($VAR < 50)
- pattern: if ($VAR === 42)
- pattern: setTimeout($$$, 5000)
- pattern: setInterval($$$, 1000)
constraints:
# Exclude common acceptable values
VAR:
not:
regex: '^(0|1|-1|100)$'
---
# Long parameter list
id: long-parameter-list
language: JavaScript
severity: medium
message: Consider using an options object for many parameters
rule:
pattern: function $NAME($A, $B, $C, $D, $E, $$$) { $$$ }
note: Functions with more than 4 parameters are hard to use correctly
---
# Nested ternary
id: no-nested-ternary
language: JavaScript
severity: medium
message: Nested ternary is hard to read
rule:
pattern: $A ? $B : $C
has:
pattern: $X ? $Y : $ZDeprecated Patterns
# var usage
id: no-var
language: JavaScript
severity: info
message: Use let or const instead of var
rule:
pattern: var $VAR = $$$
fix: const $VAR = $$$
---
# arguments object
id: no-arguments
language: JavaScript
severity: info
message: Use rest parameters instead of arguments
rule:
pattern: arguments[$INDEX]
---
# Function constructor
id: no-function-constructor
language: JavaScript
severity: error
message: Function constructor is equivalent to eval
rule:
pattern: new Function($$$)Vue 3 Patterns
Reactivity Issues
# Props mutation
id: vue-props-mutation
language: JavaScript
severity: error
message: Never mutate props directly
rule:
pattern: props.$PROP = $VALUE
note: |
Use emit('update:propName', value) or create a local copy:
const localProp = ref(props.propName)
---
# Destructuring reactive state
id: vue-reactive-destructure
language: JavaScript
severity: high
message: Destructuring reactive state loses reactivity
rule:
pattern: const { $$$PROPS } = $REACTIVE_VAR
inside:
pattern: const $REACTIVE_VAR = reactive($$$)
fix: const { $$$PROPS } = toRefs($REACTIVE_VAR)
---
# Watch without immediate or deep when needed
id: vue-watch-options
language: JavaScript
severity: info
message: Consider if watch needs immediate or deep options
rule:
pattern: watch($SOURCE, $CALLBACK)
not:
has:
pattern: watch($SOURCE, $CALLBACK, { $$$ })Composition API Patterns
# Missing onUnmounted cleanup
id: vue-missing-cleanup
language: JavaScript
severity: medium
message: Event listener should be cleaned up in onUnmounted
rule:
pattern: onMounted(() => { $TARGET.addEventListener($$$) })
not:
inside:
has:
pattern: onUnmounted(() => { $TARGET.removeEventListener($$$) })
---
# Computed with side effects
id: vue-computed-side-effect
language: JavaScript
severity: high
message: Computed properties should not have side effects
rule:
pattern: computed(() => { $$$ })
has:
any:
- pattern: console.log($$$)
- pattern: $VAR = $VALUE
- pattern: $OBJ.$PROP = $VALUE
- pattern: fetch($$$)React Patterns
Hooks Issues
# useEffect with empty deps but using state
id: react-missing-deps
language: JavaScript
severity: high
message: useEffect uses variables not in dependency array
rule:
pattern: useEffect(() => { $$$ }, [])
note: Add used variables to dependency array or use exhaustive-deps lint rule
---
# useState with object instead of useReducer
id: react-complex-state
language: JavaScript
severity: info
message: Consider useReducer for complex state objects
rule:
pattern: useState({ $$$PROPS })
has:
pattern: { $A, $B, $C, $D, $$$ }
---
# Inline function in JSX
id: react-inline-function
language: JavaScript
severity: info
message: Inline functions create new references on each render
rule:
any:
- pattern: <$COMP onClick={() => $$$} />
- pattern: <$COMP onChange={() => $$$} />
- pattern: <$COMP onSubmit={() => $$$} />
note: Use useCallback or extract to a named functionComponent Patterns
# Component without memo for expensive renders
id: react-missing-memo
language: JavaScript
severity: info
message: Consider React.memo for components receiving object props
rule:
pattern: function $Component({ $$$PROPS }) { $$$ }
not:
inside:
pattern: memo($$$)
---
# Prop drilling (props passed through multiple levels)
id: react-prop-drilling
language: JavaScript
severity: info
message: Consider Context or state management for deeply passed props
rule:
pattern: <$Child $PROP={props.$PROP} />Python Patterns
Common Anti-patterns
# Mutable default argument
id: py-mutable-default
language: Python
severity: high
message: Mutable default argument creates shared state between calls
rule:
any:
- pattern: def $FUNC($ARG=[])
- pattern: def $FUNC($ARG={})
- pattern: def $FUNC($ARG=set())
fix: |
def $FUNC($ARG=None):
if $ARG is None:
$ARG = []
---
# Bare except
id: py-bare-except
language: Python
severity: high
message: Bare except catches all exceptions including KeyboardInterrupt
rule:
pattern: except:
fix: except Exception:
---
# Global variable
id: py-no-global
language: Python
severity: medium
message: Global variables make code hard to test and reason about
rule:
pattern: global $VAR
---
# Type ignore without reason
id: py-type-ignore-comment
language: Python
severity: info
message: type: ignore should include a reason
rule:
regex: '# type: ignore$'Pythonic Issues
# Using type() instead of isinstance()
id: py-use-isinstance
language: Python
severity: info
message: Use isinstance() for type checking
rule:
pattern: type($VAR) == $TYPE
fix: isinstance($VAR, $TYPE)
---
# Manual iteration with index
id: py-enumerate
language: Python
severity: info
message: Use enumerate() instead of manual index tracking
rule:
pattern: |
for $I in range(len($LIST)):
$$$ = $LIST[$I]
note: Use 'for i, item in enumerate(list):' instead
---
# Not using with statement for files
id: py-file-context
language: Python
severity: medium
message: Use context manager (with statement) for file operations
rule:
pattern: $VAR = open($$$)
not:
inside:
pattern: with open($$$) as $VAR:Security Patterns
Injection Risks
# eval usage
id: no-eval
language: JavaScript
severity: critical
message: eval() is a security risk - never use with user input
rule:
any:
- pattern: eval($$$)
- pattern: new Function($$$)
- pattern: setTimeout($STRING, $$$)
- pattern: setInterval($STRING, $$$)
constraints:
STRING:
kind: string
---
# innerHTML XSS
id: no-innerhtml
language: JavaScript
severity: high
message: innerHTML can lead to XSS - use textContent or sanitize
rule:
any:
- pattern: $ELEM.innerHTML = $$$
- pattern: $ELEM.outerHTML = $$$
---
# SQL injection (string concatenation)
id: sql-injection
language: JavaScript
severity: critical
message: Use parameterized queries instead of string concatenation
rule:
any:
- pattern: '"SELECT * FROM " + $VAR'
- pattern: '"SELECT " + $$$ + " FROM"'
- pattern: '`SELECT * FROM ${$VAR}`'
- pattern: '"INSERT INTO " + $VAR'
- pattern: '"UPDATE " + $VAR'
- pattern: '"DELETE FROM " + $VAR'
---
# Command injection
id: command-injection
language: JavaScript
severity: critical
message: Use execFile with array arguments instead of exec with string
rule:
pattern: exec($COMMAND)
inside:
kind: call_expression
constraints:
COMMAND:
any:
- kind: template_string
- kind: binary_expressionSecrets and Credentials
# Hardcoded API keys
id: hardcoded-api-key
language: JavaScript
severity: critical
message: Never hardcode API keys - use environment variables
rule:
any:
- pattern: apiKey = '$$$'
- pattern: "apiKey: '$$$'"
- pattern: API_KEY = '$$$'
- pattern: 'x-api-key': '$$$'
constraints:
# Exclude empty strings and placeholders
$$$:
not:
regex: '^(|your-api-key|xxx|placeholder)$'
---
# Hardcoded passwords
id: hardcoded-password
language: JavaScript
severity: critical
message: Never hardcode passwords
rule:
any:
- pattern: password = '$$$'
- pattern: "password: '$$$'"
- pattern: pwd = '$$$'
- pattern: secret = '$$$'
---
# JWT secret hardcoded
id: hardcoded-jwt-secret
language: JavaScript
severity: critical
message: JWT secrets should come from environment variables
rule:
pattern: jwt.sign($$$, '$SECRET', $$$)Performance Patterns
Memory Leaks
# Event listener without cleanup
id: event-listener-leak
language: JavaScript
severity: medium
message: Event listener may cause memory leak without removal
rule:
pattern: addEventListener($EVENT, $HANDLER)
not:
inside:
has:
pattern: removeEventListener($EVENT, $HANDLER)
---
# setInterval without cleanup
id: interval-leak
language: JavaScript
severity: medium
message: setInterval should be cleared to prevent memory leaks
rule:
pattern: setInterval($$$)
not:
inside:
has:
pattern: clearInterval($$$)
---
# Closure over large objects
id: closure-memory
language: JavaScript
severity: info
message: Closure captures entire scope - consider extracting needed values
rule:
pattern: |
const $LARGE = $$$;
$$$ = () => { $$$ }Inefficient Patterns
# Array method chaining creating intermediate arrays
id: array-chain-performance
language: JavaScript
severity: info
message: Chained array methods create intermediate arrays - consider reduce
rule:
pattern: $ARR.filter($$$).map($$$)
note: For large arrays, consider using a single reduce() instead
---
# Synchronous file operations
id: sync-file-ops
language: JavaScript
severity: medium
message: Synchronous file operations block the event loop
rule:
any:
- pattern: fs.readFileSync($$$)
- pattern: fs.writeFileSync($$$)
- pattern: fs.existsSync($$$)
note: Use async versions with await or callbacks in productionRunning Multiple Rules
Create sgconfig.yml
ruleDirs:
- rules/javascript
- rules/typescript
- rules/vue
- rules/react
- rules/python
- rules/security
utilDirs:
- rules/utils
testConfigs:
testDir: tests
snapshotDir: __snapshots__
languageGlobs:
- language: TypeScript
extensions: [ts, tsx]
- language: JavaScript
extensions: [js, jsx, mjs, cjs]
- language: Python
extensions: [py]
- language: Vue
extensions: [vue]Run All Rules
# Scan with all rules
ast-grep scan
# Scan specific rule
ast-grep scan -r no-empty-catch
# Output as JSON for processing
ast-grep scan --json > antipatterns-report.json
# Filter by severity
ast-grep scan --json | jq '[.[] | select(.severity == "critical" or .severity == "high")]'Quick Reference Commands
JavaScript/TypeScript
# All anti-patterns
ast-grep -p 'console.log($$$)' --lang js
ast-grep -p 'var $VAR = $$$' --lang js
ast-grep -p 'try { $$$ } catch ($E) { }' --lang js
ast-grep -p 'eval($$$)' --lang js
ast-grep -p ': any' --lang ts
ast-grep -p '$VAR!' --lang tsVue
ast-grep -p 'props.$PROP = $VALUE' --lang js
ast-grep -p 'const { $$$PROPS } = reactive($$$)' --lang jsPython
ast-grep -p 'def $FUNC($ARG=[])' --lang py
ast-grep -p 'except:' --lang py
ast-grep -p 'global $VAR' --lang pySecurity
ast-grep -p 'eval($$$)' --lang js
ast-grep -p '$ELEM.innerHTML = $$$' --lang js
ast-grep -p 'apiKey = "$$$"' --lang js
ast-grep -p '"SELECT * FROM " + $VAR' --lang js