Stealth PR reviewer — looks like you wrote every word.
Project description
rpr — Stealth PR Reviewer
AI-powered PR reviews that look like you wrote them. No GitHub Apps, no bots, no traces.
What It Does
- Fetches the PR diff from GitHub
- Sends it to Claude with a prompt engineered to sound like a senior engineer (not AI)
- Posts the review under your GitHub account inline comments on specific lines
Nobody can tell the difference.
Install
| Channel | Command |
|---|---|
| pipx (recommended) | pipx install rpr |
| pip | pip install --user rpr |
| Homebrew | brew install dedev-llc/rpr/rpr |
| npm | npm install -g @dedev-llc/rpr |
| npx | npx @dedev-llc/rpr <pr-number> |
| curl | curl -fsSL https://raw.githubusercontent.com/dedev-llc/rpr/main/install.sh | bash |
All channels install the same rpr command. You'll also need:
- GitHub CLI (
gh) — install, thengh auth login - Anthropic API key —
export ANTHROPIC_API_KEY=sk-ant-...(get one) - Python 3.9+ (already required by all channels except npm/npx, which need it on PATH at runtime)
Usage
# In any git repo:
rpr 42 # Review PR #42
rpr 42 --dry-run # Preview in terminal first
rpr 42 --approve # Review + approve
rpr 42 --request-changes # Review + request changes
rpr 42 --comment-only # Post as single comment (no inline)
rpr 42 --repo owner/repo # Specify repo explicitly
rpr 42 --model claude-sonnet-4-6 # Override model
rpr 42 -v # Verbose mode (debug)
Recommended Workflow
-
Always dry-run first until you trust the output:
rpr 42 --dry-run
-
If it looks right, post it:
rpr 42
-
Optionally tweak a word or two in the posted review for your personal touch.
Configuration
rpr ships with sensible defaults. To override them, drop a config file at one of these paths (first match wins):
./rpr.config.json— project-local override (per-repo)~/.config/rpr/config.json— user-wide
Example (see examples/config.json):
{
"model": "claude-opus-4-6",
"max_tokens": 16000,
"max_diff_chars": 120000,
"skip_patterns": [
"*.lock",
"*.g.dart",
"*.freezed.dart"
]
}
| Key | Meaning |
|---|---|
model |
Claude model to use |
max_tokens |
Max response length |
max_diff_chars |
Truncate diffs larger than this |
skip_patterns |
Glob patterns for files to ignore (generated code, locks, etc.) |
Custom review guidelines
Inject your team's coding standards by dropping a review-guidelines.md at:
./review-guidelines.md— project-local (per-repo)~/.config/rpr/review-guidelines.md— user-wide
The contents get appended to the system prompt and the AI enforces them as if they were your personal standards. See examples/review-guidelines.md for a starter template.
How It Stays Invisible
| Concern | Solution |
|---|---|
| GitHub Actions history | None — runs locally on your machine |
| Workflow files in repo | None — no .github/workflows needed |
| Bot label on comments | None — uses your PAT via gh CLI |
| AI-sounding language | Prompt is engineered to sound human |
| Review pattern detection | Varies tone, uses informal language |
Cost
Each review costs roughly $0.01–$0.08 depending on diff size and model:
- Small PR (< 200 lines): ~$0.01
- Medium PR (200–1000 lines): ~$0.03
- Large PR (1000+ lines): ~$0.05–0.08
Tips
- Edit after posting: Tweak a word or two in your posted review for authenticity.
- Use
--dry-runliberally: Especially on important PRs. - Customize guidelines: The more specific your
review-guidelines.md, the better the reviews match your real style. - Skip generated files: Add patterns for code generators your team uses (Freezed, json_serializable, etc.) to avoid noise.
Development
git clone https://github.com/dedev-llc/rpr
cd rpr
python -m venv .venv && source .venv/bin/activate
pip install -e . # editable install — `rpr` command works from anywhere
rpr --help
Run as a module: python -m rpr 42 --dry-run
macOS gotcha: do not clone the repo into
~/Desktop(or~/Documents). macOS sets theUF_HIDDENfile flag on everything inside those App Sandbox directories, which makes Python 3.13'ssite.pyskip the editable install's.pthfile (it treats hidden-flagged files as hidden, regardless of name). The published wheel from PyPI is unaffected — this only bites editable dev installs in sandboxed dirs. Symptom:ModuleNotFoundError: No module named 'rpr'afterpip install -e .. Fix: clone to~/code/rpror somewhere outside the sandbox.
Publishing (maintainer notes)
The PyPI package is the source of truth. Other channels wrap it.
PyPI
pip install build twine
python -m build # produces dist/rpr-X.Y.Z.tar.gz + .whl
twine upload dist/* # requires PyPI account + token
Homebrew formula
After publishing to PyPI, update Formula/rpr.rb:
SHA=$(curl -sL https://files.pythonhosted.org/packages/source/r/rpr/rpr-0.1.0.tar.gz | shasum -a 256 | cut -d' ' -f1)
# Edit Formula/rpr.rb: replace the placeholder sha256 with $SHA, bump version in url
git commit -am "brew: bump rpr to 0.1.0" && git push
Users install via: brew install dedev-llc/rpr/rpr
npm
cd npm
npm version 0.1.0 --no-git-tag-version # match pyproject.toml version
npm pack --dry-run # sanity check: should list bin/ + lib/
npm publish # requires npm login
The prepack hook copies src/rpr/*.py into npm/lib/ automatically.
Release checklist
- Bump version in
pyproject.toml,src/rpr/__init__.py,npm/package.json,Formula/rpr.rb(url) - Tag:
git tag v0.1.0 && git push --tags - Publish to PyPI (above)
- Update Homebrew formula sha256 (above)
- Publish to npm (above)
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
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 rpr-0.1.1.tar.gz.
File metadata
- Download URL: rpr-0.1.1.tar.gz
- Upload date:
- Size: 14.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b51ccae628b16c6211128188560143b638c0546e3e3d4d343ee9242928d7867
|
|
| MD5 |
69b194fc04231a5585732e8f6897ce93
|
|
| BLAKE2b-256 |
b40ba46630537b00936ab829b2461eddf417dd6a10ea2df09c51cb3e8f72bfb3
|
Provenance
The following attestation bundles were made for rpr-0.1.1.tar.gz:
Publisher:
release.yml on dedev-llc/rpr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rpr-0.1.1.tar.gz -
Subject digest:
9b51ccae628b16c6211128188560143b638c0546e3e3d4d343ee9242928d7867 - Sigstore transparency entry: 1263226029
- Sigstore integration time:
-
Permalink:
dedev-llc/rpr@2e60a5b2fa73a95fe0f35eef49f3497f55343733 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/dedev-llc
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2e60a5b2fa73a95fe0f35eef49f3497f55343733 -
Trigger Event:
push
-
Statement type:
File details
Details for the file rpr-0.1.1-py3-none-any.whl.
File metadata
- Download URL: rpr-0.1.1-py3-none-any.whl
- Upload date:
- Size: 14.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa213e6be72e4636a05c9cc6263750e95654ab633ddadc86621823a693be3aa6
|
|
| MD5 |
eeb9504d6120c8a1dd758bc1b22e5b24
|
|
| BLAKE2b-256 |
67b85ee732d3f003d5c6844d6601427fc65999c31b77b6b37cfa307bf1518a04
|
Provenance
The following attestation bundles were made for rpr-0.1.1-py3-none-any.whl:
Publisher:
release.yml on dedev-llc/rpr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rpr-0.1.1-py3-none-any.whl -
Subject digest:
fa213e6be72e4636a05c9cc6263750e95654ab633ddadc86621823a693be3aa6 - Sigstore transparency entry: 1263226078
- Sigstore integration time:
-
Permalink:
dedev-llc/rpr@2e60a5b2fa73a95fe0f35eef49f3497f55343733 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/dedev-llc
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@2e60a5b2fa73a95fe0f35eef49f3497f55343733 -
Trigger Event:
push
-
Statement type: