Detect and fix patterns that make code look machine-generated, over-abstracted, unnecessarily verbose, or fluently wrong. The goal is code that reads like a competent human wrote it - minimal, intentional, grounded, and clear.
This skill covers: TypeScript/JavaScript, Python, Bash/Shell, Rust, Docker/Containers, and Infrastructure as Code (Terraform, Ansible, Helm, Kubernetes manifests). The universal patterns apply everywhere; language-specific sections add targeted checks.
When to use
Reviewing code that feels machine-generated, bloated, or oddly generic
Simplifying code after an AI-heavy implementation pass
Auditing comment noise, naming quality, over-abstraction, and dependency creep
Looking for "ugly but technically works" code that still hurts readability or maintainability
Looking for AI-native tells: hallucinated APIs, schema drift, fallback laundering, and tests that only ratify the implementation
The Three Axes of Slop
Every finding falls into one of three categories:
Noise - bulk without value (redundant comments, boilerplate, unnecessary types/annotations)
Lies - subtly wrong or outdated (hallucinated APIs, deprecated patterns, stale deps)
Correctness, logic, or race-condition bugs - use code-review
Security vulnerabilities, secret scanning, or auth review - use security-audit
One-off prompt authoring or prompt templates - use prompt-generator
Session-end documentation maintenance - use update-docs
Prose audit of docs, READMEs, wikis, emails, or creative writing - use anti-ai-prose
Safe-deletion or LOC-slimming requests (removing dead code, shrinking file count) - use code-slimming
AI Self-Check
Before returning any anti-slop audit, verify:
Rewrites compile/parse: every "after" code snippet is syntactically valid in the target language
Security patterns not flagged: auth, CORS, input validation, rate limiting, TLS - these are correct even if verbose (check the "What NOT to Flag" list)
Framework idioms respected: what looks like over-abstraction might be the framework's expected pattern (e.g., Next.js layouts, Django class-based views, Terraform module structure)
Existing project conventions preserved: the repo's naming style, comment density, and abstraction level take precedence over generic "clean code" preferences
Severity is honest: don't inflate P3 findings to P2 to pad the report
No hallucinated replacements: verify that suggested modern alternatives actually exist in the target language version (e.g., match requires Python 3.10+, LazyLock requires Rust 1.80+)
Test theater distinguished from correctness: implementation-mirroring tests, mock-heavy ceremony, and snapshots with no semantic assertions belong here; actual failing behavior still belongs to code-review
Structural duplication sweep done: compare same-role modules/classes across sibling dirs (providers, targets, sources, clients, registry) and either report near-twins or note why the duplication is intentional
Current source checked: dated versions, CLI flags, API names, and support windows are verified against primary docs before repeating them
Hidden state identified: local config, credentials, caches, contexts, branches, cluster targets, or previous runs are made explicit before acting
Verification is real: final checks exercise the actual runtime, parser, service, or integration point instead of only linting prose or happy paths
Routing overlap checked: overlapping skills, trigger terms, and "When NOT to use" boundaries are checked before returning guidance
Spec claims verified: claims about tool behavior, output contracts, or repo conventions are checked against current docs, scripts, or skill files
API/grounding verified: suspicious helpers, flags, imports, config keys, and schema claims are checked against local types, generated schema, lockfiles, --help output, or official docs before being called hallucinations
Test theater separated: tests that assert mocks or snapshots only are distinguished from tests proving behavior
Performance
Focus review on changed files and shared abstractions before scanning unrelated code.
Collapse repeated slop patterns into one finding with examples, not one finding per occurrence.
Use cheap static checks first, then run expensive tests only where they can confirm a real risk.
Best Practices
Prefer deleting unnecessary abstraction over adding a new abstraction to hide it.
Treat duplicate code as a finding only when it creates real divergence or maintenance risk.
Require concrete failure modes; style dislike is not slop.
Workflow
Step 1: Scope the audit
Default scope based on context:
If invoked right after writing code in this session -> self-check (review what you just wrote)
If there are uncommitted changes (git diff --name-only) -> recent changes
Otherwise -> ask the user
Available scopes:
Full codebase audit - scan everything, report by category
Recent changes - check git diff or recent commits
Specific files/dirs - targeted review
Self-check - review code you just wrote in this session
Step 2: Detect languages
Scan the project to determine which languages are present. Apply the universal patterns to everything, then layer on language-specific checks. Don't apply TS checks to Python code or vice versa.
Step 3: Run mechanical linters first (if available)
Before scanning for slop, run standard linters to clear the low-hanging fruit:
Shell: shellcheck
Python: ruff check / mypy
TypeScript: eslint / tsc --noEmit
Terraform: terraform validate / tflint
IaC schema tools: ansible-lint, helm lint, kubectl apply --dry-run=client, kubeconform when available
Structural patterns: ast-grep (tree-sitter powered AST search - write rules to catch restating comments, dead code, hallucinated imports across languages. Install: npm i -g @ast-grep/cli. If your tool ecosystem provides ast-grep helper skills or templates, use them.)
Linters handle syntax issues, unused imports, and known anti-patterns mechanically. This skill focuses on what linters can't catch: taste, over-abstraction, naming quality, unnecessary complexity, and stale idioms. Don't duplicate what a linter already covers.
Per-project tools (eslint, tsc, vitest, prettier) are project devDeps, not system tools. If they're not in the project's package.json/devDependencies, mention to the user what's missing and let them decide whether to install. Don't run linters that aren't set up.
Step 4: Scan for patterns
Use Grep, Glob, and Read. Read files before flagging - context matters. A pattern that looks like slop in isolation might be justified.
Before finalizing, do one explicit structural pass:
Compare same-role files across sibling directories (foo/emby.ts vs foo/jellyfin.ts, multiple registry.ts files, provider adapters, target wrappers)
Look for near-twin modules/classes with the same method set and only renamed nouns, IDs, or client types
If you find a repeated pattern across many files, report one representative example and mention the spread instead of silently dropping it
Classify each finding by axis (Noise/Lies/Soul - see above), action, and severity:
Action:
Fix - clearly wrong or wasteful, should change
Consider - judgment call, present it and let the user decide
Fine - looks like slop but is justified (note why and move on)
Severity (determines report ordering - high first):
P1 - strongly suggests fabricated or ungrounded code (hallucinated APIs, schema drift, silent swallowing used to hide uncertainty, fallback laundering)
Present findings grouped by category. For each Fix-level item, show the concrete replacement. Don't just point at problems - show the better version.
Universal Patterns (All Languages)
1. Comment Slop (Noise)
The single biggest tell. Comments that narrate what code does instead of why.
Detect:
Comments restating the next line ("Initialize array", "Loop through items", "Return result", "Set variable")
Hedging ("This should work", "This might need updating", "TODO: review this")
Overconfident assertions ("This is the most efficient approach", "This handles all edge cases")
Section dividers adding no information (# --- Helper Functions --- above obvious helpers)
Docstrings/JSDoc on every function when signatures are self-documenting
Inline comments on every block in a shell script or Terraform file
AI agent tells (rarely appear in human code):
Docstrings on every function regardless of complexity (add(a, b) -> "Returns the sum")
Restating the next line in English on every block; section headers in short functions
@param descriptions repeating the parameter name; comments on obvious ops (// increment counter)
Convention blindness: camelCase in a snake_case repo, JSDoc in a no-JSDoc project
Fix: Delete obvious comments. Keep only why comments - business logic, workarounds, gotchas, non-obvious decisions. If code needs a what comment, rewrite the code. A 20-line function needs zero comments if the names are good. A 200-line module might need 3-4.
Exception: Comments explaining workarounds for bugs, API quirks, or platform limitations are valuable. Also: shell scripts benefit from more comments than typical code because the syntax is less self-documenting.
2. Defensive Overkill (Soul)
Error handling or validation that protects against impossible scenarios.
Detect:
Try/catch (or try/except) that catches, logs, and re-raises without adding context
Null/nil/None checks after the type system or prior logic already guarantees non-null
Input validation deep inside internal functions (validate at boundaries, trust internally)
Fallback values for things that can't be missing
Shell scripts wrapping every command in if ... then ... fi instead of using set -e
Terraform try() / can() wrapping expressions that can't fail
AI agent tells (guardrails humans would never write):
Try/catch wrapping every function body, catching Error with a generic log message
Null checks on values from functions you control that never return null
Input validation on internal helpers that only receive pre-validated data
Fallback defaults for required config that should crash loudly if missing
if (!response.ok) after every internal call, not just HTTP boundaries
Fix: Remove pointless error handling. Validate at system boundaries (user input, API responses, env vars, external data), not on every internal call. If a catch block doesn't add context, retry, or recover - delete it.
Exception: Defensive checks on external data (network responses, deserialized JSON, user input, third-party libraries) are correct. Security patterns (auth, CORS, SSRF protection, input sanitization) should never be flagged.
3. Over-Abstraction (Soul)
Creating abstraction layers for problems that need 10 lines of direct code.
Detect:
Wrappers that just forward to one thing with no added logic
Abstract/base classes with a single concrete implementation
Factory functions that always produce the same type
Separate files for types/interfaces only used in one place
"Service" or "Manager" classes wrapping a single operation
Terraform modules wrapping a single resource with no added logic
Ansible roles with one task file
Shell functions called exactly once
Fix: Inline small abstractions. Delete wrappers that add no logic. A little repetition beats a premature abstraction.
Exception: Abstractions for testing (dependency injection), multiple implementations, or isolating external deps are fine even with one current impl.
4. Verbose Patterns (Noise)
Using 10 lines where 3 would do.
Detect (language-agnostic):
Unnecessary intermediate variables: result = foo(); return result
Ternaries wrapping boolean returns: return x ? true : false
Manual iteration that the language has built-ins for
Copy-pasting code blocks with tiny variations instead of parameterizing
Fix: Use the idiomatic short form for the language. See language-specific sections for details.
5. Generic Naming (Soul)
Names that could mean anything: data, result, response, item, temp, value, info, handler, manager, utils, helpers, common, misc.
Detect:
Variables with generic names outside tiny scopes (2-3 line lambdas are fine)
Files named utils.*, helpers.*, common.*, misc.* (junk drawers)
Functions named handle_x, process_x, manage_x without domain specificity
Terraform resources named this or main when there are multiple of the same type
Ansible variables named item or result in complex plays
Fix: Use domain-specific names. data -> active_subscriptions. utils.sh -> split by concern or inline.
Exception: Generic names in genuinely generic code (a map() callback, a type parameter T, a Terraform module's this when it's the only resource of that type).
Module-level smells
God modules are a structural form of generic naming: the file itself has no clear identity.
Detect:
Files named utils.*, helpers.*, common.*, misc.* with 30+ functions
A single module mixing unrelated domains (auth + formatting + DB queries + file I/O)
utils.py with functions spanning 5+ distinct concerns
Fix: Split by domain concern, not by arbitrary grouping. A 47-function utils.py typically contains 3-5 coherent modules (auth_utils.py, format_helpers.py, db_queries.py). Steps: (1) cluster functions by what they operate on or what domain they serve, (2) create a module per cluster, (3) update imports. Do not create a new junk-drawer module - each split module should have a name that describes its single concern.
Exception: Genuinely cross-cutting helpers (e.g., a retry() decorator used by 8 modules) can stay in a small, tightly scoped core.py or retry.py.
6. Logic Duplication (Lies)
Same logic written slightly differently in multiple places - a telltale sign of context-free generation.
Detect:
Near-identical helper functions in different files
Near-twin modules for adjacent integrations/providers where only names, IDs, or injected client types change
Registry classes with the same Map + register/get/all|list/clear shape repeated across domains
Thin wrappers/adapters that repeat the same mapping code for multiple backends
Same validation logic in multiple handlers/routes
Repeated inline formatting/parsing across modules
Terraform locals blocks computing the same thing in different modules
Ansible tasks doing the same thing with different variable names
Fix: Consolidate into a shared helper/factory/base module or keep one representative implementation and parameterize the differences. But only if truly the same - slight variations might be intentional.
Exception: Sometimes duplication is clearer than a contorted abstraction, especially when integrations are likely to diverge. Still surface it as a Consider finding if the files/classes are near-twins today.
7. Stale Patterns (Lies)
Code that was fine 5 years ago but has better alternatives now.
Fix: Use the modern equivalent. Check compatibility (language version, runtime, provider versions) before changing. See language-specific sections for concrete examples.
8. Error Handling Anti-Patterns (Noise + Lies)
Detect:
Catch/except blocks that log a generic message and continue (error is lost)
Every function wrapped in its own error handler (handle at boundaries instead)
Errors caught and re-raised as new exceptions, losing the original stack
Code that looks locally plausible because the names sound right, but it is not grounded in the actual API, schema, CLI, provider, or framework version in use.
Detect:
Functions, methods, imports, CLI flags, config keys, or resource arguments that look real but are not in local types, tool help, or docs
Mixing adjacent ecosystems: provider arguments from the wrong Terraform resource, Helm values keys that the chart never reads, Kubernetes fields from a different API version, Ansible params from the wrong module or collection
Compatibility blind spots: using a modern API without checking the repo's runtime/tool version
"Fixes" that paper over missing understanding with try(), optional chaining, default fallbacks, or broad catches instead of verifying the contract
Fix: Check the actual contract first - local types, generated schema, --help, provider docs, chart values, API version docs. Delete invented surface area. Prefer loud failure for required config over fantasy defaults.
Exception: Compatibility shims for multi-version support are fine when the codebase clearly supports multiple runtimes, provider versions, or API levels.
11. Test Theater / Self-Confirming Tests (Lies + Soul)
Tests can be slop too. A green test suite is not evidence if the tests were generated from the implementation and only mirror what already exists.
Detect:
Tests written after implementation that assert the exact control flow, fixture data, or internal call graph of the current code
Mock-heavy tests where every dependency is stubbed and the only assertions are call counts, method names, or log messages
Snapshots or golden files used as a substitute for semantic assertions
"Happy path only" tests paired with broad catches, default fallbacks, or defensive code that never gets exercised
Generated tests with high coverage but no clear link to the spec, acceptance criteria, or boundary behavior
Fix: Prefer spec-driven tests, behavior-level assertions, and a real RED phase. Keep mocks at the edges. If the test would still pass when the implementation is wrong in the same way, it is ceremony, not protection.
Exception: Adapter tests, logging/metrics assertions, and contract tests may legitimately assert call shapes when that contract is the behavior under test.
Language: TypeScript / JavaScript
Read references/typescript.md for the full TS/JS pattern catalog. Key highlights:
Type abuse: redundant annotations where inference works, any instead of unknown, enums instead of const objects/unions, missing satisfies / as const
Stale patterns: require() in ESM, var, React.FC, class components, PropTypes alongside TS, .then() chains, namespace
Verbose: for loops that should be .filter().map(), Object.keys().forEach() instead of for...of, classes for stateless logic
Dependency creep: node-fetch when fetch is global, uuid when crypto.randomUUID() exists, two libs for the same concern
AI-native tells: try/catch around deterministic local code, new Promise(async ...), fallback defaults for required env/config, tests that only assert mocks or snapshots
Barrel files: index.ts re-exporting everything in small directories
Language: Python
Read references/python.md for the full Python pattern catalog. Key highlights:
Class-for-everything disease: stateless classes that should be plain functions/modules
Exception anti-patterns: bare except: catching KeyboardInterrupt/SystemExit, except Exception as e: logger.error(e); raise (adds nothing), type/None checks on typed parameters (e.g., if user_id is None when the signature says int), broad try/except wrapping its own explicit raise statements
Stale patterns: os.path instead of pathlib, .format() instead of f-strings, % formatting, if/elif chains instead of match (3.10+), typing.Optional[X] instead of X | None (3.10+)
Type hints: Any used to bypass type errors, redundant hints on obvious assignments, overly complex TypeVar gymnastics
Verbose: manual dict/list building instead of comprehensions, nested if instead of early returns, lambda assigned to a variable (just use def), redundant docstrings restating the function signature
Dependency creep: requests for a single GET when urllib works, python-dotenv when os.environ is fine
AI-native tells: dict.get(..., {}) chains laundering missing invariants, catch-log-reraise noise, mock-heavy tests with no behavioral assertion
Language: Bash / Shell
Read references/shell.md for the full Shell pattern catalog. Key highlights:
Missing safety: no set -euo pipefail, unquoted variables, no shellcheck compliance
Useless use of cat: cat file | grep instead of grep file
Stale patterns: backticks instead of $(), expr instead of $(()), [ ] instead of [[ ]] in bash/zsh, parsing ls output
Over-defensive: if command; then ... fi on every line instead of set -e, manual $? checks
Verbose: echo "$var" | grep instead of [[ "$var" == *pattern* ]], external tools for built-in operations
AI-native tells: hallucinated flags/subcommands copied from adjacent CLIs, 2>/dev/null || true used to hide uncertainty, heredoc-heavy automation instead of checked files/templates
Language: Infrastructure as Code
Read references/iac.md for the full IaC pattern catalog covering Terraform, Ansible, Helm, and Kubernetes manifests. Key highlights:
Terraform: over-modularizing, redundant depends_on, not using locals, unpinned provider versions, invented resource arguments, provider/version hallucinations
Ansible: command/shell when a module exists, ignore_errors: true everywhere, registering variables never used, not using handlers, invented module params or wrong collections
Helm: hardcoded values in templates, tpl for static strings, .Values spaghetti without defaults, chart version not pinned, values keys that the chart never consumes
Kubernetes: no resource requests/limits, latest tags, no namespace, imperative kubectl run/create in automation, no probes, mismatched apiVersion/field combinations
Language: Rust
Read references/rust.md for the Rust pattern catalog. Key highlights:
Clone abuse: .clone() to dodge the borrow checker - the #1 AI-Rust tell
Error type proliferation: custom error enums for every module instead of anyhow/thiserror
Overly generic trait bounds: T: Display + Debug + Clone + Send + Sync when only Display is used
Verbose: match with two arms instead of if let, explicit return at function end, manual Option/Result matching instead of combinators
Unsafe overuse: unsafe blocks without // SAFETY: comments, transmute when as works
Stale: extern crate, #[macro_use], try!(), lazy_static instead of std::sync::LazyLock (1.80+)
Language: Docker / Containers
Read references/docker.md for Dockerfile and Compose pattern catalog. Key highlights:
Fat images: no multi-stage build, build tools in final stage, COPY . . before dep install (cache busting)
Layer waste: separate RUN per package, ADD for local files, RUN cd instead of WORKDIR
Security: running as root, chmod 777, secrets in build args/env, missing .dockerignore
Compose bloat: container_name everywhere, restart: always without healthchecks, depends_on without conditions, hardcoded ports
Stale: old base image versions, MAINTAINER directive, ENTRYPOINT+CMD confusion
Other Languages
For Go and other languages without dedicated reference files: apply the universal patterns (sections 1-11) only. Note in the report that language-specific checks were skipped. Common cross-language tells still apply - over-abstraction, comment noise, cross-language leakage, schema drift, and error handling anti-patterns look similar everywhere.
Research & Citations
Read references/research-sources.md for statistics, source citations, and deeper context on the "no soul" problem. Use when the user wants data to back up findings.
What NOT to Flag
These look like slop but aren't:
Security patterns: auth, CORS, SSRF protection, input validation at boundaries, rate limiting, TLS configuration, RBAC policies. Correct even if "defensive".
Explicit types/annotations on public interfaces: function signatures, exported types, API contracts benefit from explicitness.
Abstractions that enable testing: interfaces with one implementation for dependency injection.
Workaround comments: "works around X bug", "API requires this", "platform-specific" - institutional knowledge.
Defensive checks on external data: network responses, user input, deserialized data, third-party library output.
Shell verbosity for clarity: complex pipelines benefit from intermediate variables and comments.
Terraform count/for_each on single resources: might be conditional (count = var.enabled ? 1 : 0).
Ansible when conditions that seem obvious: often guarding against cross-platform differences.
Compatibility shims: version- or provider-specific branches may look repetitive because they support multiple real targets.
Contract-level tests: asserting exact API payloads, SQL, CLI args, or emitted metrics is fine when that contract is the thing being tested.
Output Contract
See skills/_shared/output-contract.md for the full contract.
Skill name: ANTI-SLOP
Deliverable bucket:audits
Mode: always-on. Every invocation emits the full contract - boxed inline header, body summary inline plus per-finding detail in the deliverable file, boxed conclusion, conclusion table.
Severity scale: reduced subset of the shared scale - P1 | P2 | P3 with slop-specific meanings (P1 fabricated/ungrounded, P2 maintainability, P3 style; see the Workflow classification). No P0: slop is never a build or security breaker - route those to code-review / security-audit.
Related Skills
code-review - finds bugs and correctness issues. Anti-slop finds quality and style issues.
If it would cause incorrect behavior, it's a code-review finding. If it's ugly but correct,
it's anti-slop.
security-audit - finds vulnerabilities. Defensive code that looks like "overkill" may be
correct security practice. Check the "What NOT to Flag" list before flagging security patterns.
full-review - orchestrates code-review, anti-slop, security-audit, and update-docs in
parallel. Anti-slop is one of the four passes.
update-docs - handles documentation maintenance. Anti-slop focuses on code quality;
update-docs focuses on keeping docs accurate and trimmed.
anti-ai-prose - audits prose for AI writing tells (vocabulary, syntax, tone, formatting).
Anti-slop audits code. Together they cover "does this repo read as machine-generated" across
both code and documentation.
code-slimming - handles safe-deletion and LOC-slimming passes (removing dead code, shrinking
file count). Use it when the goal is reducing volume; use anti-slop when the goal is quality.
Reference Files
references/typescript.md - TypeScript and JavaScript anti-slop patterns
references/python.md - Python anti-slop patterns
references/shell.md - shell and script anti-slop patterns
references/iac.md - Terraform, Ansible, Helm, and Kubernetes anti-slop patterns
references/rust.md - Rust anti-slop patterns
references/docker.md - Dockerfile and Compose anti-slop patterns
references/research-sources.md - supporting research, citations, and external context
Output Format
## Anti-Slop Audit: [scope]
### Findings
#### [Category Name] ([count] items)
**[action]** ([severity], [axis]) `path/to/file:line` - [description]
```[language]
// before
[code snippet]
// after
[improved code snippet]
```
### Summary
- X findings across Y files
- [top-level observations about codebase health]
Keep it concise. Show the diff, not a paragraph explaining it.
Rules
Keep correctness out of scope. If it would actually break behavior, route it to code-review instead of padding this report.
Flag AI-native lies even when they look polished. Hallucinated APIs, schema drift, and self-confirming tests belong here when the problem is lack of grounding or taste rather than a demonstrated failing behavior.
Keep security out of scope. Defensive code often looks verbose on purpose. Do not flag it casually.
Read before judging. A pattern that looks generic in isolation may be justified by framework or project constraints.
Ground hallucination claims. Use local types, schema, lockfiles, generated docs, or tool help before saying a flag/resource/API is fake.
Do not bury structural duplication. If near-twin modules or repeated registry/wrapper shapes appear, surface at least one representative finding even when higher-severity hallucination findings dominate the report.
Prefer concrete rewrites. If you flag a pattern, show the simpler version.
Run the AI Self-Check. Verify findings against the checklist before returning the audit.
1---2name: anti-slop3description: · Audit AI-generated code slop: hallucinated APIs, over-abstraction, duplicate code, test theater, noisy comments. Triggers: 'slop', 'AI-generated code', 'cleanup', 'overengineered'. Not for prose (use anti-ai-prose).4license: MIT5---67# Anti-Slop: Polyglot Code Quality Audit
89Detect and fix patterns that make code look machine-generated, over-abstracted, unnecessarily verbose, or fluently wrong. The goal is code that reads like a competent human wrote it - minimal, intentional, grounded, and clear.
1011This skill covers: **TypeScript/JavaScript**, **Python**, **Bash/Shell**, **Rust**, **Docker/Containers**, and **Infrastructure as Code** (Terraform, Ansible, Helm, Kubernetes manifests). The universal patterns apply everywhere; language-specific sections add targeted checks.
1213## When to use
1415- Reviewing code that feels machine-generated, bloated, or oddly generic
16- Simplifying code after an AI-heavy implementation pass
17- Auditing comment noise, naming quality, over-abstraction, and dependency creep
18- Looking for "ugly but technically works" code that still hurts readability or maintainability
19- Looking for AI-native tells: hallucinated APIs, schema drift, fallback laundering, and tests that only ratify the implementation
2021## The Three Axes of Slop
2223Every finding falls into one of three categories:
24251. **Noise** - bulk without value (redundant comments, boilerplate, unnecessary types/annotations)
262. **Lies** - subtly wrong or outdated (hallucinated APIs, deprecated patterns, stale deps)
273. **Soul** - lacks taste (over-abstraction, generic names, defensive overkill)
2829## When NOT to use
3031- Correctness, logic, or race-condition bugs - use **code-review**
32- Security vulnerabilities, secret scanning, or auth review - use **security-audit**
33- One-off prompt authoring or prompt templates - use **prompt-generator**
34- Session-end documentation maintenance - use **update-docs**
35- Prose audit of docs, READMEs, wikis, emails, or creative writing - use **anti-ai-prose**
36- Safe-deletion or LOC-slimming requests (removing dead code, shrinking file count) - use **code-slimming**
3738## AI Self-Check
3940Before returning any anti-slop audit, verify:
4142- [ ] **Rewrites compile/parse**: every "after" code snippet is syntactically valid in the target language
43- [ ] **Security patterns not flagged**: auth, CORS, input validation, rate limiting, TLS - these are correct even if verbose (check the "What NOT to Flag" list)
44- [ ] **Framework idioms respected**: what looks like over-abstraction might be the framework's expected pattern (e.g., Next.js layouts, Django class-based views, Terraform module structure)
45- [ ] **Existing project conventions preserved**: the repo's naming style, comment density, and abstraction level take precedence over generic "clean code" preferences
46- [ ] **Severity is honest**: don't inflate P3 findings to P2 to pad the report
47- [ ] **No hallucinated replacements**: verify that suggested modern alternatives actually exist in the target language version (e.g., `match` requires Python 3.10+, `LazyLock` requires Rust 1.80+)
48- [ ] **Test theater distinguished from correctness**: implementation-mirroring tests, mock-heavy ceremony, and snapshots with no semantic assertions belong here; actual failing behavior still belongs to code-review
49- [ ] **Structural duplication sweep done**: compare same-role modules/classes across sibling dirs (`providers`, `targets`, `sources`, `clients`, `registry`) and either report near-twins or note why the duplication is intentional
50- [ ] **Current source checked**: dated versions, CLI flags, API names, and support windows are verified against primary docs before repeating them
51- [ ] **Hidden state identified**: local config, credentials, caches, contexts, branches, cluster targets, or previous runs are made explicit before acting
52- [ ] **Verification is real**: final checks exercise the actual runtime, parser, service, or integration point instead of only linting prose or happy paths
53- [ ] **Routing overlap checked**: overlapping skills, trigger terms, and "When NOT to use" boundaries are checked before returning guidance
54- [ ] **Spec claims verified**: claims about tool behavior, output contracts, or repo conventions are checked against current docs, scripts, or skill files
55- [ ] **API/grounding verified**: suspicious helpers, flags, imports, config keys, and schema claims are checked against local types, generated schema, lockfiles, `--help` output, or official docs before being called hallucinations
56- [ ] **Test theater separated**: tests that assert mocks or snapshots only are distinguished from tests proving behavior
5758---
5960## Performance
6162- Focus review on changed files and shared abstractions before scanning unrelated code.
63- Collapse repeated slop patterns into one finding with examples, not one finding per occurrence.
64- Use cheap static checks first, then run expensive tests only where they can confirm a real risk.
6566---
6768## Best Practices
6970- Prefer deleting unnecessary abstraction over adding a new abstraction to hide it.
71- Treat duplicate code as a finding only when it creates real divergence or maintenance risk.
72- Require concrete failure modes; style dislike is not slop.
7374## Workflow
7576### Step 1: Scope the audit
7778Default scope based on context:
79- If invoked right after writing code in this session -> **self-check** (review what you just wrote)
80- If there are uncommitted changes (`git diff --name-only`) -> **recent changes**
81- Otherwise -> ask the user
8283Available scopes:
84- **Full codebase audit** - scan everything, report by category
85- **Recent changes** - check git diff or recent commits
86- **Specific files/dirs** - targeted review
87- **Self-check** - review code you just wrote in this session
8889### Step 2: Detect languages
9091Scan the project to determine which languages are present. Apply the universal patterns to everything, then layer on language-specific checks. Don't apply TS checks to Python code or vice versa.
9293### Step 3: Run mechanical linters first (if available)
9495Before scanning for slop, run standard linters to clear the low-hanging fruit:
96- **Shell**: `shellcheck`
97- **Python**: `ruff check` / `mypy`
98- **TypeScript**: `eslint` / `tsc --noEmit`
99- **Terraform**: `terraform validate` / `tflint`
100- **IaC schema tools**: `ansible-lint`, `helm lint`, `kubectl apply --dry-run=client`, `kubeconform` when available
101- **Structural patterns**: `ast-grep` (tree-sitter powered AST search - write rules to catch restating comments, dead code, hallucinated imports across languages. Install: `npm i -g @ast-grep/cli`. If your tool ecosystem provides `ast-grep` helper skills or templates, use them.)
102103Linters handle syntax issues, unused imports, and known anti-patterns mechanically. This skill focuses on what linters can't catch: taste, over-abstraction, naming quality, unnecessary complexity, and stale idioms. Don't duplicate what a linter already covers.
104105**Per-project tools** (eslint, tsc, vitest, prettier) are project devDeps, not system tools. If they're not in the project's `package.json`/`devDependencies`, mention to the user what's missing and let them decide whether to install. Don't run linters that aren't set up.
106107### Step 4: Scan for patterns
108109Use Grep, Glob, and Read. Read files before flagging - context matters. A pattern that looks like slop in isolation might be justified.
110111Before finalizing, do one explicit structural pass:
112- Compare same-role files across sibling directories (`foo/emby.ts` vs `foo/jellyfin.ts`, multiple `registry.ts` files, provider adapters, target wrappers)
113- Look for near-twin modules/classes with the same method set and only renamed nouns, IDs, or client types
114- If you find a repeated pattern across many files, report one representative example and mention the spread instead of silently dropping it
115116Classify each finding by axis (Noise/Lies/Soul - see above), action, and severity:
117118**Action:**
119- **Fix** - clearly wrong or wasteful, should change
120- **Consider** - judgment call, present it and let the user decide
121- **Fine** - looks like slop but is justified (note why and move on)
122123**Severity** (determines report ordering - high first):
124- **P1** - strongly suggests fabricated or ungrounded code (hallucinated APIs, schema drift, silent swallowing used to hide uncertainty, fallback laundering)
125- **P2** - maintainability (over-abstraction, generic naming, missing error context, logic duplication)
126- **P3** - style (verbose patterns, comment noise, redundant annotations, barrel files)
127128### Step 5: Report and fix
129130Present findings grouped by category. For each Fix-level item, show the concrete replacement. Don't just point at problems - show the better version.
131132---
133134## Universal Patterns (All Languages)
135136### 1. Comment Slop (Noise)
137138The single biggest tell. Comments that narrate what code does instead of why.
139140**Detect:**
141- Comments restating the next line ("Initialize array", "Loop through items", "Return result", "Set variable")
142- Hedging ("This should work", "This might need updating", "TODO: review this")
143- Overconfident assertions ("This is the most efficient approach", "This handles all edge cases")
144- Section dividers adding no information (`# --- Helper Functions ---` above obvious helpers)
145- Docstrings/JSDoc on every function when signatures are self-documenting
146- Inline comments on every block in a shell script or Terraform file
147148**AI agent tells** (rarely appear in human code):
149- Docstrings on every function regardless of complexity (`add(a, b)` -> "Returns the sum")
150- Restating the next line in English on every block; section headers in short functions
151- `@param` descriptions repeating the parameter name; comments on obvious ops (`// increment counter`)
152- Convention blindness: camelCase in a snake_case repo, JSDoc in a no-JSDoc project
153154**Fix:** Delete obvious comments. Keep only *why* comments - business logic, workarounds, gotchas, non-obvious decisions. If code needs a *what* comment, rewrite the code. A 20-line function needs zero comments if the names are good. A 200-line module might need 3-4.
155156**Exception:** Comments explaining workarounds for bugs, API quirks, or platform limitations are valuable. Also: shell scripts benefit from more comments than typical code because the syntax is less self-documenting.
157158### 2. Defensive Overkill (Soul)
159160Error handling or validation that protects against impossible scenarios.
161162**Detect:**
163- Try/catch (or try/except) that catches, logs, and re-raises without adding context
164- Null/nil/None checks after the type system or prior logic already guarantees non-null
165- Input validation deep inside internal functions (validate at boundaries, trust internally)
166- Fallback values for things that can't be missing
167- Shell scripts wrapping every command in `if ... then ... fi` instead of using `set -e`
168- Terraform `try()` / `can()` wrapping expressions that can't fail
169170**AI agent tells** (guardrails humans would never write):
171- Try/catch wrapping every function body, catching `Error` with a generic log message
172- Null checks on values from functions you control that never return null
173- Input validation on internal helpers that only receive pre-validated data
174- Fallback defaults for required config that should crash loudly if missing
175- `if (!response.ok)` after every internal call, not just HTTP boundaries
176177**Fix:** Remove pointless error handling. Validate at system boundaries (user input, API responses, env vars, external data), not on every internal call. If a catch block doesn't add context, retry, or recover - delete it.
178179**Exception:** Defensive checks on external data (network responses, deserialized JSON, user input, third-party libraries) are correct. Security patterns (auth, CORS, SSRF protection, input sanitization) should never be flagged.
180181### 3. Over-Abstraction (Soul)
182183Creating abstraction layers for problems that need 10 lines of direct code.
184185**Detect:**
186- Wrappers that just forward to one thing with no added logic
187- Abstract/base classes with a single concrete implementation
188- Factory functions that always produce the same type
189- Separate files for types/interfaces only used in one place
190- "Service" or "Manager" classes wrapping a single operation
191- Terraform modules wrapping a single resource with no added logic
192- Ansible roles with one task file
193- Shell functions called exactly once
194195**Fix:** Inline small abstractions. Delete wrappers that add no logic. A little repetition beats a premature abstraction.
196197**Exception:** Abstractions for testing (dependency injection), multiple implementations, or isolating external deps are fine even with one current impl.
198199### 4. Verbose Patterns (Noise)
200201Using 10 lines where 3 would do.
202203**Detect (language-agnostic):**
204- Unnecessary intermediate variables: `result = foo(); return result`
205- Ternaries wrapping boolean returns: `return x ? true : false`
206- Manual iteration that the language has built-ins for
207- Copy-pasting code blocks with tiny variations instead of parameterizing
208209**Fix:** Use the idiomatic short form for the language. See language-specific sections for details.
210211### 5. Generic Naming (Soul)
212213Names that could mean anything: `data`, `result`, `response`, `item`, `temp`, `value`, `info`, `handler`, `manager`, `utils`, `helpers`, `common`, `misc`.
214215**Detect:**
216- Variables with generic names outside tiny scopes (2-3 line lambdas are fine)
217- Files named `utils.*`, `helpers.*`, `common.*`, `misc.*` (junk drawers)
218- Functions named `handle_x`, `process_x`, `manage_x` without domain specificity
219- Terraform resources named `this` or `main` when there are multiple of the same type
220- Ansible variables named `item` or `result` in complex plays
221222**Fix:** Use domain-specific names. `data` -> `active_subscriptions`. `utils.sh` -> split by concern or inline.
223224**Exception:** Generic names in genuinely generic code (a `map()` callback, a type parameter `T`, a Terraform module's `this` when it's the only resource of that type).
225226#### Module-level smells
227228God modules are a structural form of generic naming: the file itself has no clear identity.
229230**Detect:**
231- Files named `utils.*`, `helpers.*`, `common.*`, `misc.*` with 30+ functions
232- A single module mixing unrelated domains (auth + formatting + DB queries + file I/O)
233- `utils.py` with functions spanning 5+ distinct concerns
234235**Fix:** Split by domain concern, not by arbitrary grouping. A 47-function `utils.py` typically contains 3-5 coherent modules (`auth_utils.py`, `format_helpers.py`, `db_queries.py`). Steps: (1) cluster functions by what they operate on or what domain they serve, (2) create a module per cluster, (3) update imports. Do not create a new junk-drawer module - each split module should have a name that describes its single concern.
236237**Exception:** Genuinely cross-cutting helpers (e.g., a `retry()` decorator used by 8 modules) can stay in a small, tightly scoped `core.py` or `retry.py`.
238239### 6. Logic Duplication (Lies)
240241Same logic written slightly differently in multiple places - a telltale sign of context-free generation.
242243**Detect:**
244- Near-identical helper functions in different files
245- Near-twin modules for adjacent integrations/providers where only names, IDs, or injected client types change
246- Registry classes with the same `Map` + `register/get/all|list/clear` shape repeated across domains
247- Thin wrappers/adapters that repeat the same mapping code for multiple backends
248- Same validation logic in multiple handlers/routes
249- Repeated inline formatting/parsing across modules
250- Terraform `locals` blocks computing the same thing in different modules
251- Ansible tasks doing the same thing with different variable names
252253**Fix:** Consolidate into a shared helper/factory/base module or keep one representative implementation and parameterize the differences. But only if truly the same - slight variations might be intentional.
254255**Exception:** Sometimes duplication is clearer than a contorted abstraction, especially when integrations are likely to diverge. Still surface it as a **Consider** finding if the files/classes are near-twins today.
256257### 7. Stale Patterns (Lies)
258259Code that was fine 5 years ago but has better alternatives now.
260261**Fix:** Use the modern equivalent. Check compatibility (language version, runtime, provider versions) before changing. See language-specific sections for concrete examples.
262263### 8. Error Handling Anti-Patterns (Noise + Lies)
264265**Detect:**
266- Catch/except blocks that log a generic message and continue (error is lost)
267- Every function wrapped in its own error handler (handle at boundaries instead)
268- Errors caught and re-raised as new exceptions, losing the original stack
269- Silent swallowing: `.catch(() => {})`, `except: pass`, `2>/dev/null` on critical commands
270- Shell scripts without `set -e` that check `$?` after every command manually
271272**Fix:** Handle errors at boundaries. Let errors propagate through internal code. When catching, either recover or add context and re-raise.
273274**Exception:** Fire-and-forget operations legitimately swallow errors. Comment why.
275276### 9. Cross-Language Leakage (Lies)
277278AI models trained on multiple languages bleed idioms across boundaries. A reliable tell for AI-generated code.
279280**Detect:**
281- JavaScript patterns in Python: `.push()`, `.length`, `.forEach()`, `===`, `console.log()`
282- Java patterns in non-Java: `.equals()`, `.toString()`, `System.out.println()`, `public static void`
283- Python patterns in JavaScript: `len()`, `print()`, `elif`, `def `, using `#` comments in JS
284- Shell patterns in Python: backtick usage, `$VARIABLE` syntax
285- Go patterns elsewhere: `fmt.Println()`, `:=` assignment, `func ` in non-Go
286287**Fix:** Replace with the target language's idiom. This is almost always an AI generation artifact - humans don't accidentally write `.push()` in Python.
288289### 10. Plausible Hallucinations / Schema Drift (Lies)
290291Code that looks locally plausible because the names sound right, but it is not grounded in the actual API, schema, CLI, provider, or framework version in use.
292293**Detect:**
294- Functions, methods, imports, CLI flags, config keys, or resource arguments that look real but are not in local types, tool help, or docs
295- Mixing adjacent ecosystems: provider arguments from the wrong Terraform resource, Helm values keys that the chart never reads, Kubernetes fields from a different API version, Ansible params from the wrong module or collection
296- Compatibility blind spots: using a modern API without checking the repo's runtime/tool version
297- "Fixes" that paper over missing understanding with `try()`, optional chaining, default fallbacks, or broad catches instead of verifying the contract
298299**Fix:** Check the actual contract first - local types, generated schema, `--help`, provider docs, chart values, API version docs. Delete invented surface area. Prefer loud failure for required config over fantasy defaults.
300301**Exception:** Compatibility shims for multi-version support are fine when the codebase clearly supports multiple runtimes, provider versions, or API levels.
302303### 11. Test Theater / Self-Confirming Tests (Lies + Soul)
304305Tests can be slop too. A green test suite is not evidence if the tests were generated from the implementation and only mirror what already exists.
306307**Detect:**
308- Tests written after implementation that assert the exact control flow, fixture data, or internal call graph of the current code
309- Mock-heavy tests where every dependency is stubbed and the only assertions are call counts, method names, or log messages
310- Snapshots or golden files used as a substitute for semantic assertions
311- "Happy path only" tests paired with broad catches, default fallbacks, or defensive code that never gets exercised
312- Generated tests with high coverage but no clear link to the spec, acceptance criteria, or boundary behavior
313314**Fix:** Prefer spec-driven tests, behavior-level assertions, and a real RED phase. Keep mocks at the edges. If the test would still pass when the implementation is wrong in the same way, it is ceremony, not protection.
315316**Exception:** Adapter tests, logging/metrics assertions, and contract tests may legitimately assert call shapes when that contract is the behavior under test.
317318---
319320## Language: TypeScript / JavaScript
321322Read `references/typescript.md` for the full TS/JS pattern catalog. Key highlights:
323324- **Type abuse**: redundant annotations where inference works, `any` instead of `unknown`, enums instead of const objects/unions, missing `satisfies` / `as const`
325- **Stale patterns**: `require()` in ESM, `var`, `React.FC`, class components, `PropTypes` alongside TS, `.then()` chains, `namespace`
326- **Verbose**: `for` loops that should be `.filter().map()`, `Object.keys().forEach()` instead of `for...of`, classes for stateless logic
327- **Dependency creep**: `node-fetch` when `fetch` is global, `uuid` when `crypto.randomUUID()` exists, two libs for the same concern
328- **AI-native tells**: `try/catch` around deterministic local code, `new Promise(async ...)`, fallback defaults for required env/config, tests that only assert mocks or snapshots
329- **Barrel files**: `index.ts` re-exporting everything in small directories
330331## Language: Python
332333Read `references/python.md` for the full Python pattern catalog. Key highlights:
334335- **Class-for-everything disease**: stateless classes that should be plain functions/modules
336- **Exception anti-patterns**: bare `except:` catching KeyboardInterrupt/SystemExit, `except Exception as e: logger.error(e); raise` (adds nothing), type/None checks on typed parameters (e.g., `if user_id is None` when the signature says `int`), broad try/except wrapping its own explicit `raise` statements
337- **Stale patterns**: `os.path` instead of `pathlib`, `.format()` instead of f-strings, `%` formatting, `if/elif` chains instead of `match` (3.10+), `typing.Optional[X]` instead of `X | None` (3.10+)
338- **Type hints**: `Any` used to bypass type errors, redundant hints on obvious assignments, overly complex `TypeVar` gymnastics
339- **Verbose**: manual dict/list building instead of comprehensions, nested `if` instead of early returns, `lambda` assigned to a variable (just use `def`), redundant docstrings restating the function signature
340- **Dependency creep**: `requests` for a single GET when `urllib` works, `python-dotenv` when `os.environ` is fine
341- **AI-native tells**: `dict.get(..., {})` chains laundering missing invariants, catch-log-reraise noise, mock-heavy tests with no behavioral assertion
342343## Language: Bash / Shell
344345Read `references/shell.md` for the full Shell pattern catalog. Key highlights:
346347- **Missing safety**: no `set -euo pipefail`, unquoted variables, no `shellcheck` compliance
348- **Useless use of cat**: `cat file | grep` instead of `grep file`
349- **Stale patterns**: backticks instead of `$()`, `expr` instead of `$(())`, `[ ]` instead of `[[ ]]` in bash/zsh, parsing `ls` output
350- **Over-defensive**: `if command; then ... fi` on every line instead of `set -e`, manual `$?` checks
351- **Verbose**: `echo "$var" | grep` instead of `[[ "$var" == *pattern* ]]`, external tools for built-in operations
352- **AI-native tells**: hallucinated flags/subcommands copied from adjacent CLIs, `2>/dev/null || true` used to hide uncertainty, heredoc-heavy automation instead of checked files/templates
353354## Language: Infrastructure as Code
355356Read `references/iac.md` for the full IaC pattern catalog covering Terraform, Ansible, Helm, and Kubernetes manifests. Key highlights:
357358- **Terraform**: over-modularizing, redundant `depends_on`, not using `locals`, unpinned provider versions, invented resource arguments, provider/version hallucinations
359- **Ansible**: `command`/`shell` when a module exists, `ignore_errors: true` everywhere, registering variables never used, not using handlers, invented module params or wrong collections
360- **Helm**: hardcoded values in templates, `tpl` for static strings, `.Values` spaghetti without defaults, chart version not pinned, values keys that the chart never consumes
361- **Kubernetes**: no resource requests/limits, `latest` tags, no namespace, imperative `kubectl run/create` in automation, no probes, mismatched `apiVersion`/field combinations
362363## Language: Rust
364365Read `references/rust.md` for the Rust pattern catalog. Key highlights:
366367- **Clone abuse**: `.clone()` to dodge the borrow checker - the #1 AI-Rust tell
368- **Error type proliferation**: custom error enums for every module instead of `anyhow`/`thiserror`
369- **Overly generic trait bounds**: `T: Display + Debug + Clone + Send + Sync` when only `Display` is used
370- **Verbose**: `match` with two arms instead of `if let`, explicit `return` at function end, manual Option/Result matching instead of combinators
371- **Unsafe overuse**: `unsafe` blocks without `// SAFETY:` comments, `transmute` when `as` works
372- **Stale**: `extern crate`, `#[macro_use]`, `try!()`, `lazy_static` instead of `std::sync::LazyLock` (1.80+)
373374## Language: Docker / Containers
375376Read `references/docker.md` for Dockerfile and Compose pattern catalog. Key highlights:
377378- **Fat images**: no multi-stage build, build tools in final stage, `COPY . .` before dep install (cache busting)
379- **Layer waste**: separate `RUN` per package, `ADD` for local files, `RUN cd` instead of `WORKDIR`
380- **Security**: running as root, `chmod 777`, secrets in build args/env, missing `.dockerignore`
381- **Compose bloat**: `container_name` everywhere, `restart: always` without healthchecks, `depends_on` without conditions, hardcoded ports
382- **Stale**: old base image versions, `MAINTAINER` directive, ENTRYPOINT+CMD confusion
383384## Other Languages
385386For Go and other languages without dedicated reference files: apply the universal patterns (sections 1-11) only. Note in the report that language-specific checks were skipped. Common cross-language tells still apply - over-abstraction, comment noise, cross-language leakage, schema drift, and error handling anti-patterns look similar everywhere.
387388## Research & Citations
389390Read `references/research-sources.md` for statistics, source citations, and deeper context on the "no soul" problem. Use when the user wants data to back up findings.
391392---
393394## What NOT to Flag
395396These look like slop but aren't:
397398- **Security patterns**: auth, CORS, SSRF protection, input validation at boundaries, rate limiting, TLS configuration, RBAC policies. Correct even if "defensive".
399- **Explicit types/annotations on public interfaces**: function signatures, exported types, API contracts benefit from explicitness.
400- **Abstractions that enable testing**: interfaces with one implementation for dependency injection.
401- **Workaround comments**: "works around X bug", "API requires this", "platform-specific" - institutional knowledge.
402- **Defensive checks on external data**: network responses, user input, deserialized data, third-party library output.
403- **Shell verbosity for clarity**: complex pipelines benefit from intermediate variables and comments.
404- **Terraform `count`/`for_each` on single resources**: might be conditional (`count = var.enabled ? 1 : 0`).
405- **Ansible `when` conditions that seem obvious**: often guarding against cross-platform differences.
406- **Compatibility shims**: version- or provider-specific branches may look repetitive because they support multiple real targets.
407- **Contract-level tests**: asserting exact API payloads, SQL, CLI args, or emitted metrics is fine when that contract is the thing being tested.
408409---
410411## Output Contract
412413See `skills/_shared/output-contract.md` for the full contract.
414415- **Skill name:** ANTI-SLOP
416- **Deliverable bucket:** `audits`
417- **Mode:** always-on. Every invocation emits the full contract - boxed inline header, body summary inline plus per-finding detail in the deliverable file, boxed conclusion, conclusion table.
418- **Deliverable path:** `docs/local/audits/anti-slop/<YYYY-MM-DD>-<slug>.md`
419- **Severity scale:** reduced subset of the shared scale - `P1 | P2 | P3` with slop-specific meanings (P1 fabricated/ungrounded, P2 maintainability, P3 style; see the Workflow classification). No P0: slop is never a build or security breaker - route those to **code-review** / **security-audit**.
420421## Related Skills
422423- **code-review** - finds bugs and correctness issues. Anti-slop finds quality and style issues.
424 If it would cause incorrect behavior, it's a code-review finding. If it's ugly but correct,
425 it's anti-slop.
426- **security-audit** - finds vulnerabilities. Defensive code that looks like "overkill" may be
427 correct security practice. Check the "What NOT to Flag" list before flagging security patterns.
428- **full-review** - orchestrates code-review, anti-slop, security-audit, and update-docs in
429 parallel. Anti-slop is one of the four passes.
430- **update-docs** - handles documentation maintenance. Anti-slop focuses on code quality;
431 update-docs focuses on keeping docs accurate and trimmed.
432- **anti-ai-prose** - audits prose for AI writing tells (vocabulary, syntax, tone, formatting).
433 Anti-slop audits code. Together they cover "does this repo read as machine-generated" across
434 both code and documentation.
435- **code-slimming** - handles safe-deletion and LOC-slimming passes (removing dead code, shrinking
436 file count). Use it when the goal is reducing volume; use anti-slop when the goal is quality.
437438---
439440## Reference Files
441442- `references/typescript.md` - TypeScript and JavaScript anti-slop patterns
443- `references/python.md` - Python anti-slop patterns
444- `references/shell.md` - shell and script anti-slop patterns
445- `references/iac.md` - Terraform, Ansible, Helm, and Kubernetes anti-slop patterns
446- `references/rust.md` - Rust anti-slop patterns
447- `references/docker.md` - Dockerfile and Compose anti-slop patterns
448- `references/research-sources.md` - supporting research, citations, and external context
449450---
451452## Output Format
453454````markdown
455## Anti-Slop Audit: [scope]
456457### Findings
458459#### [Category Name] ([count] items)
460461**[action]** ([severity], [axis]) `path/to/file:line` - [description]
462```[language]
463// before
464[code snippet]
465466// after
467[improved code snippet]
468```
469470### Summary
471- X findings across Y files
472- [top-level observations about codebase health]
473````
474475Keep it concise. Show the diff, not a paragraph explaining it.
476477---
478479## Rules
480481- **Keep correctness out of scope.** If it would actually break behavior, route it to code-review instead of padding this report.
482- **Flag AI-native lies even when they look polished.** Hallucinated APIs, schema drift, and self-confirming tests belong here when the problem is lack of grounding or taste rather than a demonstrated failing behavior.
483- **Keep security out of scope.** Defensive code often looks verbose on purpose. Do not flag it casually.
484- **Read before judging.** A pattern that looks generic in isolation may be justified by framework or project constraints.
485- **Ground hallucination claims.** Use local types, schema, lockfiles, generated docs, or tool help before saying a flag/resource/API is fake.
486- **Do not bury structural duplication.** If near-twin modules or repeated registry/wrapper shapes appear, surface at least one representative finding even when higher-severity hallucination findings dominate the report.
487- **Prefer concrete rewrites.** If you flag a pattern, show the simpler version.
488- **Run the AI Self-Check.** Verify findings against the checklist before returning the audit.
Run npx skillmds add majiayu000/anti-slop in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
· Audit AI-generated code slop: hallucinated APIs, over-abstraction, duplicate code, test theater, noisy comments. Triggers: 'slop', 'AI-generated code', 'cleanup', 'overengineered'. Not for prose (use anti-ai-prose). It is listed under Security on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Capability flags: makes network calls, reads secrets. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free. This skill is licensed under MIT.
majiayu000 (@majiayu000) published this skill. Their other Agent Skills are listed on their SkillMD profile.