PRWATCH
Review your own pull requests with the AI agent you already pay for โ locally, with zero CI cost.
One daemon. Every new PR reviewed.
Pick the repos to watch, pick your agent, leave it running. New PR appears โ shallow clone โ your agent runs the rubric โ one structured review comment โ clone deleted.
Zero CI cost
Nothing runs in Actions. The review happens on your machine with the agent subscription you already have.
Your agent, your rules
Claude Code, Codex, or OpenCode โ auto-detected from your PATH. The rubric is a markdown file you own.
No backlog, no spam
Only PRs opened after you start watching. Each PR reviewed exactly once. Temp clones always deleted.
Quickstart
Three prerequisites, one install, two commands.
1. Prerequisites
- Node.js
โฅ 20 gh(GitHub CLI), logged in โgh auth login- At least one agent CLI on your
PATH:claude,codex, oropencode
2. Install
$ npm install -g prwatch
3. Configure, then watch
$ prw # TUI: add repos, pick your agent, check status $ prw daemon # start the watcher in the foreground (tmux-friendly)
Open a PR on a watched repo. Within one poll interval (default 3 minutes) the review lands as a single comment on the PR.
How it works
- Poll โ every
pollIntervalMinutes,ghlists open PRs for each watched repo. - Filter โ PRs opened before you started watching that repo are skipped, so there is no backlog spam. Already-reviewed PRs are skipped via a local ledger plus an invisible
<!-- prwatch -->marker on the posted comment, which makes reviews idempotent even if local state is lost. - Clone โ the PR head is shallow-cloned into
~/.prwatch/cache/. - Review โ your agent runs inside that checkout with the rubric plus the PR title/body, fenced inside
<untrusted-pr-content>tags. - Post & clean โ the agent's output is posted as one PR comment, then the temp clone is deleted. Cache is empty between reviews.
Push more commits to a PR that was already reviewed and PRWatch will not re-review it.
Commands
| Command | What it does |
|---|---|
prw | Opens the TUI โ add/remove repos, choose the agent, see status. |
prw daemon | Runs the watcher in the foreground. Ctrl+C shuts down gracefully (no orphaned agent processes). |
prw service install | Installs a login service (launchd on macOS, systemd user unit on Linux) and prints the path it wrote. |
The TUI
Launched with a bare prw. Arrow keys / j k to move, Enter to select, q to quit.
| Screen | Purpose |
|---|---|
| Repos | Add a repo by fuzzy-searching your GitHub repos live (type to filter, Enter to add), or remove a watched one. |
| Agent | Pick among the agents actually installed on your machine โ PRWatch probes claude, codex, opencode. |
| Status | Watched repos, selected agent, and what the daemon last did. |
Configuration
~/.prwatch/config.json. The TUI writes it; editing by hand is fine. Invalid values are rejected on load rather than silently coerced.
{
"repos": ["adisagar2003/PRWatch"],
"agent": "claude",
"pollIntervalMinutes": 3,
"agentTimeoutMinutes": 10
}
| Key | Default | Notes |
|---|---|---|
repos | [] | Array of owner/name strings. |
agent | "claude" | One of claude, codex, opencode. |
pollIntervalMinutes | 3 | Finite number > 0. |
agentTimeoutMinutes | 10 | Hard timeout per review; the agent process is killed past it. |
Rubric
The review prompt's checklist. Edit it freely โ this is where you encode what your team actually cares about.
| Location | Scope |
|---|---|
~/.prwatch/rubric.md | Your default, used for every watched repo. |
.prwatch/rubric.md | Committed at a repo's root โ overrides the default for that repo. |
Run at login
$ prw service install service installed: ~/Library/LaunchAgents/com.prwatch.daemon.plist
macOS gets a launchd agent, Linux a systemd user unit. Prefer a foreground prw daemon in tmux while you're still tuning the rubric โ the log is right there.
Security
Watching a public repo means running your agent against untrusted input: the PR title and body, and the PR's own files โ which can include agent-instruction files like CLAUDE.md that an attacker committed specifically to steer your agent.
PRWatch fences the PR title/description inside <untrusted-pr-content> tags in the prompt it sends. That does not stop an agent from reading attacker-added files inside the checkout โ that mitigation has to come from your agent's own permission model.
State & logs
Everything lives under ~/.prwatch/ โ delete the directory to fully reset.
| Path | Contents |
|---|---|
config.json | Watched repos, agent, intervals. |
state.json | Watch start times and the reviewed-PR ledger. |
rubric.md | Your default review rubric. |
logs/daemon.log | Poll, review, and post activity โ first place to look. |
cache/ | Temp shallow clones. Empty between reviews. |
repo-find.sh
A standalone fzf picker for your GitHub repos, for use outside the TUI. It ships only in a source checkout (git clone) โ it is not in the npm package. Requires gh and fzf.
$ ./repo-find.sh # pick a repo, print its URL $ ./repo-find.sh open # open it in the browser $ ./repo-find.sh clone # clone into the current folder $ ./repo-find.sh view # show details in the terminal
A live preview pane runs gh repo view on whatever you hover. The repo list is cached for 10 minutes under ${XDG_CACHE_HOME:-~/.cache}/prwatch/. Fetches up to 300 repos โ raise it with REPO_LIMIT=500 ./repo-find.sh.
Troubleshooting
| Symptom | Check |
|---|---|
| No agents listed | Is the CLI on your PATH? PRWatch resolves it with which; shell aliases and functions are invisible to it. |
| Nothing gets reviewed | Only PRs opened after you added the repo qualify. Open a fresh one, and confirm gh auth status is green. |
| Review never posts | Tail ~/.prwatch/logs/daemon.log. A long agent run gets killed at agentTimeoutMinutes โ raise it. |
| Same PR reviewed twice | Shouldn't happen: the ledger plus the <!-- prwatch --> comment marker both guard it. If it does, file an issue. |
cache/ not empty | Leftover from a hard kill. Safe to delete by hand. |
Full manual end-to-end walkthrough: docs/e2e.md.