"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
Why: code quality regressions slip in because complexity metrics live in dashboards nobody checks — pretender puts cyclomatic/cognitive/abc/params gates directly into CI, over exactly the code that changed, with CI configs generated for you. Status: beta · init/report/ci-generate shipped · Motivation & design · charly-vibes Tool Ecosystem
pretender will enable development teams using CI to detect structural quality regressions before merge by reducing the rate of undetected complexity increases to <5% of all PRs within 3 months of adoption, as measured by the ratio of CI-pretender-flagged issues vs. post-merge quality incidents, compared to baseline (no pretender).
Pretender is a Rust CLI for structural code-quality checks across multiple languages.
V=$(basename "$(curl -fsSLI -o /dev/null -w '%{url_effective}' \
https://github.com/charly-vibes/pretender/releases/latest)" | sed 's/^v//')
TGT="$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/^x86_64$/amd64/; s/^aarch64$/arm64/')"
curl -fsSL "https://github.com/charly-vibes/pretender/releases/download/v${V}/pretender_${V}_${TGT}.tar.gz" | tar xz
chmod +x pretender && sudo mv pretender /usr/local/bin/cargo install pretenderInstalls the pretender binary.
brew tap charly-vibes/charly
brew install pretenderscoop bucket add charly https://github.com/charly-vibes/scoop-charly.git
scoop install pretendergit clone https://github.com/charly-vibes/pretender
cd pretender
cargo build --release| Command | Description |
|---|---|
pretender init |
Interactive wizard: write pretender.toml, install hook, generate CI |
pretender check <paths...> |
Fast pass/fail scan against configured thresholds |
pretender doctor [--json] |
Diagnose configuration, hooks, and plugin health (warns if hook installed but no config) |
pretender complexity <path> |
Show cyclomatic complexity per function, sorted worst-first |
pretender report |
Render cached last check as human, markdown, or HTML |
pretender duplication <paths...> |
Structural clone detection via AST subtree hashing |
pretender mutation <paths...> |
Mutation testing wrapper (mutmut / cargo-mutants / Stryker / PIT) |
pretender hooks install|uninstall [hook] |
Install or remove a git hook (pre-commit, pre-push; default pre-commit) |
pretender ci generate github |
Emit .github/workflows/pretender.yml |
pretender explain <metric> |
Print definition, threshold, and citation for a metric |
pretender feedback [--dry-run] [--from-last-error] |
File a structured issue against upstream repo |
pretender completions <shell> |
Generate shell completion scripts (bash, zsh, fish, etc.) |
These flags are accepted before or after any subcommand:
--verbose, -v Increase output verbosity
--quiet, -q Suppress non-error output
--json, -j Machine-readable JSON output (auto-detected for non-TTY stdout)
--human Human-readable text output (default for TTY)
pretender check <paths...> [flags]
--format human|json|sarif Output format (default: human)
--output <path> Write report to file instead of stdout
--mode guidance|tiered|gate Override pretender.toml mode (default: gate —
advisory modes require --advisory-until DATE)
--advisory-until <DATE> Advisory lease expiry (ISO YYYY-MM-DD) for
tiered/guidance; expired lease fails closed
--staged Check only git-staged files
--diff-only Check only files changed vs --diff-base
--diff-base <ref> Base ref for --diff-only (default: origin/main)
| Metric | Formula | Default threshold |
|---|---|---|
cyclomatic |
1 + decision points | 10 |
cognitive |
Nesting-weighted branch sum | 15 |
abc |
√(A²+B²+C²) | 30 |
function_lines |
end_line − start_line + 1 | 40 |
file_lines |
Total lines in file | 400 |
nesting_max |
Maximum control-flow depth | 3 |
params |
Formal parameter count | 4 |
min_assertions |
Assertions per test function | 1 (test role) |
Run pretender explain <metric> for full definition and citation.
Python, Rust, Go, JavaScript, TypeScript, Java, Ruby, C, C++
[pretender]
mode = "gate" # gate (default, fail-closed) | tiered | guidance
# advisory_until = "2027-03-31" # REQUIRED for tiered/guidance — dated
# # downgrade; expired lease fails closed
languages = ["auto"]
exclude = ["vendor/**", "node_modules/**", "**/*_generated.*"]
respect_gitignore = true # skip git-ignored dirs (target/, vendor/, …) when walking
[thresholds]
cyclomatic_max = 10
cognitive_max = 15
function_lines_max = 40
file_lines_max = 400
nesting_max = 3
params_max = 4
abc_max = 30
[thresholds.test]
cyclomatic_max = 3
cognitive_max = 5
min_assertions = 1
[thresholds.library]
exported_cyclomatic_max = 8
exported_params_max = 3
exported_lines_max = 30
[bands]
cyclomatic = { green = 10, yellow = 15, red = 20 }
cognitive = { green = 15, yellow = 25, red = 40 }A canonical template with all sections documented (roles, thresholds,
coupling, duration check, bands, plugins, output) is available at
templates/pretender.toml.example.
Start from there when configuring a new project.
just build
just test
just lint
just ci # full verification pipeline
just preflight # pre-PR checksAll the code in this repository was generated by a large language model. This is not a confession, nor an apology. It's a fact, like the one that says water boils at a hundred degrees at sea level: neutral, technical, and with consequences one discovers later.
What the human did is what tends to happen before and after things come into existence: thinking. Reviewing requirements, arguing about edge cases, understanding what needs to be built and why, deciding how the system should behave when reality —which is capricious and does not read documentation— confronts it with situations nobody anticipated. The hours of planning, of design, of reading specifications until exhaustion dissolves the boundary between understanding and hallucination.
The LLM writes. The human knows what it should say.
There is a distinction, even if looking at the commit history makes it hard to find. The distinction is that a machine can produce correct code without understanding anything, the same way a calculator can solve an integral without knowing what time is. Understanding what that integral is for, whether it actually solves the problem, whether the problem was the right problem to begin with — that remains human territory. For now.
Rendered docs are generated artifacts; the repository sources are authoritative — edit the repo sources, not the rendered output.