🐷 Sloppylint
Detect AI-generated code anti-patterns in your Python codebase.
Catches AI-specific anti-patterns that traditional linters miss
⚡ Quick Start
pip install sloppylint
sloppylint .
# Output:
# CRITICAL (2 issues)
# ============================================================
# src/api.py:23 mutable_default_arg
# Mutable default argument - use None instead
# > def process(items=[]):
#
# src/db.py:15 bare_except
# Bare except catches everything including SystemExit
# > except:
#
# SLOPPY INDEX
# ══════════════════════════════════════════════════
# Information Utility (Noise) : 24 pts
# Information Quality (Lies) : 105 pts
# Style / Taste (Soul) : 31 pts
# Structural Issues : 45 pts
# ──────────────────────────────────────────────────
# TOTAL SLOP SCORE : 205 pts
#
# Verdict: SLOPPY
🤔 Why Sloppylint Exists
Traditional linters catch style and syntax issues. But AI-generated code introduces new failure patterns they weren't designed to detect:
- Hallucinated imports - packages and functions that don't exist
- Cross-language leakage -
.push(),.equals(),.lengthin Python - Placeholder code -
pass,TODO, functions that do nothing - Confident wrongness - code that looks right but fails at runtime
Sloppylint targets these AI-specific patterns that escape Pylint, Flake8, and code review.
🎯 What It Catches
The Three Axes of AI Slop
| Axis | What It Detects | Examples |
|---|---|---|
| 📢 Noise | Debug artifacts, redundant comments | print(), # increment x above x += 1 |
| 🤥 Lies | Hallucinations, placeholders | def process(): pass, mutable defaults |
| 💀 Soul | Over-engineering, bad style | God functions, deep nesting, hedging comments |
| 🏗️ Structure | Anti-patterns | Bare except, star imports, single-method classes |
📥 What You Put In
# Scan a directory
sloppylint src/
# Scan specific files
sloppylint app.py utils.py
# Only high severity issues
sloppylint --severity high
# CI mode - exit 1 if issues found
sloppylint --ci --max-score 50
# Export JSON report
sloppylint --output report.json
📤 What You Get Out
| Output | Description |
|---|---|
| 🎯 Issues by Severity | Critical, High, Medium, Low |
| 📊 Slop Score | Points breakdown by axis |
| 📋 Verdict | CLEAN / ACCEPTABLE / SLOPPY / DISASTER |
| 📁 JSON Report | Machine-readable for CI/CD |
🔍 Pattern Examples
Critical Severity
# 🚨 mutable_default_arg - AI's favorite mistake
def process_items(items=[]): # Bug: shared state between calls
items.append(1)
return items
# ✅ Fix: Use None and initialize inside
def process_items(items=None):
if items is None:
items = []
items.append(1)
return items
# 🚨 bare_except - Catches SystemExit, KeyboardInterrupt
try:
risky_operation()
except: # Bug: swallows Ctrl+C!
pass
# ✅ Fix: Catch specific exceptions
try:
risky_operation()
except ValueError as e:
logger.error(f"Invalid value: {e}")
High Severity
# 🚨 pass_placeholder - AI gave up
def validate_email(email):
pass # TODO: implement
# 🚨 hedging_comment - AI uncertainty
x = calculate() # should work hopefully
💰 The Value
🔍 Catch AI mistakes before they hit production
Why This Matters
| Problem | Impact | Sloppylint Catches |
|---|---|---|
| Mutable defaults | Shared state bugs | ✅ Critical alert |
| Bare except | Swallows Ctrl+C | ✅ Critical alert |
| Placeholder functions | Runtime failures | ✅ High alert |
| Hallucinated imports | ImportError in prod | ✅ High alert |
| Wrong language patterns | JS/Java/Ruby/Go/C#/PHP in Python | ✅ High alert |
| Unused imports | Code bloat | ✅ Medium alert |
| Dead code | Maintenance burden | ✅ Medium alert |
| Copy-paste code | Maintenance nightmare | ✅ Medium alert |
Research Says
- 20% of AI package imports reference non-existent libraries — sloppylint catches these
- LLMs leak patterns from other languages they were trained on — sloppylint catches 100+ of these
- 66% of developers say AI code is "almost right" (the dangerous kind)
🛠️ CLI Commands
sloppylint . # 🔍 Scan current directory
sloppylint src/ tests/ # 📁 Scan multiple directories
sloppylint --severity high # ⚡ Only critical/high issues
sloppylint --lenient # 🎯 Same as --severity high
sloppylint --strict # 🔬 Report everything
sloppylint --ci # 🚦 Exit 1 if any issues
sloppylint --max-score 50 # 📊 Exit 1 if score > 50
sloppylint --output report.json # 📋 Export JSON report
sloppylint --ignore "tests/*" # 🚫 Exclude patterns
sloppylint --disable magic_number # ⏭️ Skip specific checks
sloppylint --version # 📌 Show version
✅ Features
| Feature | Description | Status |
|---|---|---|
| 🌐 Multi-Language Detection | Catches patterns from JS, Java, Ruby, Go, C#, PHP | ✅ 100+ patterns |
| 🔍 Hallucinated Imports | Detect non-existent packages | ✅ Done |
| 📦 Unused Imports | AST-based detection | ✅ Done |
| 💀 Dead Code | Unused functions/classes | ✅ Done |
| 🔄 Duplicate Detection | Cross-file copy-paste | ✅ Done |
| 🎨 Rich Output | Colors and tables (optional) | ✅ Done |
| ⚙️ Config Support | pyproject.toml configuration | ✅ Done |
Language Patterns Detected
LLMs are trained on code from many languages. When generating Python, they sometimes produce patterns from other languages:
| Language | Example Mistakes | Python Fix |
|---|---|---|
| JavaScript | .push(), .length, .forEach() |
.append(), len(), for loop |
| Java | .equals(), .toString(), .isEmpty() |
==, str(), not obj |
| Ruby | .each, .nil?, .first, .last |
for loop, is None, [0], [-1] |
| Go | fmt.Println(), nil |
print(), None |
| C# | .Length, .Count, .ToLower() |
len(), len(), .lower() |
| PHP | strlen(), array_push(), explode() |
len(), .append(), .split() |
🚫 What Sloppylint Is Not
Sloppylint does not replace:
- Human code review
- Traditional linters (Pylint, Flake8, Ruff)
- Type checkers (mypy, pyright)
- Security scanners (Bandit, Semgrep)
It complements them by catching patterns these tools miss—patterns uniquely common in AI-generated code.
📦 Installation
# Install from PyPI
pip install sloppylint
# With colored output (recommended)
pip install sloppylint[rich]
# With all optional features
pip install sloppylint[all]
# Or install from source for development
git clone https://github.com/rsionnach/sloppylint.git
cd sloppylint
pip install -e ".[dev]"
⚙️ Configuration
Configure via pyproject.toml:
[tool.sloppy]
ignore = ["tests/*", "migrations/*"]
disable = ["magic_number", "debug_print"]
severity = "medium"
max-score = 100
ci = false
format = "detailed" # or "compact" or "json"
🤝 Contributing
git clone https://github.com/rsionnach/sloppylint.git
cd sloppylint
pip install -e ".[dev]"
pytest tests/ -v # 68 tests should pass
See AGENTS.md for coding conventions and pattern implementation guide.
📄 License
MIT
🙏 Acknowledgments
Inspiration
- KarpeSlop - The original AI Slop Linter for TypeScript
- Andrej Karpathy's commentary on AI-generated code quality
Research
- Counterfeit Code - MIT research on "looks right but doesn't work" patterns
- Package Hallucinations - USENIX study on hallucinated dependencies
Metadata
Release files for sloppylint 0.5.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sloppylint-0.5.1.tar.gz | 40.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sloppylint-0.5.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 71.1 kB
Release files / sloppylint-0.5.1.tar.gz
| Download URL | sloppylint-0.5.1.tar.gz |
|---|---|
| Size | 40.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fed93df618661b7b4578f0bc64e6a7f6d44de0a3e74b7ad7a43c2fd153200e85
|
|
BLAKE2b-256 checksum How to use checksums |
d54750bfc21e24a92258eba8d12341882f79320d63a71934262d694d32c61938
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Dec 21, 2025.
Transparency logRelease files / sloppylint-0.5.1-py3-none-any.whl
| Download URL | sloppylint-0.5.1-py3-none-any.whl |
|---|---|
| Size | 30.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0ee19622ecd030b3411d58524bde27e7bb3fbffe211f0fff625506814aa95a88
|
|
BLAKE2b-256 checksum How to use checksums |
6b15c715233472d7f7ed175a7208769f417fce1fb5bc98af9208c6c6b835cf7d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Dec 21, 2025.
Transparency log