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.13.0 — LSP diagnostics (14 languages), opt-in static analysis (9 analyzers; baseline install default off, smart init enables it for detected dynamic-language projects), 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, 1469 tests pass / 37 test files, verified by collection (optional-tool skips vary).
Quick Start
pip install gitreins
cd /path/to/your-project
gitreins install # baseline config + pre-commit hook
gitreins init # smart init — detects language, size, optimal config
install is the conservative baseline: its config leaves static analysis off.
init is the smart opt-in path and enables static analysis for detected
projects such as Python, recording the configured analyzers in the config. An
explicit static_analysis setting is preserved on reruns, as is a custom
guards.test_command; only the untouched install baseline may be upgraded to
the detected test runner.
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 2 needs an LLM credential; configureGITREINS_LLM_API_KEY(plus optionalGITREINS_LLM_BASE_URLandGITREINS_LLM_MODEL) first. For an explicit Tier-1-only run, usegitreins task complete --skip-tier2 <id>. - 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] [--skip-tier2]
# Tier 2 requires GITREINS_LLM_API_KEY; optionally set GITREINS_LLM_BASE_URL and GITREINS_LLM_MODEL.
# Use --skip-tier2 for an explicit Tier 1-only evaluation without an LLM key.
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)
Parallel worktree fleet
A foreman or scheduler can run an explicit JSON/YAML manifest without coupling
to a scheduler implementation. Each lane gets one ../<repo>-wt/<task-id> tree;
commands run with argv arrays in that tree, bounded by the configured cap.
Optional guard and judge argv arrays record those phases in the shared
canonical registry.
gitreins worktree fleet lanes.json
gitreins worktree fleet lanes.json --max-concurrent-worktrees 3
gitreins worktree fleet lanes.json --merge --force-merge --actor release-bot
# Inspect cap, phase, exit status, and retained evidence:
gitreins worktree list
Manifest example:
{
"lanes": [
{"task_id": "API-1", "priority": 10, "command": ["./worker", "API-1"],
"guard": ["gitreins", "guard", "--full"]},
{"task_id": "UI-1", "priority": 20, "command": ["./worker", "UI-1"]}
]
}
The default cap is 2 and can be overridden in .gitreins/config.yaml:
worktree_fleet:
max_concurrent_worktrees: 2
venv:
source: .venv
name: .venv
When the configured source exists, every new task tree symlinks it rather than
installing dependencies. A missing source is allowed for non-Python projects;
existing destination files are never replaced. The shared environment is
intentionally not mutated by GitReins, and concurrent dependency installs are
not lane-safe. Successful --merge lanes are applied in priority/task-id order
under an advisory lock; normal judge verdict gates remain in force.
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: 1469 tests across 37 test files (collection total; optional-tool skips vary)
Architecture & Docs
- Disposable verification — run QA batteries, dogfood, and repro farms in throwaway worktrees without a bunker.
| 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.13.0
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.13.0.tar.gz | 369.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gitreins-0.13.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 575.5 kB
Release files / gitreins-0.13.0.tar.gz
| Download URL | gitreins-0.13.0.tar.gz |
|---|---|
| Size | 369.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4eb1da4ffb709845815c8d72f6bf995421592804ec74b6a2ffcfcf47bbdc2406
|
|
BLAKE2b-256 checksum How to use checksums |
ff1c3d1af314f8c958cd65b0df7270f8c6c6231a044e3a320b5e580cf368a546
|
| 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.13.0-py3-none-any.whl
| Download URL | gitreins-0.13.0-py3-none-any.whl |
|---|---|
| Size | 206.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
39c2cced672cabfa3ad7af75294ac52087f319d6a3bed76e4c486ada33509296
|
|
BLAKE2b-256 checksum How to use checksums |
ee2aaf2a183d70739f243e7b4d0b835d808038d0cc17730db1fe3efc99653b59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|