zerum 0.5.0

Deterministic Python code governance: ~75 checks, profiles, Ruff orchestration, remediation prompts
Documentation

Zerum

v0.5.0 ships ~75 native checks (ZR001–ZR510), explainable findings (curated copy for tier-1 rules; AST-precise fallbacks elsewhere), quiet default / full strict profiles, optional Ruff orchestration, human / json / sarif output, and --remediation-prompt — a deterministic markdown brief for LLM/editor agents (no model call in Zerum). Install via PyPI, Homebrew, crates.io, or GitHub Releases.

Zerum is not a Ruff replacement. It focuses on maintainability, consistency, architecture boundaries, and deterministic AI-slop patterns.


Install

Pick one. After install you get a zerum command on your PATH.

Standalone binary

Download a release archive for your OS/arch from GitHub Releases, extract, and put zerum on your PATH.

Homebrew (tap formula; after the formula is published):

brew install latentmeta/tap/zerum

crates.io (requires Rust 1.70+):

cargo install zerum --locked

Python (recommended for most Python projects)

No Rust toolchain required — prebuilt wheels:

pip install zerum

Isolated tool installs:

pipx install zerum
# or
uv tool install zerum

Verify:

zerum --version
zerum --help

Quick start

cd your-python-project

# Optional: write a starter zerum.toml (default profile)
zerum init

# Run checks on the project
zerum check .

# Write a remediation prompt for an LLM / editor agent
zerum check . --remediation-prompt

# Browse the catalog and learn a rule
zerum list-checks
zerum explain ZR001

Exit codes for zerum check:

Code Meaning
0 No issues
1 Issues found
2 Operational error (bad path, CLI error, etc.)

Using Zerum

Check a project

zerum check .
zerum check path/to/package
zerum check src/

Human-readable output is the default. Each finding includes rule id, location, explanation, and remediation.

Remediation prompt (v0.5.0)

Zerum can save a deterministic markdown prompt from its findings — grouped by check type, ordered by severity (critical → info), with shared remediation text and source snippets. Zerum does not call an LLM; you paste the file into Cursor, ChatGPT, or another agent.

zerum check . --remediation-prompt
# → zerum-remediation-prompt.md

zerum check . --remediation-prompt fixes.md
zerum check . --profile strict --remediation-prompt fixes.md

Typical workflow:

  1. zerum check . --remediation-prompt fixes.md
  2. Open fixes.md in your editor / agent and ask it to apply the remediations
  3. Re-run zerum check . until clean

The prompt includes:

  • Goal and constraints (minimal edits, preserve APIs)
  • Summary counts and a type index ordered by severity
  • Findings grouped by check id, shared explanation/remediation once per type
  • Per-occurrence location, message, and source context
  • Instructions to re-run Zerum after edits

Profiles: default vs strict

With no zerum.toml (or [profile] name = "default"), Zerum uses the built-in default profile: noisy pattern heuristics are off so greenfield modules stay quieter.

Enable the full catalog:

zerum check . --profile strict

Or persist it:

zerum init --strict
# writes a strict starter config
[profile]
name = "strict"

Compare:

zerum check .                    # default — quieter
zerum check . --profile strict   # all ~75 rules

Configuration (zerum.toml)

zerum init              # default template
zerum init --strict     # strict template

Common knobs:

[profile]
name = "default"

[checks.ZR001]
enabled = true
max_lines = 50

[checks.ZR401]
severity = "high"

# Architecture layers (ZR207)
[[checks.ZR207.rules]]
from = "app.domain"
forbidden = "app.infrastructure"

# Always run Ruff when you check (requires ruff on PATH)
# external_checkers = ["ruff"]

Custom profiles can inherit:

[profiles.team]
extends = "default"

[profiles.team.checks.ZR001]
max_lines = 60
zerum check . --profile team

Starter files in the repo: zerum.toml.example, zerum.toml.strict.example.

Explain a rule

zerum explain ZR001
zerum explain ZR401
zerum explain ZR501

Shows category, severity, rationale, false positives, tradeoffs, examples, and remediation.

List checks and external checkers

zerum list-checks
zerum list-checkers

list-checks prints the full ZR catalog. list-checkers shows external adapters (e.g. Ruff) and whether they are available on PATH.

Optional Ruff orchestration

Zerum can run Ruff alongside native checks and merge findings:

# one-off
zerum check . --with-external ruff

# or persist in zerum.toml
# external_checkers = ["ruff"]
zerum check .

Requires ruff on PATH. External findings use ids like EXT-RUFF-E501.

Rule categories

Range Category
ZR001–015 Readability
ZR101–110 Consistency
ZR201–210 Design
ZR301–315 Refactor
ZR401–415 Warning
ZR501–510 AI (deterministic)

Output formats

zerum check . --format human    # default
zerum check . --format json
zerum check . --format sarif
zerum check . --profile strict
zerum check . --with-external ruff
zerum check . --remediation-prompt fixes.md
zerum list-checkers
Output When to use
human Terminal review — rule id, location, explanation, remediation
json CI artifacts, scripts, and custom dashboards
sarif GitHub code scanning and other SARIF consumers
--remediation-prompt Markdown brief for an LLM/editor agent (file on disk; still prints human/json/sarif to stdout)

Optional external checkers (Ruff) are available from v0.4.0. Use the default profile for low noise on greenfield code; use --profile strict for full catalog coverage.


Tutorial

Educational material lives under docs/tutorial/:


Feature demos

Assume a project directory with some Python sources.

1. First pass (quiet default)

zerum check .
# exit 0 → clean under default profile
# exit 1 → findings printed to stdout

2. Full catalog

zerum check . --profile strict

Expect more findings on small modules (docstring / comment / heuristic rules).

3. Machine-readable report

zerum check . --format json > zerum-report.json

4. Learn why a finding fired

zerum check . --format human
# note a rule id, e.g. ZR003
zerum explain ZR003

5. Team config + architecture boundary

zerum init
# edit zerum.toml — set ZR207 rules for your layers
zerum check .

6. Zerum + Ruff in one command

zerum list-checkers
zerum check . --with-external ruff --format json

7. Save a remediation prompt for an LLM / editor agent

zerum check . --remediation-prompt
# → zerum-remediation-prompt.md

zerum check . --remediation-prompt fixes.md

Findings are grouped by type and sorted by severity (critical first).

8. Upgrade later

pip install --upgrade zerum
# or: pipx upgrade zerum
# or: uv tool upgrade zerum
# or: brew upgrade zerum
zerum --version

Add Zerum to CI/CD (Python project)

Fail the job when Zerum finds issues (exit 1). Use JSON if you want artifacts.

GitHub Actions (pip)

name: Zerum

on:
  pull_request:
  push:
    branches: [main]

jobs:
  zerum:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install Zerum
        run: pip install "zerum==0.5.0"

      - name: Run Zerum
        run: zerum check . --format human

      # Optional: remediation prompt artifact for reviewers / agents
      # - run: zerum check . --remediation-prompt zerum-remediation-prompt.md || true
      # - uses: actions/upload-artifact@v4
      #   if: failure()
      #   with:
      #     name: zerum-remediation-prompt
      #     path: zerum-remediation-prompt.md

GitHub Actions (uv)

- uses: astral-sh/setup-uv@v4
- run: uv tool install zerum
- run: zerum check .

GitHub Actions (pipx)

- uses: actions/setup-python@v5
  with:
    python-version: "3.12"
- run: pipx install zerum
- run: zerum check .

Pre-commit

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: zerum
        name: zerum
        entry: zerum check .
        language: system
        pass_filenames: false
        types: [python]

Install Zerum on the machine (or in CI) before running pre-commit, e.g. pipx install zerum.

GitLab CI

zerum:
  image: python:3.12-slim
  script:
    - pip install "zerum==0.5.0"
    - zerum check .

Tips for CI

  • Start with default profile; move to --profile strict once the baseline is clean.
  • Pin the version in CI: pip install "zerum==0.5.0".
  • Combine with Ruff only if ruff is installed in the job:
    zerum check . --with-external ruff.
  • Treat exit code 2 as infra failure; 1 as “findings to fix.”
  • Optionally upload --remediation-prompt output as a CI artifact when the check fails.

Changelog

See CHANGELOG.md. Release notes: v0.5.0.


Building from source (contributors)

For hacking on Zerum itself — not required for normal use.

git clone https://github.com/latentmeta/zerum.git
cd zerum
cargo build --release
./target/release/zerum check path/to/python/project

# or run without installing
cargo run -- check path/to/python/project
cargo run -- explain ZR001
cargo run -- list-checks
cargo run -- init
cargo run -- check path/to/project --remediation-prompt /tmp/fixes.md

# editable Python-env install via maturin
pip install "maturin>=1.7,<2.0"
maturin develop

Tests and lint:

cargo test
cargo clippy --all-targets --all-features -- -D warnings

Coverage (rustup cargo; asdf shims break cargo +toolchain):

export PATH="$HOME/.cargo/bin:$PATH"
cargo +1.97.1 tarpaulin \
  --engine llvm --all-targets --all-features --follow-exec \
  --out Stdout --fail-under 70 -- --test-threads=1

Packaging notes: packaging/ (PyPI, Homebrew). Config for multi-channel scaffolding: Sastri.toml.


License

MIT — see LICENSE.