cyclomatic + cognitive · 17 languages
Complexity that gates your PRs.
Per-function cyclomatic and cognitive complexity in one pass — a CLI and GitHub Action that fail a pull request when the code it touches gets too gnarly. Plus a Go library whose core needs nothing but the standard library.
↑ Click a language — 17 supported, analyzed by the same tool.
$ codemetrics --top 3 . COGNITIVE CYCLOMATIC FUNCTION LOCATION 57 24 Query.add_q sql/query.py:1380 41 19 resolve_lookup template/base.py:812 29 15 parse_http_date utils/http.py:176 codemetrics: 3 finding(s)
the two metrics
Two lenses, one parse.
Most tools give you one or the other. codemetrics computes both together and reports them side by side.
Cyclomatic
Counts decision points flatly — 1 + one per branch (if / for / case / && / ||). It measures the number of independent paths through a function.
Cognitive
Weights nested control flow more heavily, so deeply-nested logic scores higher than a flat sequence with the same branch count. It tracks how hard code is to understand. Matches gocognit.
what you get
A quality gate, not just a number.
Polyglot
17 languages. Go via the stdlib go/ast; 16 more via tree-sitter — same metrics, one tool.
Quality gate
Set --max-cognitive / --max-cyclomatic; the process exits non-zero when a function is over budget.
SARIF output
--format sarif uploads straight to GitHub Code Scanning — findings land in the PR's Files-changed view.
PR mode
--diff origin/main...HEAD judges only the functions a pull request actually changes.
Baseline
Adopt on legacy code without a big-bang cleanup: record a baseline and fail only on new complexity.
Suppression
Opt a function out with //gocyclo:ignore, //nolint, or codemetrics:ignore — gocyclo/gocognit-compatible.
GitHub Action
Drop the Marketplace action into a workflow and every PR is gated — no runner setup, no Docker.
Stdlib-only core
The root library package imports only go/ast, so embedding it compiles no third-party code. Tree-sitter and the CLI's deps are opt-in.
Skips the noise
Vendored and minified files (bundled libs, *.min.js) are skipped by default, powered by projectdetect.
in your pipeline
Gate every pull request.
Add the Action and fail the check when a function the PR touches exceeds your threshold. Existing debt is left alone.
GitHub Action
name: complexity on: pull_request jobs: gate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: {fetch-depth: 0} - uses: richardwooding/codemetrics@v0.10.0 with: max-cognitive: "15"
…or the CLI, anywhere
# Fail only on functions this PR changed codemetrics --diff origin/main...HEAD \ --max-cognitive 15 . # Adopt on an existing repo via a baseline codemetrics --max-cognitive 15 \ --write-baseline .codemetrics.json . # SARIF for GitHub Code Scanning codemetrics --format sarif \ --max-cognitive 15 . > results.sarif
install
One binary, no dependencies.
Grab it however you like — the CLI ships as a single static binary.
brew install --cask richardwooding/tap/codemetricsgo install github.com/richardwooding/codemetrics/cmd/codemetrics@latestuses: richardwooding/codemetrics@v0.10.0Or download a prebuilt binary for macOS, Linux, or Windows from the releases page.