A fast multi-language code complexity analyzer built on tree-sitter. Knots measures traditional complexity metrics alongside two AI-specific cost scores — AIRD (AI Reasoning Difficulty) and AICP (AI Context Pressure) — to identify which functions are genuinely expensive to modify with AI assistance.
- Multiple Complexity Metrics: McCabe, Cognitive, Nesting Depth, SLOC, ABC, Test Scoring
- AI Cost Metrics: AIRD (reasoning difficulty) and AICP (context pressure) — corpus-validated against 32,205 functions across 6 open-source C codebases
- Multi-Language: C, C++, Rust, Python, JavaScript, TypeScript, Ada, Go, Java, C#, Kotlin, Swift, PHP, Fortran, Scala, and Lua — same metrics and thresholds across all supported languages
- Testability Matrix: Categorize functions by complexity and testability
- Multiple Output Formats: text, SARIF, JSON, NDJSON (find/xargs-composable), CSV
- CI Threshold Enforcement: exit 1 on any threshold violation; recommended
--aird-threshold 85 - Pre-commit Hook: native integration, no shim scripts required
- Validated: McCabe matches pmccabe exactly; Cognitive matches Mozilla rust-code-analysis at 1.004× mean ratio (11,365 Rust functions)
Prebuilt binary from PyPI (no Rust toolchain, installs in seconds):
pipx install knots # or: uv tool install knotsFrom crates.io:
cargo install knotsOr from source:
git clone https://github.com/brandon-arrendondo/knots.git
cd knots
cargo build --releaseNo C compiler or build system required.
# Single file
knots src/main.c
# Recursive directory
knots -r src/
# CI gate — fail if any function has AIRD > 85
knots -r src/ --aird-threshold 85
# Adopt the gate on a legacy codebase: snapshot today, then fail only on regressions
knots -r src/ --aird-threshold 85 --baseline .knots-baseline.json --write-baseline
knots -r src/ --aird-threshold 85 --baseline .knots-baseline.json
# Gate only the functions you actually touched (no new debt in this change)
knots -r src/ --aird-threshold 85 --changed
# SARIF for GitHub Code Scanning
knots -r --format sarif src/ > knots.sarif
# Corpus analysis — one JSON record per function
find . -name "*.c" -o -name "*.rs" | xargs knots --format ndjson > metrics.ndjson
# Testability matrix
knots -m src/main.cBased on max(McCabe, cognitive):
| Range | Indicator | Meaning |
|---|---|---|
| 1–10 | 😊 Good | Low complexity, easy to maintain |
| 11–20 | 😐 Okay | Moderate complexity, monitor |
| 21–49 | 😠 Bad | High complexity, consider refactoring |
| 50+ | 😢 Critical | Urgent refactoring needed |
knots [OPTIONS] [FILE]...
knots [OPTIONS] --compile-commands <FILE>
Options:
-r, --recursive Recursively process all supported source files in directories
-v, --verbose Show detailed per-function analysis
-m, --matrix Show testability matrix categorization
--compile-commands <FILE> Use compile_commands.json to get file list
--include <FILE> Include filter rules from JSON file (whitelist)
--exclude <FILE> Exclude filter rules from JSON file (blacklist)
--exclude-path <PATTERN> Exclude files whose path matches this regex (repeatable)
--format <FORMAT> text (default) | sarif | json | ndjson | csv
--mccabe-threshold <N> Exit 1 if any function exceeds this McCabe complexity
--cognitive-threshold <N> Exit 1 if any function exceeds this cognitive complexity
--nesting-threshold <N> Exit 1 if any function exceeds this nesting depth
--sloc-threshold <N> Exit 1 if any function exceeds this SLOC count
--abc-threshold <F> Exit 1 if any function exceeds this ABC magnitude
--return-threshold <N> Exit 1 if any function exceeds this return count
--aird-threshold <N> Exit 1 if any function exceeds this AIRD (AI Reasoning Difficulty) score (recommended: 85)
--aicp-threshold <N> Exit 1 if any function exceeds this AICP (AI Context Pressure) score
--external-calls-threshold <N> Exit 1 if any function exceeds this external call count
--unreachable-blocks-threshold <N> Exit 1 if any function has more than this many unreachable (dead-code) basic blocks (C/C++/Rust only)
--report <FILE> Write a detailed per-function report to this file (opt-in)
--baseline <FILE> Ratchet mode: gate only on regressions vs. this snapshot (see docs/baseline.rst)
--write-baseline Snapshot current scores to --baseline and exit without gating
--since <REF> Gate only functions overlapping lines changed since this git ref
--changed Gate only functions changed in the working tree (sugar for --since HEAD)
--explain <METRIC> Explain a metric (e.g. aird, aicp) and how to lower it, then exit
--find-duplicates Report structurally duplicated functions across the corpus (--recursive only)
--include-fixture-pairs Keep tests/pass vs tests/fail fixture pairs in --find-duplicates output (excluded by default)
--include-trivial-duplicates Keep small-body, low-repeat groups (getters, one-assert tests) in --find-duplicates output (excluded by default)
--dump-duplicates <FILE> Write a JSON snapshot of --find-duplicates results, for later comparison via --diff-duplicates
--diff-duplicates <BEFORE> <AFTER> Compare two --dump-duplicates snapshots and summarize resolved/new/shrank/grew groups; exits without needing corpus files
-j, --jobs <N> Parallel analysis threads (0 = auto-detect, 1 = sequential, default: 0)
-h, --help Print help
-V, --version Print version
Full documentation is in the docs/ directory (Sphinx/RST):
- Installation
- Quick Start & Usage Examples
- CLI Reference
- Metrics Reference — AIRD/AICP formulas, corpus validation
- Output Formats — JSON schema, SARIF, NDJSON corpus patterns
- CI Integration — GitHub Actions, pre-commit hook
- Baseline / Ratchet Mode — adopt the gate on legacy code, fail only on regressions
- Filter Rules —
--include/--excludewhitelists/blacklists - knots.toml & Inline Suppression — TOML thresholds/exclusion,
tools:off/tools:suppresscomments - Test Quality Analysis — knots-test-complexity companion tool
- Alternatives Comparison — vs. lizard, rust-code-analysis, clippy; cognitive algorithm differences
- Troubleshooting
MIT