Knots
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.
Features
- Multiple Complexity Metrics: McCabe, Cognitive, Nesting Depth, SLOC, ABC, Test Scoring
- AI Cost Metrics: AIRD (reasoning difficulty) and AICP (context pressure) — ceilings calibrated on six open-source C codebases; predictive validation is a pilot so far (see Metrics Reference)
- Multi-Language: C, C++, Rust, Python, JavaScript, TypeScript, Ada, Go, Java, C#, Kotlin, Swift, PHP, Fortran, Scala, and Lua — one CLI across supported languages; calibrate thresholds for your project
- 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, and exit 3 when a selected file could not be analysed; recommended
--aird-threshold 85 - Pre-commit Hook: native integration, no shim scripts required
- Validated: McCabe agrees with pmccabe's traditional (per-
case) count on 98.00% of 30,461 C functions across six pinned corpora (nearly all differences are in functions with#ifarms); Cognitive follows the SonarSource specification, including the recursion increment other implementations omit. See Metrics Reference
Installation
Prebuilt binary from PyPI (no Rust toolchain, installs in seconds):
pipx install knots # or: uv tool install knots
From crates.io:
cargo install knots
Or from source:
git clone https://github.com/brandon-arrendondo/knots.git
cd knots
cargo build --release
Running a prebuilt binary requires no C compiler or project build system. Building from source requires Rust and a native C/C++ compiler for the bundled tree-sitter grammars.
Quick Start
# 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 (GNU xargs)
find . -type f \( -name "*.c" -o -name "*.rs" \) -print0 | xargs -0 -r knots --format ndjson > metrics.ndjson
# Testability matrix
knots -m src/main.c
The AIRD gate is calibrated mainly on C; it rarely fires on Rust or JS/TS. See ADR-0003 before choosing project thresholds.
Complexity Indicators
Based 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 |
Command-Line Options
knots [OPTIONS] [FILE]...
knots [OPTIONS] --compile-commands <FILE>
Options:
--supported-languages List compiled languages and extensions, then exit
-l, --language <LANG> Restrict analysis to a language or extension (repeatable)
-q, --quiet Suppress normal output; retain threshold violations
--score-components Add AIRD/AICP components to JSON, NDJSON, or CSV
--count-anonymous-closures Emit anonymous functions as separate entries
-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 report in multi-file text mode (opt-in)
--completion-report <FILE> Write what the scan analysed, and each file it could not, as JSON (any --format)
--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)
--tier <function|block> Select duplicate fingerprint granularity (default: function)
--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
Documentation
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
- Architecture — substrate and consumer responsibilities
- Architecture Decision Records — metric definitions and gate decisions
- Troubleshooting
Acknowledgements
knots' numbers are checked against independent tools, and several of its fixes were found by disagreeing with one of them. The comparison tables are in validation/probes/TOOLS.md and the corpus results in validation/README.md.
- pmccabe (Paul Bame,
Hewlett-Packard): the reference for McCabe complexity on C. Its separate
"traditional" and "modified" columns let knots'
switchcounting, and much else, be checked function by function across six C corpora. - SLOCCount (David A. Wheeler): the reference for physical SLOC, built on the same definition knots follows.
- cloc (Al Danial): the most widely used line counter, and the second SLOC reference.
- SLOC, also: tokei and scc.
- McCabe and Cognitive Complexity, other languages:
- lizard (Terry Yin);
- rust-code-analysis (Mozilla);
- clang-tidy's
readability-function-cognitive-complexity(LLVM); - AdaCore's gnatmetric;
- Clippy's
cognitive_complexitylint (the Rust project); - ESLint's
complexityrule; - eslint-plugin-sonarjs (SonarSource).
The metrics themselves follow their published definitions:
- T. J. McCabe, "A Complexity Measure" (1976), and G. J. Myers' extension to compound conditions (1977);
- G. Ann Campbell, Cognitive Complexity (SonarSource, version 1.7, 2023);
- R. E. Park, Software Size Measurement (CMU/SEI-92-TR-20, 1992);
- J. Fitzpatrick's ABC metric (1997).
knots parses every language with tree-sitter and its community grammars. The validation corpora are open-source projects, pinned in validation/README.md.
Upstream contributions
Fixes in other metric tools that came out of reading their sources against the published definitions, listed once the maintainers have merged them:
- multimetric: the
--bugpredict oldHalstead estimate multiplied effort by 2/3 instead of raising it to the 2/3 power (Halstead's E^(2/3)/3000). Reported in issue #213 and fixed by the maintainer in PR #214.
AI Assistance
knots was developed with assistance from Claude (Anthropic), used for code generation, the metrics and language support, bug fixes, and documentation. From October 2026, Codex (OpenAI) also contributed documentation fixes and the tooling that enforces the agent and commit guidelines. Each of its changes was reviewed before it was merged.
Many earlier commits have a Co-Authored-By: Claude trailer, but not every AI-assisted commit does, so the trailers are not a complete record. From October 2026 the contribution is acknowledged once, here, and not with a co-author trailer on each commit.
License
MIT. Copyright 2025-2026 BISSELL Homecare, Inc.
Metadata
Release files for knots 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| knots-2.0.0.tar.gz | 310.2 kB | With provenance | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| knots-2.0.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| knots-2.0.0-py3-none-musllinux_1_2_x86_64.whl | Python 3 | none | Linux musl 1.2+ x86-64 | Details |
| knots-2.0.0-py3-none-musllinux_1_2_aarch64.whl | Python 3 | none | Linux musl 1.2+ ARM64 | Details |
| knots-2.0.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64 | Details |
| knots-2.0.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | Python 3 | none | Linux glibc 2.17+ ARM64 | Details |
| knots-2.0.0-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details |
| knots-2.0.0-py3-none-macosx_10_12_x86_64.whl | Python 3 | none | macOS 10.12+ x86-64 | Details |
Total release size: 38.0 MB
Release files / knots-2.0.0.tar.gz
| Download URL | knots-2.0.0.tar.gz |
|---|---|
| Size | 310.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c0c72512ba24d465e85352558e763135fabb32b8881cf60659cc66b91a8057a6
|
|
BLAKE2b-256 checksum How to use checksums |
b7bfc910569f0f7d510f15d23ad3c89a3b73e701676517fa9cf24ac01a46806d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / knots-2.0.0-py3-none-win_amd64.whl
| Download URL | knots-2.0.0-py3-none-win_amd64.whl |
|---|---|
| Size | 5.0 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
87db130a9f5ed9a96abf4698e2f2da20bce17b16cd73572f1ad562ff19aa1b0d
|
|
BLAKE2b-256 checksum How to use checksums |
eb70d116f1094f702aeafd601c50e7c81392f8aed55c37f21aaa736cb49ba658
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / knots-2.0.0-py3-none-musllinux_1_2_x86_64.whl
| Download URL | knots-2.0.0-py3-none-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 5.6 MB |
| Tags | Linux musl 1.2+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
91ae65bd9fd394e1efdc84a0e186184abed493ed9fa6566ec60b75a424ef2ef5
|
|
BLAKE2b-256 checksum How to use checksums |
2b1de5f7e9d71c95b9117668fa1ea790ed0d2588d8fff896e3d616adcbbd6228
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / knots-2.0.0-py3-none-musllinux_1_2_aarch64.whl
| Download URL | knots-2.0.0-py3-none-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 5.4 MB |
| Tags | Linux musl 1.2+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
ab4b634a5cd15dcd6fc2c6eb85673cb7b477f3e4f534d1ced1c657f0fb03e933
|
|
BLAKE2b-256 checksum How to use checksums |
26098d89417f66936f00ae14960549427473c67ccf105085047cb7d8f34e3749
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / knots-2.0.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | knots-2.0.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 5.4 MB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
3026f10afca7f467331927af733bc89faad1ad3d1b559217bd133b3b0d0083be
|
|
BLAKE2b-256 checksum How to use checksums |
2230e214bd5f3965971aae564b0aba30ac7638bf69e88eae98e8d396129fee4e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / knots-2.0.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | knots-2.0.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 5.5 MB |
| Tags | Linux glibc 2.17+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
b5e0cd146ac573e6c7d0f0b1e4d8a3fba26fca4c67e36d71d2a35bf2ad06d6bc
|
|
BLAKE2b-256 checksum How to use checksums |
95ae614a6d4e7eb04e0baa1c233ce430fa5e89a1fd161941fb7eadc69cba9738
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / knots-2.0.0-py3-none-macosx_11_0_arm64.whl
| Download URL | knots-2.0.0-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 5.4 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
46c7e5318005e9ad1403338d7ab569ce3c3bfc50259a4ce277f7d85919398d37
|
|
BLAKE2b-256 checksum How to use checksums |
f08eea4ea1911b59b2efc9c83e763c3a15f5965ed087283c53c53403c8dbd064
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / knots-2.0.0-py3-none-macosx_10_12_x86_64.whl
| Download URL | knots-2.0.0-py3-none-macosx_10_12_x86_64.whl |
|---|---|
| Size | 5.3 MB |
| Tags | Python 3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
8c60d9d35a0bd8001521b3ef313a16101cd9ff061fbc3b48ded34fecc01fa604
|
|
BLAKE2b-256 checksum How to use checksums |
3f4335c28891ee524736f5cad0a49334b0f2c8f2d555a5cea941f93d9250ee74
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logSecurity for knots 2.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 8 files in this release have been uploaded with provenance metadata.
Attestation for knots-2.0.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.