AI Slop Cleaner: Automating Your Codebase Hygiene

Dev.to / 4/30/2026

💬 OpinionDeveloper Stack & InfrastructureTools & Practical Usage

Key Points

  • The article presents slop-cleaner, a CLI tool that automates codebase hygiene by finding unused imports, dead functions/classes, and overly complex functions using tree-sitter AST analysis rather than regex.
  • It automatically fixes only high-confidence issues (notably unused imports) while flagging medium-confidence findings (dead code and high cyclomatic complexity) for human review.
  • The tool uses a five-phase pipeline—Audit, Analyze, Clean, Verify—parsing Python and TypeScript/TSX files, building a cross-project call graph, and applying changes as atomic patches.
  • slop-cleaner includes safety mechanisms: it backs up files before writing and rolls changes back automatically if the test suite fails, helping prevent silent regressions.
  • Complexity thresholds (default cyclomatic complexity > 10) are used to prioritize refactoring candidates without making risky automatic removals.

Every codebase accumulates clutter over time. An import left behind after a refactor. A helper function that nothing calls anymore. A method that grew too complex to reason about. None of it breaks anything immediately, but it slows down every developer who reads through it, and it silently raises the cost of every future change.

The usual fix is a manual review pass. Someone spends an hour looking for unused imports, searching for dead functions, flagging complexity hotspots. It is tedious, inconsistent, and happens far less often than it should.

slop-cleaner is a CLI tool that does this automatically. It detects unused imports, dead functions and classes, and over-complex code using tree-sitter AST analysis (not regex) so it never removes an import that appears in a docstring or string annotation. Every patch is atomic: backed up before writing, and rolled back automatically if your test suite fails.

What slop-cleaner Detects and Fixes

slop-cleaner targets three specific categories of clutter that accumulate in every codebase:

Unused imports: Imports left behind after refactors. These are detected at HIGH confidence and removed automatically. The tool handles single-line imports, selective removal from from X import A, B blocks where only one name is unused, and multi-line from X import (...) blocks where individual lines are surgically removed.

Dead functions and classes: Defined but never called anywhere in the codebase. These are detected at MEDIUM confidence and flagged in the report for human review. The tool builds a full call graph across all symbols before making this determination.

Over-complex functions: Functions with cyclomatic complexity above the threshold (default 10). These are flagged at MEDIUM confidence for manual refactoring. The tool never auto-removes a function, complexity is a signal that something needs attention, not a safe automatic fix.

HIGH confidence issues are fixed automatically. MEDIUM confidence issues are always left to human judgment.

The 5-Phase Pipeline

Everything slop-cleaner does runs as a five-phase pipeline. Each phase feeds into the next, and every patch is atomic, backed up before writing and rolled back automatically if your tests fail.

Audit:Parses every .py and .ts/.tsx file with tree-sitter. Collects unused imports at HIGH confidence and high-complexity functions at MEDIUM confidence.

Analyze: Builds a call graph across all symbols in the project. Identifies dead code, defined but never called.

Clean: Applies HIGH-confidence patches atomically. Handles single-line and multi-line from X import (...) blocks. Backs up each file before writing.

Verify: Runs your test suite with pytest. On any failure, rolls back every patched file to its backup automatically. Returns exit code 1 so CI catches it.

Document: Generates three Markdown reports: ARCHITECTURE.md, FUNCTION_MAP.md, and SLOP_REPORT.md covered in detail below.

What Gets Fixed Automatically vs. Flagged

The distinction matters. HIGH confidence patches are cases where the tool is certain removal is safe. MEDIUM confidence cases, dead code and complexity could have dynamic dispatch, reflection, or other patterns that make automatic removal risky. The tool flags these and leaves the decision to you.

Edge Cases Handled

One of the hardest parts of detecting unused imports is knowing when a name that looks unused is actually needed. slop-cleaner handles these correctly:

These are exactly the cases where regex-based tools get it wrong. Because slop-cleaner parses an actual AST, it understands the difference between a name appearing inside a string and a name being used as an identifier.

Installation

git clone https://github.com/your-org/slop-cleaner
cd slop-cleaner

# Create and activate a virtual environment
python3 -m venv .venv
source .venv/bin/activate      # macOS / Linux
# .venv\Scripts\activate       # Windows

# Install the tool and its dependencies
pip install -e .

This registers two CLI commands: slop-audit and slop-clean.
Dependencies installed automatically via pyproject.toml:

Note for modern Linux (Ubuntu 23.04+, Debian 12+): system Python blocks global pip install. Always use a virtual environment as shown above, or use pipx install . to install the CLI tools globally without a venv.

To run the test suite:

pip install -e ".[test]"   # adds pytest + pytest-cov
pytest                     # runs tests/test_parsers.py (22 tests)

Quick Start

# Audit a project — report issues, exit 1 if any found (CI-friendly)
slop-audit path/to/project/

# Audit a single file
slop-audit src/services/user_service.py

# Full clean — audit, fix, verify tests, generate docs
slop-clean path/to/project/

# Dry run — show what would change without touching files
slop-clean path/to/project/ --dry-run

# Write audit JSON for tooling integration
slop-audit path/to/project/ --output report.json

Commands

slop-audit
slop-audit scans a file or directory and prints a table of all issues found without touching anything. It exits with code 1 if issues are found, making it a clean CI gate.

slop-audit <target> [--output JSON] [--threshold N] [--verbose]

Exit codes: 0 = clean, 1 = issues found.

slop-clean
slop-clean runs the full 5-phase pipeline. Always run --dry-run first on an unfamiliar project, it shows exactly what patches would be applied without touching any file.

slop-clean <target> [--output DIR] [--threshold N] [--dry-run] [--verbose]

Exit codes: 0 = success, 1 = rollback was triggered.

Generated Output

After slop-clean runs, the --output directory contains three reports:

After slop-clean runs, the --output directory contains three reports:

slop-output/
├── ARCHITECTURE.md   — file tree + Mermaid dependency graph
├── FUNCTION_MAP.md   — every symbol with start line and complexity score
└── SLOP_REPORT.md    — issue summary, patches applied, dead-code candidates

ARCHITECTURE.md gives a structural overview of the codebase with a visual Mermaid call graph, useful for understanding how the project fits together at a glance.

FUNCTION_MAP.md is a complete index of every function and class with its start line and complexity score. For large codebases, this is the fastest way to see where complexity is concentrated.

SLOP_REPORT.md is the actionable output: what was fixed automatically, what was flagged for manual review, and which dead-code candidates need a human decision.

Trying It on the Example Projects

Two sample projects ship in examples/ so you can try the tool immediately after installing:

# Audit only — no test verification needed
slop-audit examples/todo_app/ --verbose
slop-audit examples/event_pipeline/ --verbose

# Full clean — dry run first, then apply
slop-clean examples/todo_app/ --dry-run
slop-clean examples/todo_app/

To run the example test suites directly, change into the project directory first so their imports resolve correctly:

cd examples/todo_app && pytest tests/ -v
cd examples/event_pipeline && pytest tests/ -v

todo_app is a sample Python app with intentional slop, a good first run to see exactly what the tool catches. event_pipeline covers tricky import patterns like aliases, multi-line imports, and string annotations, designed to show the AST analysis handling edge cases correctly.

CI Integration

slop-audit drops directly into CI as a quality gate. It exits 1 if any issues are found, failing the workflow step automatically:

# .github/workflows/quality.yml
jobs:
  slop-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pip install -e .
      - run: slop-audit src/ --threshold 12

This catches unused imports and complexity regressions on every pull request before they get merged into the main branch.

Project Structure

slop-cleaner/
├── cli/
│   └── main.py               — entry points + rich-formatted output
├── engines/
│   ├── auditor.py            — Phase 1 · AST-based issue detection
│   ├── analyzer.py           — Phase 2 · call-graph + dead-code finder
│   ├── cleaner.py            — Phase 3 · atomic patch application
│   ├── verifier.py           — Phase 4 · pytest runner + rollback
│   └── documenter.py         — Phase 5 · Markdown report generator
├── parsers/
│   ├── python_parser.py      — tree-sitter Python wrapper
│   └── typescript_parser.py  — tree-sitter TypeScript/TSX wrapper
├── examples/
│   ├── todo_app/             — sample Python app with intentional slop
│   └── event_pipeline/       — sample project with tricky import patterns
├── assets/
│   ├── pipeline.svg          — 5-phase flow diagram
│   ├── features.svg          — feature overview infographic
│   └── before-after.svg      — code transformation visual
└── tests/
    └── test_parsers.py       — 22 tests covering the parsers

The structure maps cleanly to the five phases, one engine per phase, two parsers for Python and TypeScript/TSX, and a single CLI entry point that ties them together.

How I Built This Using NEO

This tool was designed, built, debugged, and refined entirely using NEO, a fully autonomous AI engineering agent that writes, runs, and iterates on real code without hand-holding.

Every engine, every edge-case fix, and every SVG was produced by NEO in a single session. The five-phase pipeline, the tree-sitter AST parsers for Python and TypeScript, the atomic patch application with backup and rollback, the call graph builder, the pytest runner with automatic rollback on failure, and the three Markdown report generators all of it built end-to-end from a high-level problem description.

How You Can Use and Extend This With NEO

Use it as a CI quality gate on every pull request:
Drop slop-audit into your CI pipeline. Every PR gets checked for unused imports and complexity regressions before it touches main. The exit code 1 on issues means it fails the build automatically, no configuration beyond one workflow step. It is already wired for this out of the box.

Use it before a major refactor:
Before starting a large refactor, run slop-clean on the codebase. It removes accumulated import clutter, flags dead code that no longer needs to be worked around, and generates a complexity map. You go into the refactor with a cleaner starting point and a clear picture of where complexity lives.

Use it to onboard onto an unfamiliar codebase:
Run slop-audit on a project you have just inherited and read SLOP_REPORT.md. You get a structured list of unused imports, dead functions, and complexity hotspots, a map of technical debt you can act on rather than discovering piece by piece while working in the code.

Use it to generate a documentation baseline for a legacy project:
Run slop-clean and read ARCHITECTURE.md and FUNCTION_MAP.md. You get a file tree, a visual call graph, and a complete index of every symbol with its complexity score. For a project with no existing documentation, that is a meaningful starting point.

The tool is also designed to be extended and NEO can take any of these further without starting from scratch:

JavaScript/JSX parser- Two parsers already exist (python_parser.py, typescript_parser.py) following the same tree-sitter wrapper pattern. A third for JavaScript/JSX follows the same interface and plugs into all five engines immediately.

Additional complexity metrics- auditor.py already tracks cyclomatic complexity. Additional metrics like function length follow the same detection pattern and surface automatically in FUNCTION_MAP.md and the audit output once added.

Auto-fix for dead code- dead code is currently flagged at MEDIUM confidence and left to human judgment. For clearly dead private functions confirmed unreachable by the call graph, automatic removal is a natural next step built directly on the existing analyzer.py and cleaner.py infrastructure.

Pre-commit hook- slop-audit already exits 1 on issues. A small wrapper that hooks into the existing CLI entry point brings slop detection into the local development loop before anything reaches CI.

Final Notes

Code clutter is not a cosmetic problem. Unused imports add noise to every code review. Dead functions add surface area that has to be mentally accounted for. High-complexity functions resist change and hide bugs. slop-cleaner addresses all three automatically, with AST-level precision that regex-based tools cannot match, and with a test-verification step that means it never leaves your codebase in a worse state than it found it.
The code is at https://github.com/your-org/slop-cleaner
You can also build with NEO in your IDE using the VS Code extension or Cursor.