Avouch: A Git-Aware AST Linter That Reviews Only the Python You Changed
Avouch is a lightweight, Git-aware static analysis CLI for Python that reviews only the files your next commit will touch, using the standard library AST module and configurable limits in avouch.toml.

Most Python linters are repository-wide: they flag every issue in your codebase, including the legacy you inherited. Avouch takes a different approach. It asks Git which files your next commit will touch, parses only those with the standard ast module, and reports structural problems against limits you configure in avouch.toml.
No daemon, no network, no path lists to maintain. Run it in the seconds before git push, fix what it flags, push.
Why it exists
Avouch's core idea is that the review set is the diff, not the repository. It computes the review set from Git at run time (git diff HEAD --name-only plus untracked files), so every finding is attributable to work you are about to push, never to the legacy you inherited.
Metrics are exact. Parameter counts, nesting depth, and line spans come from the AST, not regex. If a metric cannot be computed exactly, Avouch does not claim it.
Errors are data. An unreadable or syntactically broken file becomes an ERROR entry in the report. One broken file never cancels the review of the others.
Avouch reviews; it does not gate. The exit code signals the outcome — 0 clean, 1 violations found, 2 Avouch error — but enforcement belongs in an opt-in interface, not in a tool you run before every push.
The runtime is the standard library. Three git subprocess calls and ast/tomllib. No daemon to keep alive; runtime is bounded by the size of your diff, not your repository.
Installation and quick start
Requires Python 3.10+ (rules use ast.Match; configuration uses tomllib) and Git on PATH. Install with pip install avouch.
The interface is one command with a small set of optional flags:
cd your-repo
# ... make a change ...
avouch # human report
avouch --json # one JSON document on stdout
avouch --docs # built-in documentation; no review performed
avouch --version # print the version and exit
avouch --verbose # step-by-step review details on stderr
avouch --quiet # analyze, print no report; exit code only
avouch --changed # compact added/deleted view of changed files vs HEAD
avouch --staged # review only files staged for the next commit
avouch --all-files # review every eligible Python file, not just the diff
avouch --not-git # review every eligible .py file on disk; no Git repo needed
avouch --help # every flagThe review set is defined by Git, so there is nothing to configure at invocation time. Avouch reviews tracked files modified vs. HEAD and untracked .py files. Deleted paths and non-.py files are skipped. Committed, untouched files never appear in the output. Files that look generated (generated.py, *_generated.py, codegen.py, autogen.py, …) are skipped too.
Output and CI integration
For automation and CI, --json prints the review as a single JSON document on stdout, with no human-readable text mixed in. Each violation carries the rule id, severity, message, file, component name, kind (func, class, or file), and line. The document is a stable, versioned contract: version is the schema version, tool identifies the emitter, and the same input always produces the same JSON — no colors, timestamps, or diagnostics leak in.
Exit codes behave exactly as in normal mode, so avouch --json can gate CI: parse stdout for the findings and react to the exit status (0 clean, 1 violations, 2 Avouch error).
Colors are ANSI codes emitted only when stdout is a TTY. Piped output is plain, so avouch | tee review.log and CI capture work cleanly. Runtime errors are written to stderr, so stdout stays clean for piping and --json capture.
Configuration and rules
Avouch is configured via avouch.toml, where you set limits like maximum parameter count, nesting depth, and line length. Rules are identified by IDs like SCR002 (bare except) and SCR014 (too many parameters). The tool is designed to be extensible — you can add your own rules.
Avouch is a refreshing take on Python linting: it respects your time by only reviewing what you actually changed, and it respects your codebase by not drowning you in pre-existing issues. If you're a Python developer who wants fast, diff-focused feedback before pushing, Avouch is worth a look.
Review the Python you changed, not the Python you inherited.
Source: GitHub
Discussion
0 Comments
Be the first to start the discussion.