GitReins
Git-Native Agent Co-Harness — static guards + agentic evaluator for AI-assisted code
GitReins lives inside your git repository as a quality harness. It provides MCP tools for task lifecycle management, an agentic evaluator that judges code completeness against task definitions, and git hooks that ensure nothing bypasses the quality gates.
✅ v0.12.0 — LSP diagnostics (14 languages), opt-in static analysis (9 analyzers, default off), commit audit with CVE-scored severity, optional Antares CVE-localization guard, Anthropic Messages API support, DeepSeek prompt caching telemetry, large-repo hardening (fast-track +
--skip-tier2), MCPpropagate, judge single-flight + resume lease, evaluator committed-diff read path, 1335 tests pass / 32 test files, verified on a full run 2026-08-25 (1328 passed, 7 skipped, 1 known env-dependent LSP flake — tracked attests/test_lsp.pyPYLSP_SKIP_310).
Quick Start
pip install gitreins
cd /path/to/your-project
gitreins install # creates .gitreins/config.yaml + pre-commit hook
gitreins init # smart init — detects language, size, optimal config
Running from a source checkout (no pip install): the gitreins console
script is not on your PATH — it lives in the repo's virtualenv. Activate it
first in each shell, then the commands above work as written:
source .venv/bin/activate # or call .venv/bin/gitreins directly
gitreins --help
New to GitReins? Read the Onboarding Guide — full install → init → first guard run → task workflow, plus troubleshooting for the most common first-run failures (gitleaks regex config, Python import setup).
uv is optional.
gitreins initprefersuv run pytestas the test command when uv is installed, but a machine without uv still passes the tests guard: when the configuredtest_commandstarts with a runner (uv run/pipenv run/poetry run) whose binary is missing from PATH, the guard automatically falls back topython -m pytest ...and prints a warning line. pip-only users never seeuv: command not found.
How It Works
- Create tasks — Define criteria via CLI or MCP tools
- Work with your AI agent — Claude, Hermes, Codex, or Pi does code generation
- Complete tasks —
gitreins task complete <id>triggers automatic evaluation - Tier 1: Static guards — secrets, build, lint, tests (configurable)
- Tier 2: Agentic evaluator — LLM loop reads files, runs tests, delivers per-criterion PASS/FAIL
- Verdicts persisted — stored in
.gitreins/history/, browsable viagitreins report - Commit through harness — pre-commit hook runs guards, blocks if checks fail
MCP commit rule: the MCP
committool refuses while any task isin_progress— completed work must be judged against the task's criteria first. Finish tasks withtask.complete(which runs the quality judge) or remove them withtask.delete, then retry the commit.
Commands
gitreins install # Install hooks + config
gitreins init # Smart init (language, size, optimal config)
gitreins guard [--dead-code] # Run Tier 1 static checks (--dead-code: opt-in Python dead-code detection)
gitreins security-scan [-d DIR] [--output text|json] [--force-ml]
# Run the Antares CVE localization scanner
gitreins report [-n N] [--interactive] # Browse verdict history
gitreins task create <id> <title> [criteria...] [--depends-on ...]
gitreins task start <id>
gitreins task complete <id> [--force]
gitreins task list [--status pending|in_progress|complete]
gitreins task delete <id>
gitreins judge <id> # Evaluate a task
gitreins commit <message> # Commit with guard checks
gitreins commit-audit [message] # Validate commit message against staged diff (commit-msg hook)
gitreins setup-tools # Show available static analysis tools and install instructions
gitreins mcp-server # Run MCP stdio server (for AI agents)
Security Scan (optional)
GitReins ships an opt-in Tier 1 security guard that localizes
known CVEs against your staged Python code. It is built on the
Antares CVE localization framework
(FDTN-AI's 1B-parameter model fine-tuned for code-level vulnerability
localization). Until the optional ML stack is installed, the guard
falls back to a keyword-based heuristic that produces
CVE-SIMULATED findings so the wiring can be exercised end-to-end.
CLI
# Scan staged Python files (default; used by `gitreins guard`).
gitreins security-scan
# Recursively scan a directory instead of staged files.
gitreins security-scan --directory engine/
# Machine-readable output for piping into other tools.
gitreins security-scan --output json
# Require real ML inference — fail if huggingface_hub/transformers
# are not installed (exit code 2). Without this flag the heuristic
# fallback is used.
gitreins security-scan --force-ml
Exit codes:
| Code | Meaning |
|---|---|
| 0 | Clean — no findings |
| 1 | One or more findings produced |
| 2 | --force-ml requested but ML dependencies are missing |
Install requirements
The heuristic scanner has no extra dependencies. Real ML inference requires the optional ML stack:
pip install huggingface_hub transformers
# Optional, for GPU inference:
pip install torch # or onnxruntime
The model is downloaded on first use into
~/.cache/gitreins/antares-1b/ and reused on subsequent runs.
Configuration
Enable the guard in .gitreins/config.yaml:
defaults:
security_scan:
enabled: true # opt-in: default false
model: antares-1b # "antares-1b" | "antares-350m"
min_confidence: 0.7 # filter by CVSS severity score
cve_source: nvd # "nvd" | "github" | "both"
| Key | Default | Notes |
|---|---|---|
enabled |
false |
When true, the security_scan guard runs alongside other Tier 1 checks |
model |
antares-1b |
HuggingFace model id; antares-350m is a smaller variant |
min_confidence |
0.7 |
Drop entries whose CVSS score is below this. Severity→score: CRITICAL=1.0, HIGH=0.85, MEDIUM=0.6, LOW=0.3 |
cve_source |
nvd |
nvd uses the NVD REST API, github uses the GitHub Advisory Database, both merges the two |
The CVE feed is cached at ~/.cache/gitreins/cve_feed/ with a
24-hour TTL. When the network is unreachable the feed serves stale
cache; when both cache and network are unavailable the feed returns
an empty list and the guard exits clean (it is opt-in and must
never block a commit on missing infrastructure).
Test Modes: full vs diff
GitReins supports two strategies for when tests run on commit, controlled by test_mode in .gitreins/config.yaml.
test_mode: "full" (default for new projects)
The entire test suite runs on every commit. Safe and thorough.
Best for:
- New projects with a small, fast test suite
- Projects where all tests pass reliably
- When you want maximum safety on every commit
Tradeoff: Slow on large projects. Pre-existing failures in untouched code block unrelated commits.
guards:
test_mode: "full"
test_mode: "diff" (recommended for mature projects)
Only tests for packages you actually changed. Uses basename mapping:
| Changed file | Test run |
|---|---|
engine/guard_manager.py |
tests/test_guard_manager.py |
gitreins/cli.py |
tests/test_cli.py |
gitreins_mcp/server.py |
tests/test_mcp_server.py |
Best for:
- Projects with 5+ packages where full suite is slow
- Projects with pre-existing test failures in untouched code
- When you want fast feedback on the code you actually changed
Safety nets — diff mode falls back to full suite when:
pyproject.toml,.gitreins/config.yaml,Makefile, orsetup.cfgchanged- A test file itself changed (always included, plus its source-mapped siblings)
- Changed files don't map to any known test files (unknown file = safety)
- No staged files at all
- Test command isn't
pytest(custom runners can't be narrowed)
Tradeoff: Less safety on cross-cutting changes. Config changes always trigger full suite.
guards:
test_mode: "diff"
Which mode should I use?
| Project state | Recommended mode |
|---|---|
| Brand new, <5 packages | full |
| Mature, 5+ packages, tests pass | diff |
| Mature, pre-existing test failures | diff |
| Refactoring across packages | full (temporarily) |
| CI / PR checks | full (safety over speed) |
Output examples
Full mode:
Tier 1 Guards: PASS (test mode: full)
✓ secrets — clean
✓ lint — ok
✓ tests — passed
Diff mode (targeted):
Tier 1 Guards: PASS (test mode: diff, 3 test file(s))
✓ secrets — clean
✓ tests — passed
Diff mode (safety trigger — full suite):
Tier 1 Guards: PASS (test mode: diff, full suite — safety trigger)
✓ secrets — clean
✓ tests — passed
Verdict History
Every gitreins task complete and gitreins judge saves a verdict to .gitreins/history/. Configure in .gitreins/config.yaml:
history:
enabled: true # false = don't save verdicts
storage: "git" # "git" = auto-commit to gitreins branch
# "filesystem" = write files only, no git commits
max_verdicts: 1000 # auto-prune old entries
Browse history:
gitreins report # last 10 evaluations
gitreins report -n 20 # last 20
gitreins report --interactive # TUI with arrow-key navigation (requires textual)
Branch mechanics (git storage)
With storage: "git" (the default), every verdict is auto-committed to a
dedicated orphan gitreins branch — never to main. The branch is only
checked out transiently (or updated via a temporary worktree), so your
working tree is never disturbed. .gitreins/history/ is intentionally
gitignored: the verdict files are runtime artifacts whose canonical home is
the gitreins branch, and a fresh clone therefore has no local
.gitreins/history/ directory.
gitreins report reads verdicts in this order:
- Local filesystem —
.gitreins/history/in the working tree (used when present, e.g. right after a judge run in the same checkout). gitreinsbranch fallback — when the local directory is missing or empty and storage is"git", verdicts are read straight from the branch (git ls-tree/git show), so a fresh clone can still browse the full verdict history.
To inspect the branch directly:
git log --oneline gitreins # verdict commits
git ls-tree -r --name-only gitreins -- .gitreins/history # stored files
git show gitreins:.gitreins/history/<date>/<hash>/verdict.json # one verdict
With storage: "filesystem", verdicts are written locally only — no branch
is created and the fallback is skipped.
Task Dependencies
Tasks can depend on other tasks. Evaluation is blocked until dependencies pass:
gitreins task create build "Project builds" \
"CGO_ENABLED=0 go build ./cmd/server exits 0"
gitreins task create api-crud "CRUD endpoints" --depends-on build \
"POST /api/users creates a user" \
"GET /api/users lists users"
gitreins task complete api-crud
# → "Cannot complete 'api-crud' — depends on: build"
gitreins task complete build # complete the dependency first
gitreins task complete api-crud # now this works
# Or force-skip dependency checks:
gitreins task complete api-crud --force
Configuration
Full .gitreins/config.yaml reference:
# ── Global defaults ──────────────────────────────────
defaults:
model: deepseek-v4-flash
max_iterations: 100
check_for_updates: true
# ── Tier 1 guards ────────────────────────────────────
guards:
secrets: true
lint: true
tests: true
test_mode: "full" # "full" or "diff"
# uv/pipenv/poetry are OPTIONAL — if the runner prefix's binary is not on
# PATH, the guard falls back to `python -m pytest ...` with a warning.
test_command: "uv run pytest -x --tb=short"
# Go projects (auto-detected via go.mod):
go:
build: true
lint: true
tests: true
# ── Tier 2 evaluator caps ────────────────────────────
evaluator:
max_iterations: 25 # LLM reasoning turns
max_time: "5m" # wall clock cap
max_input_tokens: "200k"
max_output_tokens: "50k"
tool_call_weight: 0.1 # tool calls cost 0.1 iterations
# ── Verdict history ──────────────────────────────────
history:
enabled: true
storage: "git"
max_verdicts: 1000
Tech Stack
- Language: Python 3.10+
- Dependencies: mcp, pyyaml, requests, packaging (4 packages)
- MCP Transport: stdio (12 tools)
- Config: YAML in
.gitreins/directory - Evaluator Default Model: DeepSeek V4 Flash (~$0.01/eval)
- Test suite: ~1335 tests across 32 test files (parallelized with pytest-xdist; last verified full run 2026-08-25: 1328 passed, 7 skipped, 1 known env-dependent LSP flake — tracked at
tests/test_lsp.pyPYLSP_SKIP_310)
Architecture & Docs
| Document | What it covers |
|---|---|
| Full Architecture | System design and data flow |
| Component Map | Module inventory with paths and line counts |
| Agentic Evaluator Design | How the evaluator loop works |
License
MIT
Metadata
Release files for gitreins 0.12.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gitreins-0.12.1.tar.gz | 293.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gitreins-0.12.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 452.3 kB
Release files / gitreins-0.12.1.tar.gz
| Download URL | gitreins-0.12.1.tar.gz |
|---|---|
| Size | 293.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d5a62e1dabb0a9aa3f6814161aaaf5702bbb4ce04d5967d61875ad3aa1258413
|
|
BLAKE2b-256 checksum How to use checksums |
cd9035b9beab1904a68ef5a70a42c2180b95945633abab4d205aa9fba75e6a83
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / gitreins-0.12.1-py3-none-any.whl
| Download URL | gitreins-0.12.1-py3-none-any.whl |
|---|---|
| Size | 159.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9c879b7bba3d5e7fde21e6ad2109e4e33fcc6508483b61c9a360c8eca4e865bf
|
|
BLAKE2b-256 checksum How to use checksums |
f4037cc5e7b8273ce25ad2152f0351dc9c9b902097ba398273d9f63d11dbf84f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|