complexipy: cognitive complexity for Python, implemented in Rust
Blazingly fast cognitive complexity analysis for Python, written in Rust.
At a glance
- What is it?
- complexipy is a Rust-backed Python tool that measures cognitive complexity, the readability-oriented metric from G. Ann Campbell's research, with a CLI, a Python API, a language server and CI integrations. It suits teams that want a maintainability gate rather than a branch-count check.
- Who is it for?
- complexipy is a good fit for a Python team that has tried cyclomatic complexity and found it too noisy, that wants the metric to penalise nesting and flow breaks rather than branch count, and that wants the check to run fast enough to put in a pre-commit hook rather than only in a nightly job.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A metric about readers, not about machines
The definition the project leads with is the whole point. Cognitive complexity measures how hard code is to understand by humans, not machines. The contrast is with traditional metrics like cyclomatic complexity, which account for nesting depth and control flow patterns that affect human comprehension, and the metric is inspired by G. Ann Campbell's research at SonarSource. The stated benefits follow directly from that framing. It is human-focused, penalising nesting, flow breaks and human-unfriendly logic. It gives actionable insights, identifying genuinely hard-to-maintain code. And it differs from cyclomatic complexity, which measures structural, testing and branch density, whereas this measures readability. That last distinction is the reason the tool exists at all, and the documentation links a dedicated page comparing it with Ruff's PLR0912 rule, noting the two measure different things and that you might want to use both. The project is explicit about its own status in the lineage: complexipy is an independent project inspired by the research, and it is not affiliated with or endorsed by SonarSource.
The Rust core, and the Python surface on top of it
The implementation is a Rust core with several thin surfaces around it, and the packaging explains why. The Python distribution is built with maturin, which compiles Rust into a Python extension module, so the pip install is a wheel containing compiled code rather than pure Python. The Cargo workspace is a set of crates under a crates directory, with the Python bindings coming from pyo3. The parser is not written from scratch, and that is the interesting engineering choice. The workspace pulls ruff_python_parser and ruff_python_ast directly from the Ruff repository at a pinned tag, 0.15.14, so complexipy parses Python with the same parser Ruff uses. That is a deliberate bet on a fast, correct parser rather than on a hand-rolled one, and it means the tool inherits Ruff's syntax coverage without maintaining it. The rest of the dependency list shows the scope of the tool itself: rayon for parallel work across files, crossbeam-channel for the channels between them, serde and serde_json for output, csv for tabular output, globset and ignore for path handling, clap for the command line, comfy-table and owo-colors for the terminal output, syntect for syntax highlighting, lsp-server and lsp-types for the language server mode, wasm-bindgen for the web build, and blake2 and sha2 for hashing.
The command line covers analysis, gating and diffing
The CLI examples in the readme are organised by what you want to do, and the flags matter more than the examples. Analysing the current directory is the basic case, and a custom threshold is set with the max-complexity-allowed flag. The failed flag shows the functions that exceed the threshold, and the suggest-refactors flag adds refactoring suggestions for them. The output format flag switches to JSON, which is what you want when the results feed something else. Two flags turn the tool into a gate rather than a report. The diff flag compares against a git reference, so a pull request is only blocked by the complexity the change introduces rather than by complexity that was already there. The exclude flag takes glob patterns, so a directory of generated code or a legacy module can be left out without a per-file inline ignore. The usage guide covers every flag, configuration files, snapshots, the complexity diff and inline ignores, and the repository root holds a complexipy.toml file, a complexipy.schema.json schema for it and a complexipy/ Python package directory alongside the crates.
A Python API for when the report is not the point
The Python API is small, and it is the surface to use when you are building something on top of the analysis rather than running it as a gate. The documented example imports a single function and calls it on a file:
from complexipy import file_complexity
# Analyze a file
result = file_complexity("app.py", check_script=True)
print(f"File complexity: {result.complexity}")
for func in result.functions:
print(f"{func.name}: {func.complexity}")The result object carries an overall complexity and a list of functions, each with a name and a complexity. The check_script argument is the switch that decides whether the script is treated as code to be measured, which matters for a file that is partly configuration or partly data, and the result is a plain object you can assert on, so a test suite can fail on a specific function rather than on a whole-file number. The package declares no runtime dependencies, which is a real advantage for a tool that ends up in a developer's pre-commit environment, and it declares itself typed, with a Typing Typed classifier, so the API is usable from a type checked codebase.
Four integration surfaces, one metric
The integrations are where a linter becomes a habit, and this project has four of them. The GitHub Action runs the tool on a pull request and takes the paths to check, the maximum complexity allowed and a flag to emit JSON. The pre-commit hook installs from a separate repository with the complexipy identifier, pinned to a revision. The VS Code extension is on the Visual Studio Marketplace and on OpenVSX, and it runs the complexipy language server, which means the complexipy tool itself has to be installed separately, for example with uv tool install, and the extension then updates inlay hints, hover information and warnings as you type. The general editor integration runs the same language server, complexipy lsp, and the documentation covers the setup for VS Code, Neovim and Zed. The action and the pre-commit hook catch a problem before it lands, and the language server catches it while you are writing the code, and having one metric across all three is what stops the number from meaning something different in each place. The repository also has a benchmarks directory, a web directory with a deploy script and a serve script, a build-wasm.sh for the web build, a vscode directory and a zed directory.
Versioning, compatibility and the independent-project caveat
The release cadence is fast and the versioning is honest about breaking changes. The recent releases are 8.1.0 on 2026-10-19, 8.0.1 on 2026-09-07 and 8.0.0 on 2026-09-03, with the last push on 2026-10-19, so a major version arrives every few months and the last release is the same day as the last commit. The Python side supports a wide range of interpreters, with the requires-python bound running from 3.8 up to below 3.16, and the classifiers list each version from 3.8 through 3.15, plus the CPython and PyPy implementations, and the development status is given as Production/Stable. The independence point appears in three places in the readme, in the common questions section, in the footer and in the inspiration credit, and it matters for anyone adopting it in a commercial context, because the metric is implemented independently rather than licensed from SonarSource. The repository also carries a CHANGELOG.md, a RELEASING.md, a SECURITY.md, a CODE_OF_CONDUCT.md, a CONTRIBUTING.md, a pre-commit configuration and agent instruction directories. The project is MIT licensed with the terms in a LICENSE file.
Editorial conclusion
complexipy is a good fit for a Python team that has tried cyclomatic complexity and found it too noisy, that wants the metric to penalise nesting and flow breaks rather than branch count, and that wants the check to run fast enough to put in a pre-commit hook rather than only in a nightly job. It is the wrong tool if you need SonarSource's commercial platform, since the project states it is independent and not affiliated with or endorsed by SonarSource, and it is the wrong tool if your standard is already Ruff's PLR0912 rule and you have no reason to change. It is also the wrong tool if you cannot use a compiled extension, because the Python package is a maturin build wrapping Rust and ships no runtime dependencies to make up for it. Before adopting it, read the scoring documentation rather than assuming it matches another implementation, since the metric has several published variants, and set the threshold in config rather than on the command line so every surface agrees. The project is MIT licensed, the last push was on 2026-10-19, and the current release is 8.1.0 from the same day.
Frequently asked questions
What is complexipy and how is it installed?
It is a Python library and command line tool that calculates cognitive complexity, written in Rust and distributed on PyPI. The installation options are pip install complexipy, uv add complexipy for a project dependency, or uv tool install complexipy for a standalone tool.
How does cognitive complexity differ from cyclomatic complexity?
Cognitive complexity measures how hard code is to understand by humans, and it penalises nesting depth, flow breaks and control flow patterns that affect comprehension. Cyclomatic complexity measures structural, testing and branch density instead, and the project links a page comparing the two, noting you might want to use both.
Can complexipy block a pull request that adds complex code?
Yes. The diff flag compares against a git reference so only the complexity introduced by the change counts, the max-complexity-allowed flag sets the threshold, the failed flag lists the offending functions, and the suggest-refactors flag adds refactoring suggestions. The exclude flag takes glob patterns for paths to leave out.
Is complexipy affiliated with SonarSource?
No. The project states that it is an independent project inspired by G. Ann Campbell's cognitive complexity research at SonarSource, and that it is not affiliated with or endorsed by SonarSource. The metric is its own implementation for Python.
Does complexipy work in an editor as you type?
Yes, through a language server. The VS Code extension runs the complexipy language server and updates inlay hints, hover information and warnings as you type, and the same server is used for the other editor setups, with documented instructions for VS Code, Neovim and Zed. The extension requires the complexipy tool itself to be installed as well.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rohaquinlop-complexipy)Was this useful?