View on GitHub →

Python quality gates for repos and teams

One deterministic quality loop for every Python PR.

Standardize lint, typecheck, test, coverage, mutation, deps, architecture, and audit across local edits, hooks, and CI. Stronger evidence for human- and AI-authored code.

uvx --from interlocks il doctor
install: uv tool install interlocks offline: interlocks warm zero runtime deps

Dispatches every gate through uvx or uv run --with at pinned versions, so the tool environment stays isolated from your project resolver. pipx install interlocks is also supported.

“One command tells every repo where the quality bar is.”

Human review cannot be the quality floor when teams and agents ship code fast. Deterministic gates catch fake confidence before it reaches CI or customers.

Proof in the terminal

No dashboard fiction. The product surface is the pass/fail output every repo sees.

local run

il check 7.4s PASS
$ il check
interlocks v0.2.1  ·  preset=baseline  ·  runner=pytest  ·  invoker=uv

── Quality Checks ──────────────────────────────────────────
  [fix]         ruff check --fix                      ok
  [format]      ruff format                           ok (2 files reformatted)

── Parallel ────────────────────────────────────────────────
  [typecheck]   basedpyright                          0 errors, 0 warnings
  [test]        pytest -q                             184 passed in 3.2s
                                                      coverage 87.4%

── Advisory ────────────────────────────────────────────────
  [deps]        deptry                                ok
  [crap]        cached (crap_max=30.0)                ok · 0 offenders

── Suppressions ────────────────────────────────────────────
  ruff : noqa              0
  basedpyright : ignore    1   interlocks/runner.py:42
  pytest.skip              2

Completed in 7.4s

failure example

il gate coverage --min=85 FAIL
$ il gate coverage --min=85
coverage                                      79.2% < required 85%
next: inspect uncovered files
$ il trust --refresh --verbose

Operate as an agent

Every workflow command emits machine-readable JSON. interlocks {check,ci,evaluate,trust,doctor,config} --json writes one JSON object to stdout. Exit codes are unchanged, and --json dominates --verbose.

interlocks check --json

--json stdout
$ interlocks check --json
{
  "command": "check",
  "schema_version": 1,
  "passed": true,
  "gates": [
    { "name": "typecheck", "status": "ok" },
    { "name": "test", "status": "ok", "detail": "184 passed" }
  ],
  "skipped": [
    { "name": "mutation", "reason": "nightly only" }
  ],
  "artifacts": [".interlocks/run-summary.json"],
  "agent": {
    "state": "attention",
    "required_actions": [],
    "recommended_actions": [
      { "command": "interlocks gate properties --profile=check", "reason": "harden new code" }
    ]
  }
}

Quality loop

Evaluate first with doctor, then check. Adopt permanently with setup only after the gate proves useful; CI and nightly keep the same evidence running after merge.

After edits

il check
LOCAL FAST GATE

Default local loop after file changes.

  • fix + format
  • typecheck + test in parallel
  • deps, cached CRAP, suppressions report
  • --changed scopes file-level gates to the diff; test, acceptance, and properties skip with a banner

Before commit

il hook pre-commit
HOOK BLOCKING

Runs on staged changes through git hook.

  • fix + format staged Python
  • re-stage formatted files
  • typecheck + tests when source changed

Pull request

il ci
CI BLOCKING

Required PR gate for repo-wide verification.

  • lint + format check
  • complexity, audit, deps, typecheck
  • coverage, CRAP, arch, acceptance

Scheduled trust

il nightly
CRON SLOW GATE

Long-running confidence check for tests.

  • coverage first
  • mutation via mutmut
  • blocks on mutation_min_score

Setup + maintenance

il setup / il clean
SETUP UTILITY

Wire feedback loops and reset generated state.

  • install git pre-commit hook
  • merge Claude Code Stop hook
  • remove caches, build artifacts, coverage, mutation state

What gets verified

Commands stay small. Stages compose them into local, hook, CI, and scheduled gates.

Command Purpose Where Gate
fix Fix lint errors with ruff. LOCALHOOK BLOCKING
fix-* (plan/rule/replay/annotate/metrics/optimize) Rule-scoped lint-fix planning, replay, annotation, metrics, and optimization. LOCAL UTILITY
format Format code with ruff. LOCALHOOK BLOCKING
lint Read-only lint check. CILOCAL BLOCKING
typecheck Run basedpyright. LOCALCI BLOCKING
test Run pytest or unittest from detected config. LOCALCI BLOCKING
coverage Run tests with threshold and uncovered listing. CINIGHTLY BLOCKING
crap Gate complex, under-tested functions. CILOCAL BLOCKING
mutation Run mutmut kill-rate checks. NIGHTLYCI ADVISORY
properties Generated-input property tests via Hypothesis. CINIGHTLY ADVISORY
deps Find unused, missing, transitive deps with deptry. LOCALCI ADVISORY
deps-freshness Check outdated dependencies with an explicit package-index lookup. LOCAL ADVISORY
audit Audit dependencies for known vulnerabilities. CILOCAL BLOCKING
arch Run import-linter architecture contracts. CILOCAL BLOCKING
acceptance Run Gherkin scenarios via pytest-bdd or behave. CILOCAL BLOCKING
trust Report coverage, CRAP, suspicious tests, hot files, next actions. LOCAL REPORT
evaluate Score static quality gaps and print CLI closure paths. LOCAL REPORT
property-candidates Rank functions for property-test hardening. LOCAL REPORT
doctor Diagnose paths, tools, venv, hooks, config. LOCAL REPORT
init Scaffold greenfield pyproject and tests. LOCAL UTILITY
init --acceptance Scaffold tests/features and step_defs. LOCAL UTILITY
presets Show or set baseline, strict, legacy, progressive preset. LOCAL UTILITY
warm Pre-fetch bundled tool wheels into ~/.cache/uv for offline runs. LOCAL UTILITY
version Print interlocks version. LOCAL REPORT
help Print command help and detected config. LOCAL REPORT

Before / after

Before

Quality depends on scattered tools, hand-maintained config, and human memory.

  • ×ruff, pyright, pytest, coverage, deptry, lizard, pip-audit, import-linter, mutmut configured by hand.
  • ×Local check differs from protected branch check.
  • ×Weak tests pass coverage until mutation or CRAP exposes fake confidence.

After

Repo gets diagnosed once. Same deterministic gate runs before review, before commit, and before merge.

  • 1il doctor detects source, tests, runner, invoker, preset, thresholds.
  • 2il setup wires local hooks, agent docs, and the Claude skill.
  • 3il check gives local pass/fail before push.
  • 4Reusable GitHub Action runs the CI gate.

Why agents need gates

Models can write plausible code. Interlocks forces evidence.

Claude Code Opus 4.8

I can write PRs fast. I still need gates that do not negotiate: lint, types, tests, coverage, mutation, deps, architecture, and audit in one loop.

interlocks makes the quality bar explicit before a human reviews.

GPT-5.5

The failure mode is not syntax. It is plausible code with shallow tests and green checks.

interlocks catches fake confidence: complex untested code, weak coverage, surviving mutants, and CI drift.

Block bad PRs in CI

Use the same CLI gate on pull requests and protected branches.

workflow

CI BLOCKING
name: interlocks
on: [push, pull_request]
jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: 0xjgv/interlocks@v1

Result: trustworthy Python PRs before human review.

Read docs on GitHub →