Deterministic guardrails for AI-written code. rein catches what coding agents get wrong - leaked secrets, unsafe calls, imports that do not resolve, junk files, and commit-hygiene problems - turns them into a PASS / WARN / BLOCK verdict with fix guidance, and gates the code before it runs. It makes no LLM calls and no network requests: a reproducible check you can run in CI, a git hook, your editor, or an agent's own loop. Website: https://rein.software
Detection lives in pure functions under rein.core; the value is the engine
around them - policy, verdict, steering, and remediation. The core stays
dependency-free and can also govern best-of-breed external detectors (bandit,
gitleaks, ruff, semgrep) as optional adapters. Thin adapters expose it: a CLI,
an MCP server, a git pre-commit hook, a GitHub Action, and a VS Code extension.
$ rein review app.py
[CRITICAL] secret.aws-access-key app.py:3
Possible AWS access key ID committed in source.
[HIGH ] security.eval-exec app.py:6
Use of eval/exec runs arbitrary code; avoid it or strictly validate input.
Verdict: BLOCK
The verdict is BLOCK, so rein exits non-zero and the CI step, hook, or agent
loop stops until the code is fixed.
# End users: install the published package (the command stays `rein`)
pipx install rein-engine
# or: pip install rein-engine
# Developers: install from a clone with the dev extras
pip install -e ".[dev]"# Scan files or directories for leaked credentials
rein scan .
rein scan src/config.py
# Scan only added lines from a diff (reads stdin)
git diff | rein scan --diff
# Run lint rules over Python code
rein lint .
rein lint src/ --ruff
# Flag unsafe-code patterns
rein security .
# Run all guardrails and get a PASS/WARN/BLOCK verdict
rein review .
# Run all guardrails plus external detectors (installed separately)
# Detectors can also be enabled declaratively via .rein.toml
rein review --bandit --gitleaks --semgrep .
# Show how to fix each finding
rein review --explain .
# Review only changed lines (reads working tree and stdin diff)
git diff | rein review --diff
# Machine-readable findings for CI or agents
rein scan --format json .
rein lint --format json src/
# Check a commit message and the staged files
rein commit-check -m "feat(auth): add token refresh"
rein commit-check # uses the last commit message and staged files
# Note: commit-check and pre-commit hooks will strictly flag any modifications to rein's own config files as HIGH.
# They also provide advisory warnings (MEDIUM/LOW) if you attempt to commit junk/slop files (e.g. .DS_Store, temp.py).rein exits non-zero on any finding at HIGH severity or above, so it works as a
CI step or a pre-commit hook.
You can drop rein directly into your GitHub Actions pipeline. It reviews a
path and uploads the findings as SARIF, so they surface in the Security tab:
name: CI
on: [push, pull_request]
jobs:
rein:
runs-on: ubuntu-latest
permissions:
contents: read # checkout the repository
security-events: write # upload SARIF to the Security tab
actions: read # upload-sarif reads run metadata (private repos)
steps:
- uses: actions/checkout@v4
- name: Run rein review
uses: SametAtas/rein@v0.4.0
with:
path: src/
output: rein.sarifCode scanning (the Security tab) needs GitHub Advanced Security on private
repositories. Where it is unavailable, set upload: false to produce the SARIF
file as a build artifact instead of uploading it.
rein plugs into agents you already use, as a deterministic gate on the code they write. Same code, same verdict, no extra model calls for the check.
aider lints every file it edits. Point its lint command at rein:
aider --lint-cmd "rein review"After each edit aider runs rein review <file>; on a BLOCK it feeds rein's
findings back to the model to fix before continuing.
rein-openhands is a deterministic
SecurityAnalyzer, a no-LLM alternative to the built-in LLMSecurityAnalyzer:
pip install rein-openhandsfrom rein_openhands import ReinSecurityAnalyzer
agent = Agent(llm=llm, tools=tools, security_analyzer=ReinSecurityAnalyzer())The rein VS Code extension shows rein's findings inline as you edit, and reviews the workspace, the staged git diff, or a commit message on demand. Also on Open VSX.
Control the engine declaratively with a .rein.toml file at the root of your project to configure the rein review verdict policy, disable specific rules, and enable external detectors:
[policy]
fail_at = "high" # severity at/above which a finding blocks
warn_at = "low" # severity at/above which a finding warns
[policy.category_fail_at]
lint = "low" # override fail threshold per category (secret/lint/security/commit/ruff)
secret = "critical"
[rules]
disabled = ["lint.todo-comment", "secret.jwt"] # rule_ids to drop entirely
[[rules.custom]]
id = "no-print"
pattern = "\\bprint\\("
severity = "low"
message = "Avoid print() in production code"
[detectors]
# Declaratively enable external detectors (must be installed separately).
# Note: semgrep is a multi-language, rule-based detector and is heavier, so it is opt-in.
bandit = true
gitleaks = true
ruff = true
semgrep = trueYou can override the path via rein review --config path/to.toml ..
src/rein/
core/ pure checks: findings.py, pragmas.py, diffs.py, secrets.py, security.py, lint.py, commits.py, review.py, remediation.py, ruff.py, bandit.py, gitleaks.py
report.py shared output formatting and exit codes
cli/ command-line adapter
mcp/ MCP server adapter (stdio)
hooks/ git pre-commit adapter
tests/ one test file per module
Agents can use rein to check and correct their own code before committing. The reference implementation for this steering loop is rein.loop.run_loop (pure, bounded, agent injected).
- An LLM agent generates a patch.
- The loop runs
review()orreview_diff(). - If the verdict is
BLOCK, the loop fetchessuggest_fixes()and feeds the findings + guidance back to the agent as a prompt. - The agent revises the code. The loop repeats until the verdict passes or the iteration bound is hit.
See examples/guarded_agent.py for a runnable demonstration.
Record the current findings so CI only blocks on new issues:
rein baseline # writes .rein-baseline.json
git add .rein-baseline.json
rein review --baseline .rein-baseline.json .Findings already in the baseline are suppressed; only new ones trigger a BLOCK.
Install with MCP support:
pip install -e ".[mcp]"Start the stdio server:
rein-mcpClient config snippet (e.g. for Claude Desktop or any MCP client):
{
"mcpServers": {
"rein": {
"command": "rein-mcp",
"transport": "stdio"
}
}
}The server exposes eight tools: scan_secrets, check_commit, lint_code, scan_diff, check_security, review_code, suggest_fixes, and review_diff. The review tools (review_code and review_diff) accept an optional config object (same shape as .rein.toml) to steer with a custom policy.
A configurable Policy turns findings into a verdict and is how rein adapts to different standards and domains.
The rule the code follows: detection stays in core and returns Finding
objects; adapters only gather input, call core, and render the result.
pytest -qApache-2.0 (see LICENSE). Contributions require a Developer Certificate of
Origin sign-off; see CONTRIBUTING.md.