Skip to content
codemetrics

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 — python
$ 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.

McCabe

Cyclomatic

Counts decision points flatly — 1 + one per branch (if / for / case / && / ||). It measures the number of independent paths through a function.

SonarSource

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.

brewbrew install --cask richardwooding/tap/codemetrics
gogo install github.com/richardwooding/codemetrics/cmd/codemetrics@latest
actionuses: richardwooding/codemetrics@v0.10.0

Or download a prebuilt binary for macOS, Linux, or Windows from the releases page.