Catch AI-generated code slop before it ships — a quality gate for the vibe-coding era.
Distyll analyzes pull requests for AI-generated code anti-patterns and assigns a slop score (0-100) with specific, actionable fixes. It uses AST-based pattern detection via tree-sitter to catch structural issues that traditional linters miss.
# Install globally
npm install -g distyll
# Scan a project
distyll scan .
# Or use npx without installing
npx distyll scan .Distyll ships with 12 detection rules targeting patterns unique to AI-generated code:
| Rule | What It Catches |
|---|---|
unnecessary-try-catch |
Try-catch blocks wrapping synchronous pure functions that cannot throw |
single-use-wrapper |
Functions that wrap a single call and are only used once — pointless abstraction |
verbose-comments |
Comments that restate the code verbatim (e.g., // increment counter above counter++) |
unused-imports |
Import statements for modules/symbols never referenced in the file |
single-option-object |
Options/config objects that only ever use one property — over-engineering |
redundant-else-return |
else blocks after a return statement — the else is unnecessary |
hallucinated-imports |
Imports of modules that don't exist in the project or standard library |
near-duplicate-functions |
Function bodies that are >85% similar — copy-paste with subtle variations |
over-defensive-nulls |
Null/undefined checks on values that are already guaranteed non-null |
magic-values |
Magic strings and numbers used inline instead of named constants |
dead-code-paths |
Unreachable code after unconditional return/throw/break/continue |
excessive-comments |
Files where >50% of lines have trailing comments — a hallmark of AI verbosity |
Every rule is conservative by design. The #1 complaint about existing slop detectors is false positives. Distyll only flags patterns that are clearly AI-generated bloat, not legitimate code.
Scan files or directories for slop patterns.
distyll scan . # Scan current directory
distyll scan src/ lib/ # Scan specific directories
distyll scan src/utils.ts # Scan a single file
distyll scan . --format json # JSON output
distyll scan . --threshold 50 # Exit code 1 if score > 50
distyll scan . --style # Compare against style profile
distyll scan . --verbose # Show parsing details per file
distyll scan . --quiet # Output only the score numberOptions:
-f, --format <format>— Output format:text(default) orjson-t, --threshold <number>— Exit with code 1 if slop score exceeds this value-s, --style— Compare against project style profile (rundistyll fingerprintfirst)-v, --verbose— Show AST parsing details and rule execution time per file-q, --quiet— Only output the slop score number (useful for scripting)
Scan only changed lines in a git diff. Only reports findings on new/modified code.
distyll diff # Scan unstaged changes
distyll diff --staged # Scan staged changes only
distyll diff --ref main # Diff against a branch
distyll diff --ref HEAD~3 # Diff against 3 commits agoOptions:
-s, --staged— Scan staged changes only-r, --ref <ref>— Git ref to diff against-f, --format <format>— Output format:textorjson-t, --threshold <number>— Exit with code 1 if score exceeds threshold-v, --verbose— Show detailed info-q, --quiet— Output only the score number
Install a pre-commit hook that blocks commits above a slop threshold.
distyll hook install # Default threshold: 70
distyll hook install --threshold 50 # Custom threshold
distyll hook uninstall # Remove the hookRun in CI mode with GitHub Actions-optimized output.
distyll ci # Annotations format (default)
distyll ci --format summary # Markdown summary
distyll ci --format json # JSON output
distyll ci --threshold 60 # Fail CI if score > 60
distyll ci --ref main # Diff against main branchAnalyze your codebase to build a style profile. This captures your team's actual patterns (function length, naming conventions, comment density, etc.) so --style mode can flag deviations.
distyll fingerprint # Analyze current directory
distyll fingerprint ./src # Analyze specific directoryThe profile is stored in .distyll/profile.json.
Initialize Distyll in a project. Creates .distyll.json config and .distyll/ cache directory.
distyll init # Initialize in current directory
distyll init ./my-project # Initialize in specific directoryCreate a .distyll.json file in your project root (or run distyll init):
{
"rules": {
"unnecessary-try-catch": "error",
"verbose-comments": "warn",
"magic-values": "off"
},
"threshold": 70,
"ignore": [
"**/generated/**",
"**/migrations/**"
]
}rules— Override severity or disable rules. Values:"off","warn","error"threshold— Default slop score threshold for hooks and CIignore— Additional glob patterns to exclude from scanning (node_modules, dist, build, and vendor are always excluded)
Add Distyll to your CI pipeline. Create .github/workflows/distyll.yml:
name: Distyll Slop Check
on: [pull_request]
jobs:
distyll:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '18'
- run: npm install -g distyll
- run: distyll ci --ref origin/main --threshold 50Or use the bundled action:
- uses: ./action.yml
with:
threshold: 50The slop score (0-100) is calculated from weighted findings normalized by lines of code:
- Info findings: weight 1
- Warning findings: weight 3
- Error findings: weight 5
Formula: min(100, round(weightedSum / totalLOC * 100))
| Score | Rating | Meaning |
|---|---|---|
| 0-20 | Clean | Minimal AI slop detected |
| 21-50 | Moderate | Some patterns worth reviewing |
| 51-100 | High | Significant AI-generated bloat |
- JavaScript (
.js,.mjs,.cjs) - TypeScript (
.ts,.tsx) - Python (
.py)
| Feature | Distyll | ESLint | CodeRabbit | SonarQube |
|---|---|---|---|---|
| AI slop detection | 12 rules | No | Generic | No |
| Slop score | 0-100 | No | No | Complexity only |
| Fix suggestions | Yes | Some | Yes | Some |
| Style fingerprinting | Yes | No | No | No |
| Git hook | Built-in | Via plugin | No | No |
| CI integration | Native | Native | Native | Native |
| Offline/local-first | Yes | Yes | No | Self-host |
- Node.js >= 18.0.0
- Git (for
diff,hook, andcicommands)