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 noise (lock files, build dirs, minified, generated)
│
▼
[ chunker ] ── packs files into ≤60k-char chunks (hybrid batching)
│
▼
[ 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
│
▼
[ report_generator ] ── merges findings, computes risk level
│
▼
reports/report.json + reports/review-report.md
Requirements
- Python 3.11+
- Claude Code CLI installed and authenticated.
claude --versionmust work from your shell. - Git, if you want to review live branches (not required for
--diffmode).
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 |
60000 |
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. |
--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. |
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.
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
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:
- Summary — risk level, source, branch, timestamp, agents, finding counts
- Merge Verdict — deterministic verdict driven by risk level (not a separate Claude call)
- Key Findings — top blocking issues (High + Medium)
- Key Recommendations — deduplicated fixes
- 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.
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 |
| Unknown | All executed agents failed — risk could not be determined |
Architecture
src/pr_sentinel/
├── cli.py # Click entrypoint + Rich UI
├── git_diff.py # git rev-parse, git diff, --staged
├── diff_parser.py # per-file splitting + noise filter + 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
├── cache.py # sha256-keyed disk cache for Claude responses
├── 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
└── prompts/
├── security.md
├── quality.md
├── performance.md
└── testing.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 diff_parser.py.
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.
lineHintis 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.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pr_sentinel-0.1.0.tar.gz.
File metadata
- Download URL: pr_sentinel-0.1.0.tar.gz
- Upload date:
- Size: 30.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c6604540ae4f7590cc429c964daa5ff7c504cb5ee3a482c6e26d0ecb08d5ae8
|
|
| MD5 |
42dbe79d2ba6d4a2dd04aba0f801b018
|
|
| BLAKE2b-256 |
190f50de8d45a6ec38f2c2771f6a6d5f1224818ae65267ce417fb139ba1a335f
|
File details
Details for the file pr_sentinel-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pr_sentinel-0.1.0-py3-none-any.whl
- Upload date:
- Size: 29.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c2911b02bed94838b22dab44b5d41316e3fbffcfe664122faa76e46346ffaf0d
|
|
| MD5 |
27c563874d9b6d9c30cf7aad9a2074a8
|
|
| BLAKE2b-256 |
beda7629570db8644ba2e74af0bae4af687552a8cf10035f94bf822a03eee13e
|