Agentic code quality linter — catches slop before it becomes architectural rot
Project description
slop
Agentic code quality linter — catches slop before it becomes architectural rot.
slop is a language-agnostic linter that detects structural quality defects across a codebase using established software metrics. It ships with opinionated defaults tuned for AI-assisted development, where code rot accumulates faster than in human-only workflows.
One CLI. One config file. Ten rules. Exit code 0 or 1.
Installation
pip install agent-slop-lint
For full setup instructions — system dependencies, pre-commit hooks, CI pipelines, and agent skill integration — see the setup guide. For threshold tuning, rule-by-rule explanations, and lax/default/strict profiles — see the configuration reference.
This installs slop and its Python dependency aux-skills (the computational backend that provides all metric kernels).
System dependencies
slop's metric kernels shell out to system tools that must be installed separately:
| Tool | Purpose | Install |
|---|---|---|
ripgrep (rg) |
Content search, symbol reference counting | apt install ripgrep / brew install ripgrep |
fd (fd or fdfind) |
File discovery | apt install fd-find / brew install fd |
| git | Hotspot churn analysis (git log) | apt install git / brew install git |
| Python 3.10+ | Runtime | python.org |
Tree-sitter grammars (for AST-based metrics like CCX, CK, Halstead, NPATH) are bundled as Python wheels by aux-skills — no manual grammar installation needed.
Verify
slop rules # list all rules and thresholds
aux doctor # check system tool availability
Alternative: install script
git clone https://github.com/JordanGunn/agent-slop-lint.git
cd agent-slop-lint
./scripts/install.sh # checks deps, installs everything, verifies PATH
Windows: Use .\scripts\install.ps1 instead.
Quick start
# Run all rules with defaults
slop lint
# See what's available
slop rules
# Generate a config file to customize
slop init
Rules
| Rule | Default | What it measures | Citation |
|---|---|---|---|
complexity.cyclomatic |
CCX > 10 | Per-function path count | McCabe 1976 |
complexity.cognitive |
CogC > 15 | Per-function reading difficulty | Campbell 2018 |
complexity.weighted |
WMC > 50 | Per-class aggregate method complexity | Chidamber & Kemerer 1994 |
hotspots |
14d window | Files that are complex AND growing fast | Tornhill 2015 |
packages |
D' > 0.7 | Package design distance from the Main Sequence | Martin 1994 |
deps |
any cycle | Dependency cycles between modules | — |
orphans |
disabled | Unreferenced symbols (advisory, needs human review) | — |
class.coupling |
CBO > 8 | Classes coupled to too many other classes | Chidamber & Kemerer 1994 |
class.inheritance.depth |
DIT > 4 | Inheritance hierarchies that are too deep | Chidamber & Kemerer 1994 |
class.inheritance.children |
NOC > 10 | Base classes with too many direct subclasses | Chidamber & Kemerer 1994 |
Configuration
slop loads config from (in priority order):
--config <path>flag.slop.tomlin the project rootpyproject.toml[tool.slop]section- Built-in defaults
Generate a starter config:
slop init
.slop.toml
root = "."
# languages = ["python", "typescript"]
# exclude = ["**/test_*", "**/vendor/**"]
[rules.complexity]
enabled = true
cyclomatic_threshold = 10
cognitive_threshold = 15
weighted_threshold = 50
severity = "error"
[rules.hotspots]
enabled = true
since = "14 days ago"
min_commits = 2
fail_on_quadrant = ["hotspot"]
severity = "error"
[rules.packages]
enabled = true
max_distance = 0.7
fail_on_zone = ["pain"]
severity = "warning"
[rules.deps]
enabled = true
fail_on_cycles = true
severity = "error"
[rules.orphans]
enabled = false
min_confidence = "high"
severity = "warning"
[rules.class]
enabled = true
coupling_threshold = 8
inheritance_depth_threshold = 4
inheritance_children_threshold = 10
severity = "error"
CLI reference
slop lint Run all enabled rules
slop lint --root ./src Override root directory
slop lint --output json JSON output (for agents/CI)
slop lint --output quiet Summary only (one line)
slop lint --max-violations 0 Show all violations (no cap)
slop lint --no-color Disable ANSI colors
slop check complexity Run one category
slop check complexity.cyclomatic Run one rule
slop check class.inheritance Run a subcategory
slop init Generate .slop.toml
slop rules List rules with thresholds
slop schema Config schema as JSON
Exit codes
| Code | Meaning |
|---|---|
0 |
No violations |
1 |
One or more violations found |
2 |
Configuration or runtime error |
Output modes
human (default) — grouped by category and sub-rule, top 5 violations per rule with ...and N more, colored when connected to a terminal.
json — structured JSON with per-rule violations, summaries, and metadata. Designed for agent consumption and CI pipelines.
quiet — one-line summary: 53 violations | 2 advisories | FAIL
Language support
| Language | Extensions | Complexity | Hotspots | Packages | Deps | Class |
|---|---|---|---|---|---|---|
| Python | .py |
yes | yes | yes | yes | yes |
| JavaScript | .js, .mjs, .cjs |
yes | yes | — | yes | yes |
| TypeScript | .ts, .tsx |
yes | yes | — | yes | yes |
| Go | .go |
yes | yes | yes | yes | yes |
| Rust | .rs |
yes | yes | — | — | yes |
| Java | .java |
yes | yes | — | yes | yes |
packages (Martin metrics) currently supports Go and Python only. Other languages' files are excluded from the relevant rules, not errored.
Why 14 days?
Tornhill's canonical hotspot window is 1 year, calibrated for human release cycles. slop defaults to 14 days because agentic code rot accumulates in days, not months — an agent can dump 200 lines of private helpers into a file in a single session, and the architectural damage is immediate. A 1-year window on an agent-assisted repo drowns the recent signal in human-era noise. Widen to "90 days ago" for human-pace repos, or override with --since / rules.hotspots.since.
Architecture
slop is a thin orchestration layer. The computational backend is aux-skills, which provides deterministic metric kernels built on tree-sitter, ripgrep, fd, and git. slop wraps those kernels with a linter interface: declarative config, threshold checking, human/JSON/quiet output, and CI exit codes.
No metric computation happens in slop itself. When aux-skills gains a new kernel, slop gains a new rule with zero kernel work.
Acknowledgments
slop implements metrics from established software engineering research. Full citations are in NOTICE.
| Metric | Author(s) | Year |
|---|---|---|
| Cyclomatic Complexity | Thomas J. McCabe | 1976 |
| Cognitive Complexity | G. Ann Campbell (SonarSource) | 2018 |
| CBO, DIT, NOC, WMC | Shyam R. Chidamber & Chris F. Kemerer | 1994 |
| Instability, Abstractness, D' | Robert C. Martin | 1994, 2002 |
| Hotspot analysis | Adam Tornhill | 2015 |
| Dependency cycle detection | Robert E. Tarjan | 1972 |
These are mathematical formulas computed from source code structure. slop implements them independently via tree-sitter AST traversal — no code from the original authors' implementations is used.
License
Apache 2.0 — see LICENSE
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agent_slop_lint-0.4.0.tar.gz.
File metadata
- Download URL: agent_slop_lint-0.4.0.tar.gz
- Upload date:
- Size: 65.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e354a69f0abbea2fc68ddf632aa7050f891ce86280a1708f55ab5b8cb3da16ff
|
|
| MD5 |
42c2d10d23a41f9bb49f2db33914a940
|
|
| BLAKE2b-256 |
00aa0975c95471c31509c3c28e7a6835a907d188bb3c586cadc55e34ca4a1fdf
|
Provenance
The following attestation bundles were made for agent_slop_lint-0.4.0.tar.gz:
Publisher:
publish.yml on JordanGunn/agent-slop-lint
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agent_slop_lint-0.4.0.tar.gz -
Subject digest:
e354a69f0abbea2fc68ddf632aa7050f891ce86280a1708f55ab5b8cb3da16ff - Sigstore transparency entry: 1320908346
- Sigstore integration time:
-
Permalink:
JordanGunn/agent-slop-lint@03e49d90fc8e6edf8c07ef4e3645cc8cee12e94e -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/JordanGunn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@03e49d90fc8e6edf8c07ef4e3645cc8cee12e94e -
Trigger Event:
push
-
Statement type:
File details
Details for the file agent_slop_lint-0.4.0-py3-none-any.whl.
File metadata
- Download URL: agent_slop_lint-0.4.0-py3-none-any.whl
- Upload date:
- Size: 40.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7aca7b3aee6ac6dc6190b8f0afe8fa9c003ad80c0278d87010b666958950687b
|
|
| MD5 |
950cdb60e11b3eebfad910de7dcff0d1
|
|
| BLAKE2b-256 |
c4e499cbd088d8dcecceb0571d5361c4c7698f2b5dee1bc0f0879e0433b04578
|
Provenance
The following attestation bundles were made for agent_slop_lint-0.4.0-py3-none-any.whl:
Publisher:
publish.yml on JordanGunn/agent-slop-lint
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agent_slop_lint-0.4.0-py3-none-any.whl -
Subject digest:
7aca7b3aee6ac6dc6190b8f0afe8fa9c003ad80c0278d87010b666958950687b - Sigstore transparency entry: 1320908496
- Sigstore integration time:
-
Permalink:
JordanGunn/agent-slop-lint@03e49d90fc8e6edf8c07ef4e3645cc8cee12e94e -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/JordanGunn
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@03e49d90fc8e6edf8c07ef4e3645cc8cee12e94e -
Trigger Event:
push
-
Statement type: