ReproGuard works with no configuration at all. This page covers the parts you reach for once it does: configuration, the CLI surface, custom rules, and how the score is actually computed.
pip install reproguard
# verify
reproguard --version
reproguard scan .
uv tool install reproguard
# or run it without installing
uvx reproguard scan .
git clone https://github.com/vipulgote1999/ReproGuard.git
cd ReproGuard
pip install -e .
# with the dev toolchain
pip install -e ".[dev]"
# Presidio-backed deep PII detection (--presidio)
pip install "reproguard[privacy]"
Requires Python 3.10 or newer. Works on Linux, macOS, and Windows.
reproguard init writes a config file and a ready-to-run
CI workflow so you start from something working rather than a blank
file.
# config + GitHub Actions workflow
reproguard init --ci github
# config tuned for an LLM/agent project
reproguard init --profile genai
# GitLab instead
reproguard init --ci gitlab
Everything below is a flag on
reproguard scan <target>.
| Flag | What it does |
|---|---|
--format text|json|html|sarif|gitlab|all |
Which reports to write. Defaults to all. Text
goes to the terminal, the rest into the output directory.
|
--output-dir <dir>, -o |
Where reports land, default .reproguard. Use
-o - to stream a single machine format to stdout
for jq.
|
--fail-under <score> |
Exit non-zero when the score is below the threshold. The main CI gate. |
--baseline <report.json> |
Diff against a previous report. Combine with
--fail-new N or
--fail-new-critical to block only regressions.
|
--fail-trend N |
Fail when the score dropped N or more points since the previous recorded scan. |
--since <git-ref> |
Scan only files changed since a ref — fast incremental scans on large repos. Repo-level checks still run. |
--execute / --no-execute |
Run notebooks on a clean kernel to prove they actually
execute. --no-execute is the default.
|
--parallel, --max-workers N |
Execute notebooks in parallel subprocesses, kernelspec-aware. |
--profile genai |
GenAI-tuned category weights: GenAI findings penalise harder, handoff findings less. |
--privacy / --no-privacy,
--presidio
|
Control PII and secret scanning. --presidio adds
named-entity detection and needs the
privacy extra.
|
--fix gitignore|clear-counts|seed|strip-outputs|all
|
Idempotent, non-destructive remediations applied before the exit gates run. |
--git-history |
Scan git history diffs for secrets committed in the past (gitleaks-lite). |
--sbom <file> |
Write a CycloneDX 1.5 bill of materials from the declared dependencies. |
--model-card [--model-card-format md|hf] |
Emit a Markdown handoff artifact, optionally in Hugging Face Hub front-matter form. |
--manifest-online |
Validate llm.yaml model ids against the
OpenRouter catalog.
|
--execution-timeout <seconds> |
Per-notebook timeout for clean execution runs. |
reproguard init # scaffold config + CI workflow
reproguard list # every registered check
reproguard explain LEAK001 # full record for one check
reproguard trend # score history for this project
Create a .reproguard.yml at your project root. Like
git, ReproGuard walks up from the scan path to find it, so a
subdirectory scan picks up the root config.
# .reproguard.yml
exclude_paths:
- "archive/**"
- "tests/**"
exclude_dirs:
- scratch
# CI gate defaults
fail_under: 50
# GenAI-tuned weights (same as --profile genai)
profile: genai
thresholds:
severity_penalties:
critical: 18
high: 10
category_weights:
genai: 30
handoff: 5
checks:
disabled:
- LEAK005 # large tabular output
- PII004 # base64 images in output
ignore:
- code: SEC002
path: "tests/**" # fixtures hold fake keys
- code: DATA001
path: "notebooks/explore.ipynb"
evidence: "/mnt/shared/.*" # optional regex on the match
execution:
enabled: false
timeout: 300
parallel: false
max_workers: 4
checks.ignore is path-scoped, so you silence a
finding where it is wrong rather than muting the check everywhere.
An optional evidence regex narrows it further.
Suppressed counts are recorded in report metadata so nothing
disappears silently.
Setting only critical under
severity_penalties keeps the defaults for every other
severity. Unknown keys and malformed values produce warnings,
never tracebacks.
Organisation-specific patterns live in the same file and behave like built-ins: scored, reported, and suppressible.
# .reproguard.yml
rules:
- code: NOSAMPLE # flag sampling without a fixed seed
title: Sample without seed
pattern: 'sample\('
category: reproducibility
severity: medium
confidence: 0.8
file_patterns:
- 'src/**/*.py'
- '*.ipynb'
- code: TODO001
title: TODO left in code
pattern: '# TODO'
severity: low
Rules are capped at 20 findings per file, matching the flood-control
philosophy of the built-in checks. category defaults to
custom when it isn't a known value.
No machine learning, no hidden model. The score is a transparent penalty calculation you can reproduce on a napkin.
penalty = Σ severity_penalty × (category_weight / 20) × confidence
score = max(0, min(100, 100 − penalty))
severity penalties: critical 18 · high 10 · medium 5 · low 2 · info 0
category weights: reproducibility 30 · execution 30 · genai 30
data_leakage 25 · privacy 20 · data_dependency 15
handoff 10 · custom 10
75–100 · ready_with_caution — review
the minor findings.
50–74 · needs_review — significant
issues to address.
0–49 · not_ready — blocking.
Any CRITICAL · not_ready, regardless
of score.
Every report carries penalties_by_category, and those
values sum exactly to 100 − score. A 40/100 project
tells you it lost 25 points to leakage and 20 to privacy, not just
that it is "bad".
# one document on stdout, ready for jq
reproguard scan . -f json -o - | jq '{score, status, n: (.issues|length)}'
# {
# "score": 42,
# "status": "not_ready",
# "n": 8
# }
Streaming guarantees exactly one parseable document: notices go to
stderr, GitHub annotations are suppressed, and
--format all with -o - is rejected up
front.
# SARIF 2.1.0 for GitHub Code Scanning and VS Code
reproguard scan . --format sarif
Upload with github/codeql-action/upload-sarif@v3. See
the CI guide.
# gl-code-quality-report.json for merge-request annotations
reproguard scan . --format gitlab
# standalone interactive report with severity filters
reproguard scan . --format html
Self-contained — no external assets, so it survives being emailed or attached to a ticket.
Use Ruff and Black for style. ReproGuard looks for risks that only exist in data-science artefacts: execution order, leakage, environment drift, hidden credentials.
DVC and LakeFS own that. ReproGuard flags that a DVC-tracked output is missing, then stops.
MLflow and Weights & Biases own that. ReproGuard runs before and around them.
Evidently, Arize, and WhyLabs own monitoring. ReproGuard is a pre-production gate.
Start with a single scan. Add configuration only when a finding turns out to be wrong.