Skip to main content

Local PR review tool that orchestrates Claude Code CLI agents over git diffs.

Project description

PR Sentinel

Local pull-request review tool. Reads a git diff, runs four specialized review agents over it via the Claude Code CLI, and emits a structured JSON + Markdown report so you can fix issues before raising the PR.

No API keys. No hosted services. PR Sentinel shells out to claude -p and uses your existing Claude Code authentication.

How it works

git diff main...HEAD
        │
        ▼
[ diff_parser ] ── filters built-in noise + user skip patterns
        │             (--skip-files, .prsentinelignore)
        ▼
[ chunker ] ── packs files into ≤100k-char chunks (hybrid batching)
        │
        ▼
[ router ] ── per chunk, decides which agents are relevant for those file types
        │
        ▼
[ orchestrator ] ── runs (agent × chunk) tasks in a bounded thread pool
        │
        ├── Security Agent      (claude -p prompts/security.md)
        ├── Code Quality Agent  (claude -p prompts/quality.md)
        ├── Performance Agent   (claude -p prompts/performance.md)
        └── Testing Agent       (claude -p prompts/testing.md)
                │
                ▼
[ cache ] ── sha256(model + prompt) → response, on disk
                │
                ▼
[ Summary Agent ] ── single claude call that dedupes/merges findings across agents
        │             (prompts/summary.md; falls back to raw findings on failure)
        ▼
[ report_generator ] ── merges findings, computes risk level
        │
        ▼
reports/report.json + reports/review-report.md

File-type routing

Not every agent has something useful to say about every file. PR Sentinel skips agents that have nothing meaningful to contribute to a chunk's file types, reducing token usage with no loss in review quality.

File type Security Quality Performance Testing
*.cs (source)
*Test*.cs, *Spec.cs, *Fixture.cs
*.cshtml, *.razor, *.html
*.js, *.ts
*.css, *.scss, *.less
*.svg
*.csproj, *.props, *.targets
*.sln
appsettings*.json, *.yml, *.yaml, *.xml, *.json
Dockerfile, *.bicep, *.tf
*.sql
*.csv, *.tsv, *.resx
*.md, *.txt, *.http
Unknown extension

Three rules behind the table:

  • Security runs on almost everything — secrets and PII appear in docs, config files, and data files.
  • Performance and Testing only run on executable code.
  • Unknown extensions always get all four agents — nothing is silently skipped.

If a chunk contains mixed file types (e.g. a .cs file and a .css file together), the agents for the union of both types are run. Binary files (*.png, *.dll, *.zip, etc.) are dropped entirely before routing — their diffs are unreadable.

Requirements

  • Python 3.11+
  • Claude Code CLI installed and authenticated. claude --version must work from your shell.
  • Git, if you want to review live branches (not required for --diff mode).

Install

From PyPI:

pip install pr-sentinel

From source (for development):

git clone https://github.com/kishor2004reddy/Pull-Request-Sentinel-CLI.git
cd Pull-Request-Sentinel-CLI
pip install -e .[dev]

Verify:

pr-sentinel --help
pr-sentinel agents

Quickstart

Review your current branch against main:

pr-sentinel review --base main

Or review a saved diff file (works without a git repo):

git diff main...HEAD > my.diff
pr-sentinel review --diff my.diff --out reports

Open reports/review-report.md.

Commands

pr-sentinel review

Flag Default Description
--base main Branch to diff against. Runs git diff <base>...<head>.
--head HEAD Source branch/ref to review. Use with --base to diff arbitrary refs without checking them out.
--diff PATH Review a saved diff file instead of running git. Mutually exclusive with --staged.
--staged off Review staged changes (git diff --cached).
--repo PATH cwd Path to the git repository to review. Ignored when --diff is used.
--agents security,quality,performance,testing Comma-separated agents to run.
--out ./reports Output directory.
--format both json, markdown, or both.
--max-file-size 20000 Per-file diff size cap (chars). Larger files get truncated with a marker.
--chunk-budget 100000 Max combined diff size per Claude call before chunking kicks in.
--model haiku Claude model to use. Shortcuts: sonnet, opus, haiku. Or pass a full model ID such as claude-opus-4-7, claude-sonnet-4-6, claude-haiku-4-5-20251001. Forwarded to claude --model.
--max-parallel 8 Max concurrent claude calls across all (agent, chunk) pairs.
--timeout 600 Per-call timeout in seconds for each claude subprocess.
--no-cache off Bypass the response cache for this run. Successful responses are still written to the cache.
--skip-files Comma-separated glob patterns to skip on top of built-in noise filters (e.g. "*.lock,vendor/**,fixtures/*.json"). Combines with .prsentinelignore if present.

pr-sentinel agents

Lists available agents and their implementation status.

pr-sentinel cache

Inspect and manage the on-disk response cache.

Subcommand Description
cache size Show cache location, entry count, and disk usage.
cache clear Wipe the entire cache (prompts for confirmation).
cache prune --older-than 30d Delete entries older than the given age. Supports s/m/h/d suffixes. Add --dry-run to preview.

The cache lives at ~/.pr-sentinel/cache/ by default. Override with the PR_SENTINEL_CACHE_DIR environment variable. Keys are sha256(model + prompt), so changing the model or any prompt content invalidates the entry automatically.

Auto-pruning. Every pr-sentinel review run silently drops cache entries older than 90 days before doing any work. No flag, no output — it just keeps the cache from growing unbounded over time. The threshold is set via AUTO_PRUNE_AGE_DAYS in config.py. Use cache prune --older-than ... for manual prunes at a different age.

Skipping files

PR Sentinel always filters built-in noise (lock files, build/dist dirs, minified, generated). To skip additional files — large fixtures, vendored code, anything that wastes tokens without adding review value — use either of these:

Per-run flag, good for one-offs:

pr-sentinel review --skip-files "vendor/**,fixtures/*.json,*.snap"

Repo-wide ignore file, good for project defaults — drop a .prsentinelignore at the repo root:

# generated docs
docs/api/**

# huge test fixtures
tests/fixtures/large/**

# vendored deps
vendor/**

Syntax: one glob per line, # for comments, blank lines ignored. Patterns use fnmatch (same as the built-in noise filter), matched against both the full path and the basename. The two sources combine — flag patterns are appended to the ignore file's patterns. Skipped files are listed in the "Skipped noise file(s)" panel at the top of the run output.

Examples

Review current branch vs main:

pr-sentinel review --base main

Run only the security agent:

pr-sentinel review --base main --agents security

Review what's currently staged:

pr-sentinel review --staged

Review a feature branch without checking it out:

pr-sentinel review --base main --head feature/new-auth

Use a stronger model for higher-stakes reviews:

pr-sentinel review --base main --model opus

Force a fresh run, ignoring cached responses:

pr-sentinel review --base main --no-cache

Skip extra files for this run only:

pr-sentinel review --base main --skip-files "vendor/**,*.snap"

Prune cache entries older than a week:

pr-sentinel cache prune --older-than 7d

Report structure

The markdown report always emits these five sections in this fixed order, regardless of findings:

  1. Summary — risk level, source, branch, timestamp, agents, finding counts
  2. Merge Verdict — deterministic verdict driven by risk level (not a separate Claude call)
  3. Key Findings — top blocking issues (High + Medium)
  4. Key Recommendations — deduplicated fixes
  5. All Findings — per-agent summary table + full per-issue detail

The JSON report contains the same data in a single structured object suitable for piping into other tools. Key fields:

  • riskLevelHigh / Medium / Low / None / Unknown (see table below)
  • coverageCompletefalse if any agent failed during the run
  • agentsExecuted, failedAgents — who ran and who didn't
  • findings — flat list, sorted by severity then file
  • rawFindingCount — only present when the Summary Agent ran; how many findings existed before dedup

Risk levels

Level Trigger
High Any High-severity finding, or 5+ Medium-severity findings
Medium One or more Medium-severity findings (and fewer than 5)
Low Only Low-severity findings
None No findings across all executed agents (full coverage)
Unknown All executed agents failed, or some agents failed and the rest found nothing (can't call it clean with incomplete coverage)

Architecture

src/pr_sentinel/
├── cli.py                  # Click entrypoint + Rich UI
├── config.py               # tunable defaults + shared constants (single source of truth)
├── git_diff.py             # git rev-parse, git diff, --staged
├── diff_parser.py          # per-file splitting + noise filter (+ --skip-files / .prsentinelignore) + truncation
├── chunker.py              # greedy packer to keep prompts under chunk-budget
├── claude_runner.py        # subprocess(claude -p) + JSON extraction + 1 retry
├── orchestrator.py         # parallel (agent, chunk) execution via ThreadPoolExecutor
├── router.py               # file-type routing table — decides which agents run per chunk
├── cache.py                # sha256-keyed disk cache + 90-day auto-prune
├── report_generator.py     # build_report + JSON/Markdown writers
├── agents/
│   ├── base.py             # BaseAgent: load prompt, chunk, call, validate
│   ├── security_agent.py
│   ├── quality_agent.py
│   ├── performance_agent.py
│   ├── testing_agent.py
│   └── summary_agent.py    # post-processes findings: dedupe/merge across agents
└── prompts/
    ├── security.md
    ├── quality.md
    ├── performance.md
    ├── testing.md
    └── summary.md

tests/
├── test_diff_parser.py
├── test_chunker.py
└── test_report_generator.py

Running tests

pip install -e .[dev]
pytest -q

Troubleshooting

claude CLI not found on PATH — install Claude Code and confirm claude --version works in the same shell where you run pr-sentinel.

claude returned non-JSON output after retry — Claude occasionally returns prose instead of JSON. The runner retries once; if it still fails, that chunk's findings are dropped and the agent is marked failed for the run. Re-running usually succeeds.

Slow runs — large diffs trigger chunking. Each chunk is one Claude call per agent. Reduce scope with --agents security if you only want one perspective, or with --max-file-size to truncate huge files. The cache amortizes repeat runs against the same diff.

Lock files / minified files showing up — they shouldn't. If they do, add the pattern to NOISE_PATTERNS in config.py, or skip on a per-project basis with .prsentinelignore (see Skipping files).

Want to skip a non-noise file (huge fixture, vendored dep, generated snapshot)? Use --skip-files "pat1,pat2" for a one-off, or commit a .prsentinelignore for project-wide defaults.

Notes & limitations

  • The Performance Agent only sees the diff. It can flag pattern-level issues (N+1 queries, sync-over-async) but cannot reason about runtime behavior or system load.
  • lineHint is approximate — unified diffs have hunk headers, not absolute line numbers. The prompt asks Claude for a description of the location rather than a hallucinated number.
  • Agents cannot read other files in the repo. Review depth is limited to what's visible in the diff itself.
  • If any one chunk fails for an agent (timeout, exit code, unparseable JSON after retry), that agent is marked failed for the run and its partial findings are discarded. Other agents continue.
  • The Summary Agent makes one additional claude call per run to deduplicate and merge findings across the four review agents. If it fails (timeout, bad JSON), the report falls back to the raw findings — nothing is lost.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pr_sentinel-0.1.5.tar.gz (42.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pr_sentinel-0.1.5-py3-none-any.whl (42.4 kB view details)

Uploaded Python 3

File details

Details for the file pr_sentinel-0.1.5.tar.gz.

File metadata

  • Download URL: pr_sentinel-0.1.5.tar.gz
  • Upload date:
  • Size: 42.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.4

File hashes

Hashes for pr_sentinel-0.1.5.tar.gz
Algorithm Hash digest
SHA256 a4350b3a5aadd1d3175de536865df1209fea127c60a4df3c6f3b153171dbf0ab
MD5 31ddd76ef39fd9c7fc31d59aafaf9bbe
BLAKE2b-256 b417633938b71abeabf262fba5614fe59833d7c918eaad4229cdf58904da8c9a

See more details on using hashes here.

File details

Details for the file pr_sentinel-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: pr_sentinel-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 42.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.4

File hashes

Hashes for pr_sentinel-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 29c2f5d59ed1e3390d78606c02a8cdda41dbafb6c1cda8a5cc023e7d1bdc96cf
MD5 d1756f96c8fc050e3e12afd7883127cf
BLAKE2b-256 c9d1c73036fb38cdb0131c1133c1928b6ebe8d30bc614415b09a110194f0fa1d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page