Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

“Send in your skeletons Sing as their bones go marchin’ in again The need you buried deep The secrets that you keep are ever ready Are you ready? I’m finished makin’ sense Done pleading ignorance, that whole defense Spinning infinity, boy The wheel is spinnin’ me, it’s never ending, never ending Same old story” — Foo Fighters

Getting Started

This guide walks you from a fresh install to a passing pretender check in a real repository. It covers the six steps most teams need on day one.

Prerequisites

  • Rust toolchain (stable) — install via rustup.rs
  • Git ≥ 2.x — required for --diff-only and hook installation
  • Internet access for the initial cargo install

1. Install

cargo install pretender

Verify the install:

pretender --version

2. Initialise your repository

Run the interactive wizard from the root of your repository:

pretender init

The wizard will:

  1. Ask which languages your project uses
  2. Suggest threshold values based on project size
  3. Write pretender.toml to the repo root
  4. Offer to install the pre-commit hook
  5. Offer to generate a CI workflow file

A minimal generated pretender.toml looks like:

[pretender]
mode = "tiered"
languages = ["auto"]

[thresholds]
cyclomatic_max = 10
cognitive_max  = 15

See the Configuration reference for every available key.


3. Run your first check

pretender check .

pretender check . scans all files in the given paths. To check only files changed relative to origin/main:

pretender check . --diff-only

Reading the output

⚠ src/parser.py — parse_token(): cyclomatic 14 > 10
  role: test
  parse_token: cyclomatic=14, cognitive=8, assertions=0, function_lines=15, params=2, nesting_max=2, abc=3.46
    ADVISORY cyclomatic 14 > 10
SymbolMeaning
⚠Advisory — metric exceeds the configured threshold (tiered mode)
✗Violation — metric exceeds the threshold in gate mode

In gate mode every violation exits non-zero. In the default tiered mode advisories are printed but exit is still zero.


4. Fix a violation

Suppose parse_token() scores cyclomatic=14 against a threshold of 10. Extract the per-branch logic into helpers to bring each function under the threshold:

Before — one function with 14 branches:

def parse_token(token, context, strict):
    if token.type == "string":
        if strict and not token.value.startswith('"'):
            raise ValueError("unquoted string")
        return token.value.strip('"')
    elif token.type == "number":
        try:
            return int(token.value)
        except ValueError:
            return float(token.value)
    # … six more branches omitted for brevity

After — each helper is cyclomatic ≤ 3:

def _parse_string(token, strict):
    if strict and not token.value.startswith('"'):
        raise ValueError("unquoted string")
    return token.value.strip('"')

def _parse_number(token):
    try:
        return int(token.value)
    except ValueError:
        return float(token.value)

def parse_token(token, context, strict):
    if token.type == "string":
        return _parse_string(token, strict)
    elif token.type == "number":
        return _parse_number(token)
    # …

Recheck after refactoring:

pretender check src/parser.py

Adopting a gate baseline

Some violations are legitimate but hard to fix right now, and mechanical changes (a tree-wide reformat, a generated file) shouldn’t read as “new” violations forever. check --adopt writes the current scan’s violations into a gate baseline — pretender-baseline.json, next to pretender.toml:

pretender check --adopt
# ✓ adopted 3 findings into pretender-baseline.json (file_lines 1, function_lines 2)

Commit that file. From then on, pretender check --mode gate fails only on genuinely new violations — findings whose stable ID (path, function name, rule — deliberately not line numbers) is not in the baseline. Known violations pass with a summary line:

→ gate: 3 known (baselined), 0 new

Without a baseline file, gate mode keeps its fail-closed behavior: any violation fails. A corrupt or unreadable baseline also fails the check rather than silently degrading. Adopted findings still appear in reports and resolution tracking — the baseline changes gate semantics, not visibility. Refresh the baseline by re-running with --adopt.


5. Install the pre-commit hook

Keep violations from reaching the repository by running pretender before each commit:

pretender hooks install

This writes a .git/hooks/pre-commit script that runs pretender check --staged on the files you are about to commit. To remove it:

pretender hooks uninstall

6. Add CI integration

Generate a GitHub Actions workflow:

pretender ci generate github

This writes .github/workflows/pretender.yml. The workflow runs pretender check on every pull request and, if mutation testing is configured, gates merges on the mutation score defined by thresholds.mutation_min in your pretender.toml.

For mutation testing details, see Mutation testing. To gate on mutation score in CI, set thresholds.mutation_min in pretender.toml — the generated workflow picks it up automatically.


Next steps

TopicDocument
All pretender.toml keys and defaultsConfiguration reference
Mutation testing flags and JSON outputMutation testing
Writing custom metric pluginsWriting plugins
Language-specific tracked nodeslanguages/

Ecosystem

pretender is part of the charly-vibes Tool Ecosystem — the map shows how it relates to its sibling tools.