Desloppify

An agent harness that turns vibe-coded slop
into engineer-grade beautiful code

pip install desloppify — 2,500+ stars — 29 languages — 1,600+ files

github.com/peteromallet/desloppify

ELI5: Explain Like I'm 5

What is desloppify, and why should anyone care?

The Problem: Slop Code

When you ask an AI to build something, it works fast — but it cuts corners you can't see.

What "vibe coding" gives you

  • Working features, fast
  • Code that runs but nobody can read
  • Copy-pasted logic everywhere
  • Dead code that does nothing
  • Errors handled 3 different ways

What happens over time

  • Every new change risks breaking something
  • Even the AI gets confused by its own code
  • Technical debt snowballs silently
  • The codebase "rots" from the inside
The core insight: LLMs are good at spotting bad code now, if you ask the right questions. Desloppify is the framework for asking those questions systematically.

What Desloppify Does

Think of it as a personal code quality coach that your AI coding agent uses while it works.

1. Scan

Looks at every file and finds problems — dead code, duplicated logic, confusing names, security issues, untested functions.

2. Score

Gives your codebase a single number (0–100). A score above 98 means "a senior engineer would call this beautiful."

3. Fix Loop

Tells your agent exactly what to fix next. Fix it, mark it done, ask for the next thing. Repeat until the score is high.

The Loop: scan → fix → rescan

You paste one prompt. The agent does the rest.

# You paste this into your AI coding agent:
"I want you to improve the quality of this codebase."
"Install and run desloppify."

# The agent runs:
pip install desloppify
desloppify scan --path .     # find all the problems
desloppify next              # what should I fix first?

# Agent fixes the issue, then:
desloppify resolve <id>     # mark it done
desloppify next              # what's next?

# ...repeat until the score hits your target
Key idea: The agent is the primary user, not you. Desloppify gives the agent a north-star score to optimize toward, and the tools to get there.

Why Can't You Just Game the Score?

Most code quality tools let you cheat. Suppress a warning, score goes up. Desloppify is different.

Anti-gaming tricks

  • Marking an issue "won't fix" widens the gap between your lenient and strict scores
  • 75% of the score comes from subjective LLM review — you can't suppress that
  • Re-reviewing a dimension can lower your score if the LLM finds new problems
  • Scores near target values get flagged as suspicious

What actually works

  • Fix the dead code
  • Unify error handling patterns
  • Improve naming and abstractions
  • Add tests for uncovered logic
  • Actually make the code better
The only way to improve the score is to genuinely improve the code.

Full Technical Deep Dive

Architecture, scoring model, detectors, review pipeline, and anti-gaming

Repository at a Glance

1,609
files in the repo
29
languages supported
0
core dependencies
2,500+
GitHub stars

Pure Python (3.11+), MIT licensed, installable via pip install desloppify[full]. Zero required dependencies — optional extras for tree-sitter, Pillow, bandit, PyYAML.

Design philosophy: "The primary user is an AI coding agent, not a human." Every CLI output, every command, every state file is optimized for agent consumption.

Architecture: Four Layers

The codebase is organized into clean architectural layers with strict dependency boundaries.

Layer Package Responsibility
app/ desloppify/app/ CLI parser, command handlers, output rendering. Thin orchestrators only.
engine/ desloppify/engine/ Detectors, scoring, state management, work queue, plan operations.
intelligence/ desloppify/intelligence/ LLM review pipeline, dimension prompts, holistic context, narratives.
languages/ desloppify/languages/ Language plugins — per-language detectors, fixers, review data, tree-sitter specs.

Plus base/ for shared primitives (config, discovery, registry, search, text utilities) and data/ for global configuration data.

The Workflow Pipeline

Desloppify defines a strict five-phase lifecycle. Work progresses in order:

Scan
→
Score
→
Review
→
Triage
→
Execute
→
Rescan
  • Scan — runs mechanical detectors across the codebase (dead code, duplication, complexity, naming, security)
  • Score — computes dimension scores weighted across mechanical (25%) and subjective (75%) findings
  • Review — LLM assesses subjective quality: naming, abstractions, error handling, module boundaries
  • Triage — prioritize, cluster related issues, enrich with implementation detail, build execution queue
  • Execute — next → fix → resolve → repeat
  • Rescan — verify improvements, catch cascading effects, feed the next cycle

CLI: 23 Commands in 4 Categories

The CLI is built on argparse with allow_abbrev=False to prevent ambiguous option shortcuts.

Workflow

scanRun all detectors
statusShow current score + state
nextGet next fix from queue
backlogView full issue backlog
planManage execution plan

Investigation

showInspect specific issues
treeFile structure view
vizVisualizations
detectRun single detector

Improvement

autofixAuto-apply safe fixes
suppressMark false positives
resolveMark issue as fixed
reviewTrigger LLM review
moveFile reorganization

Configuration

configSettings management
update-skillInstall agent guide
langsLanguage support info
excludePath exclusions

Mechanical Detectors

The engine/detectors/ package contains 15+ detectors that find issues machines can identify with certainty.

DetectorWhat it finds
dupesDuplicated code blocks (15K-line implementation)
orphanedDead / unreachable code
complexityHigh cyclomatic complexity
couplingExcessive module coupling
godsGod classes / objects
largeOversized files
namingPoor naming conventions
single_useSingle-use abstractions
DetectorWhat it finds
flat_dirsFlat directory structure issues
coverageImport/dependency coverage gaps
test_coverageMissing test coverage
securitySecurity pattern violations
signatureFunction signature problems
passthroughPassthrough wrappers
graphDependency graph analysis
review_coverageReview completeness gaps

Each detector produces structured FunctionInfo / ClassInfo / ComplexitySignal objects with file, line, body, hash, and metrics.

Language Plugin Architecture

29 languages supported through a layered plugin framework in languages/.

Full plugin depth (8 languages)

Custom detectors, fixers, review data, and tree-sitter specs:

TypeScript Python C# C++ Dart GDScript Go Rust

Generic support (21 languages)

Generic linter + tree-sitter analysis:

Ruby Java Kotlin PHP Swift Scala Haskell Lua Elixir Zig +11 more

Plugin structure

languages/
  _framework/         # shared base
    base/             # abstract classes
    treesitter/       # tree-sitter parsing
    review_data/      # dimension JSONs
    registry/         # plugin registration
  typescript/
    detectors/        # TS-specific detectors
      deps/           # dependency analysis
      patterns/       # pattern matching
      react/          # React-specific
      security/       # TS security rules
      smells/         # code smell detection
    fixers/           # auto-fix logic
    review_data/      # TS review dimensions
    syntax/           # syntax parsing
  python/
    detectors/        # Python-specific
    fixers/
    review_data/

The Scoring Model: The North Star

A single number (0–100) that correlates with genuine codebase quality. The scoring formula uses dimension-weighted aggregation.

Score computation

For each dimension with n detectors:

# Per dimension:
total_checks = sum(detector.potential)
weighted_fails = sum(detector.weighted_failures)

dim_score = (
  (total_checks - weighted_fails)
  / total_checks
) * 100

# Overall:
score = weighted_average(dim_scores,
                         dim_weights)

Three modes computed simultaneously: lenient strict verified_strict

ScoreBundle dataclass

Each scan produces six metrics:

  • dimension_scores — lenient mode
  • strict_dimension_scores — strict mode
  • verified_strict_dimension_scores — most conservative
  • overall_score — primary health metric
  • objective_score — mechanical only
  • strict_score — the one that matters
The strict score is the target. It counts unresolved items as open debt, giving an honest health metric.

Dimension Weighting: 25/75 Split

The scoring deliberately weights subjective review 3x heavier than mechanical detection.

Mechanical Dimensions 25%

DimensionFocus
File HealthFile size, structure, organization
Code QualityComplexity, coupling, dead code
DuplicationCopy-paste detection
Test HealthCoverage gaps, test quality
SecurityPattern-based vulnerability scan

Subjective Dimensions 75%

DimensionWeight
High Elegance22.0 — architectural quality
Mid Elegance22.0 — module-level design
Contracts & Type SafetyModerate
Design CoherenceModerate
Naming QualityLow (nudge)
AI-Generated DebtLow (nudge)
Why 75% subjective? The mechanical stuff (dead imports, duplication) is necessary but insufficient. Real code quality lives in naming, abstractions, error handling patterns, and module boundaries — things only an LLM reviewer can assess.

The LLM Review Pipeline

The intelligence/ package handles subjective code review via structured LLM prompts.

Review architecture

intelligence/
  review/
    dimensions/      # what to review
      data.py        # JSON loader + cache
      holistic.py    # loads dimensions
      lang.py        # per-lang overrides
    _context/        # what to show the LLM
    _prepare/        # prompt assembly
    context_holistic/
      budget/        # token budgeting
      clusters/      # issue clustering
      selection/     # file selection
    context_signals/ # mechanical evidence
    importing/       # score importing
  narrative/         # progress stories

How it works

  • Dimensions are loaded from JSON configs with per-language overrides (append, remove, customize prompts)
  • Context building selects relevant files, clusters issues, manages token budgets
  • Mechanical evidence is injected as signals so the LLM has objective data alongside the code
  • Holistic review assesses cross-cutting concerns (architecture, patterns, consistency)
  • Supports --external-runner for Claude, Cursor, Codex, Copilot, and more
Dimension prompts are defined in JSON, not hardcoded. Languages can override base dimensions via dimensions.override.json.

Anti-Gaming: The Hard Part

The difference between a useful signal and a vanity metric. Desloppify's scoring resists every obvious gaming strategy.

Gaming prevention mechanisms

StrategyCounter-measure
Suppress warnings"Won't fix" items widen the lenient/strict score gap
Hit exact targetsmatches_target_score() flags scores within 5% of targets as suspicious
Avoid re-reviewRe-reviews can lower scores if the LLM finds new issues
Game mechanical onlyMechanical is only 25% of the score
Skip attestationAttestation requirements verify fixes were real

Three scoring modes

  • Lenient — counts only clearly-failed checks
  • Strict — unresolved items count as debt
  • Verified Strict — most conservative, requires verification

The gap between lenient and strict scores is itself a meaningful signal. A large gap means lots of swept-under-the-rug issues.

From the dev philosophy: "Anti-gaming stuff matters to us a lot — it's the difference between a useful signal and a vanity metric."

State Persistence & Work Queue

All state lives in .desloppify/ so progress survives across agent sessions.

State management

  • Centralized in engine/_state/
  • Issue tracking with full lifecycle: open → queued → in-progress → resolved
  • Score snapshots for trend tracking
  • Suppression records with scoring impact
  • Cross-platform persistence handling

Work queue

  • Lives in engine/_work_queue/
  • Prioritized execution queue from triage
  • Only triaged items appear in next
  • Cluster-based grouping of related issues

Plan system

engine/_plan/
  operations/   # queue manipulations
  policy/       # ordering rules
  schema/       # plan data models
  sync/         # state synchronization
  triage/       # 6-stage triage pipeline

Triage has six substages that the agent works through:

  • Categorize findings
  • Reflect on patterns
  • Organize into clusters
  • Enrich with implementation detail
  • Prioritize by impact
  • Build execution queue

The next Command: Core of the Loop

The most important command. It drives the entire execution cycle.

Queue build + render flow

# Internal flow of `desloppify next`:

_build_and_render_queue_view()
  |
  +-- parse options
  +-- check guardrails
  +-- load execution plan
  +-- _resolve_queue_items()
  +-- apply cluster filtering
  |
  +-- if empty:
  |   _render_empty_queue_view()
  |     display score context
  |     show plan information
  |
  +-- else:
      _render_terminal_queue_view()
        render items + nudges
        compute narratives
        emit resolve command

What the agent sees

A structured output containing:

  • The specific issue to fix, with file path and line numbers
  • Implementation guidance from triage enrichment
  • The resolve command to run when done
  • Queue progress (e.g., "3 of 47 resolved")
  • Nudges — contextual hints (rescan reminders, score updates)
Three public entry points: build_and_render_execution_queue(), build_and_render_backlog_queue(), and a generic build_and_render_queue() with configurable views via QueueViewConfig.

Multi-Agent Support

Desloppify installs a SKILL.md workflow guide tailored to each agent platform.

Supported agents

AgentSkill file
Claude CodeCLAUDE.md
CursorCURSOR.md
CodexCODEX.md
CopilotCOPILOT.md
DroidDROID.md
WindsurfWINDSURF.md
GeminiGEMINI.md

How skill installation works

# Install the full workflow guide:
desloppify update-skill claude

# This writes a CLAUDE.md file that
# teaches the agent the full workflow:
#   - When to scan vs. rescan
#   - How to interpret scores
#   - The next/resolve loop
#   - Triage substages
#   - Anti-gaming awareness
The skill file is a 13K+ character comprehensive guide. It's not a simple cheat sheet — it teaches the agent the full methodology, including when not to substitute its own analysis.

Autofix & Structural Moves

Two powerful remediation tools beyond the manual fix loop.

Autofix

Safe, mechanical fixes the tool can apply directly:

app/commands/autofix/
  apply_flow.py      # forward fix pipeline
  apply_retro.py     # retroactive fixes
  fixer_selection.py # choose right fixer
  preview.py         # dry-run preview
  • Two modes: flow (apply forward) and retro (retroactive cleanup)
  • Fixer selection matches issues to the right language-specific fixer
  • Preview mode for dry-run inspection
  • Per-language fixers in languages/*/fixers/

Move

Structural reorganization of files and modules:

app/commands/move/
  planning.py    # plan the restructure
  directory.py   # directory-level moves
  language.py    # language-aware moves
  apply.py       # execute the plan
  reporting.py   # report what changed
  • Language-aware: updates imports when files move
  • Directory-level or file-level granularity
  • Planning phase before execution
  • Full reporting of what changed

Scorecard & Badge Generation

Visual output for tracking progress and displaying quality publicly.

The scorecard

  • Generated via app/output/scorecard_parts/
  • Uses Pillow (optional) for image generation
  • Shows score, dimension breakdown, and trend
  • Designed for README badges and GitHub profiles
  • Left panel with score primitives + right panel with dimension detail

Score projection

  • Projects future scores based on queue progress
  • "If you fix these 12 items, your score goes from 78 to 85"
  • Motivates the agent to keep going

Output pipeline

app/output/
  scorecard_parts/
    # Left panel: score visualization
    # Right panel: dimension breakdown
    # Projection: future estimate
    # Drawing primitives

# Badge for your README:
# Shows your current desloppify score
# as a visual badge
From the README: "A score above 98 should correlate with a codebase a seasoned engineer would call beautiful."

Testing & Quality Infrastructure

Desloppify dogfoods its own methodology with extensive testing.

Test organization

tests/
  base/          # base utility tests
  commands/      # CLI command tests
  core/          # engine core tests
  detectors/     # detector unit tests
  engine/        # engine integration
  intelligence/  # review pipeline tests
  lang/          # per-language tests
  narrative/     # narrative tests
  plan/          # plan system tests
  review/        # review tests (deep)
  scan/          # scan workflow tests
  scoring/       # scoring formula tests
  state/         # state persistence tests
  workflows/     # end-to-end workflows
  snapshots/     # snapshot testing

CI pipeline

  • GitHub Actions with CI + integration workflows
  • Import linting via .github/importlinter.ini enforces architectural boundaries
  • Ruff linter (Python 3.11, 88-char lines)
  • mypy type checking on command modules
  • Snapshot tests for CLI output stability
  • Per-language test directories

Noteworthy test files

  • review_commands_cases.py — 97K lines of test cases
  • test_holistic_review.py — 60K lines
  • test_scoring.py — 34K lines

Key Design Decisions

Zero dependencies by default

Core package has zero required dependencies. Tree-sitter, Pillow, bandit, and PyYAML are all optional extras. This minimizes install friction for agents.

Agent-first, human-second

CLI output, state format, and skill files are all optimized for LLM consumption. The dev philosophy explicitly states the human is the secondary user.

No API stability promises

The team changes implementations freely when improvements emerge. No backward compatibility guarantees — the tool evolves fast.

Thin command handlers

Command files in app/commands/ are thin orchestrators. Business logic lives in engine/ and intelligence/.

Dynamic imports at extension points only

Language plugins use dynamic imports, but only at defined registration boundaries. No hidden dynamic imports elsewhere.

Regression tests protect refactoring

Snapshot tests and extensive test suites ensure the aggressive refactoring pace doesn't break behavior.

From Vibe Coding to Vibe Engineering

The philosophical shift this tool embodies.

Vibe Coding

"Gets things built fast. But the codebases it produces tend to rot in ways that are hard to see and harder to fix — not just the mechanical stuff like dead imports, but the structural kind. Abstractions that made sense at first stop making sense."

Vibe Engineering

"An agent with the right framework can hold a codebase to a real standard, the kind that used to require a senior engineer paying close attention over months."

The Bet

"The hope is that anyone can use this to build something a seasoned engineer would look at and respect. That's the bar we're aiming for."

Key Takeaways

  • Agent harness — gives AI coding agents a north-star score to optimize toward
  • 25/75 scoring split — mechanical detection + subjective LLM review
  • Anti-gaming by design — the only way up is to genuinely improve the code
  • 29 languages — with 8 at full plugin depth
  • Persistent state — chips away across sessions via a prioritized work queue
  • 1,600+ files of well-structured Python with zero core dependencies

pip install desloppify[full]  •  github.com/peteromallet/desloppify  •  Discord community