Local-first pull request review for macOS

You're the reviewer.
Pruse just makes you faster.

Every pull request checked out on your own machine. A diff that keeps up with your keyboard. Reviews that survive force-pushes. And an AI that can read your code — but is never allowed to run it.

Free & local · Apple Silicon · Works with the gh login you already have. No account, no telemetry.

OpenIdempotent retries for webhooks#482
Conversation 6Files 4Commits Changed since your review Review 2
Filter files  /
src/webhooks
M retry.ts +18
A backoff.ts +64
M handler.ts +41
test
M retry.test.ts +22
All changesSince your review 2 new commits · rebased ✦ Ask
src/webhooks/retry.ts+18
12export async deliver(event: WebhookEvent) {13  const key = idempotencyKey(event)14  for (let i = 0; i < 3; i++) {14  for (const delay of backoff({ max: 5 })) {15    const res = await post(event.url, event.body)15    const res = await post(event.url, event.body, { headers: { 'Idempotency-Key': key } })16    if (res.status === 409) return 'duplicate'17    if (res.ok) return 'delivered'18    await sleep(delay)19  }
youDraftline 16 · not posted yet

Should a 409 still record the attempt? Otherwise the dashboard shows it as never sent.

20  throw new DeliveryError(event.id)21}
test/retry.test.ts+22
31test('a 409 counts as delivered once', async () => {32  server.reply(409)33  expect(await deliver(event)).toBe('duplicate')34})
Try a theme Tokyo Night

What's inside

Everything a careful reviewer wants.
Nothing that reviews for you.

A diff that keeps up with your hands

Virtualized, syntax-highlighted, unified or side by side. Move with j k, jump files with n p, mark viewed with v, comment with c. Lock files and generated code fold themselves away.

⎇

Real checkouts, not a web view

Each PR is fetched into its own git worktree. Jump to definitions in your editor, grep the whole repo, read the files around the change.

✎

Drafts that survive new pushes

Comments stay local until you submit. If the author pushes meanwhile, Pruse finds your lines again by content and moves them.

◐

Sixteen themes

From GitHub Dark to Rosé Pine Dawn. Pick one per light and dark mode; the diff colors follow.

✦

Ask, privately

Select lines, press a, and ask Claude Code about them. Answers appear only for you — turn one into a draft if it's worth saying, in your own words.

Merges that can't surprise you

Merge, squash or rebase from the Conversation tab. Pruse tells GitHub exactly which commit you looked at — if someone pushed after you, the merge is refused instead of shipping code nobody reviewed.

❝

The whole conversation

Description, checks, reviews and threads in one calm column. Reply, resolve, and jump from any thread to its line in the diff.

Your own branches, too

Every worktree's changes at a glance. Switch branches, fetch, fast-forward, stage, commit, push and open a PR — with a description the AI can draft for you to edit. Nothing that could lose work: no resets, no force-pushes.

Re-review

Force-pushed? Rebased?
See only what's new.

Submitting a review pins the exact commit you saw. When the author pushes again — even a rebase — Pruse shows Changed since your review and diffs just that.

What happened
What you read
All changes251lines · 4 files
Since your review3lines · 1 file
Survives force-pushes

The commit you reviewed is pinned in your clone, so rewriting the branch can't make it disappear.

Rebase-aware

Your old changes are replayed onto the new base first. What the base brought in stays out of your way.

Viewed stays viewed

Files you already ticked keep their check — unless their content actually changed.

Principles

PR code is untrusted.
So the agent never runs it.

Pruse drives the Claude Code you already have, but on its own terms. The agent can read and search the checkout. It can't execute commands, write files or reach the network — enforced from outside, in layers.

  1. 01

    Only three tools exist

    The session is created with Read, Grep and Glob. There's no shell, no editor, no web fetch to misuse.

  2. 02

    Nothing loads from the repo

    No project settings, hooks, instructions or MCP servers — a malicious PR can't configure the agent that reads it.

  3. 03

    Every other request is refused

    Anything that isn't a read inside the checkout is denied — and shown to you, so you see what it tried.

  4. 04

    No doors on the client

    Pruse advertises no terminal and no file writing to the agent. There's nothing to ask for.

0servers of ours your code touches
0comments posted without your click
1token, from your existing gh login

From the terminal

One command away
from any repo.

~/code/payments
$ 
Opening acme/payments#482 in Pruse…
$ pruse inbox
  REVIEW REQUESTED
  #482  Idempotent retries for webhooks   maya   +214 −37
  #479  Split ledger writes by tenant     theo    +88 −12
$ pruse diff      # your own uncommitted changes

Get Pruse
for your Mac.

Free, for Apple Silicon Macs. Everything runs on your machine.

Download Pruse.zip

Apple Silicon · macOS

1

Unzip and drag Pruse.app into Applications.

2

Pruse isn't notarized by Apple yet, so the first time, right-click it → Open → Open. Or in Terminal:

xattr -dr com.apple.quarantine /Applications/Pruse.app
3

Optional: the pruse command, to open any repo or PR from your terminal.

ln -sf /Applications/Pruse.app/Contents/Resources/app/bin/pruse ~/.local/bin/pruse

Needs git and the GitHub CLI, logged in (gh auth login). Claude Code is optional — without it, Pruse is simply a great diff.