Read a pull request the way the code runs — not the way git diff prints it.
Loupe is a macOS desktop app that reorders a PR into data-flow order and walks you through it one symbol at a time, with AI that clusters the change, labels each group, and answers questions about your actual codebase inline.
A diff is a pile of files in alphabetical order. But that's not how you understand a change — you follow it: where data enters, how it's transformed, where it lands. Loupe does that reordering for you:
- Data-flow order, not file order. The engine groups the change into clusters and lays them out so you read entry points → core logic → edges.
- One symbol-card at a time. A focused card per changed function/type. Keyboard-first:
Spaceto pass,←/→to move. No 4,000-line scroll. - Grounded AI, not vibes. Threads run an agentic, read-only Claude scoped to the repo — it reads the real definitions and callers, not just the diff snippet.
- 🧭 Data-flow review — clusters + flow ordering so a PR reads as a story.
- 🃏 Symbol cards — one changed function/type per card, split before/after diff.
- 💬 Inline threads — drag to select lines, ask a question; the answer is codebase-aware (reads definitions/callers across the repo). Pick Sonnet or Haiku per thread. Threads persist with the review.
- 🔗 Jump links — when an answer references another changed symbol, it's a click away.
- 🧠 Editor handoff —
⌘-clickany diff line to open the whole project at thatfile:linein IntelliJ IDEA or VS Code. - ⌨️
loupeCLI —loupe <path> [base] [target]from a terminal or an AI skill; the app opens and starts the review (and remembers it in recents). - 🔎 Fast project switching — branch picker with live search; recent projects.
- 🔍
⌘ + scrollto zoom the code; adaptive font that fits the change. - ✅ Approve the PR — when a review ends all-pass, approve the GitHub PR straight
from the summary screen (delegated to your
ghCLI; explicit two-step confirm). - 🗄️ SHA-cached — re-opening an unchanged range is instant (no AI re-spend).
- macOS 11 (Big Sur) or later — universal build (Apple Silicon + Intel).
- Claude Code CLI installed and on your
PATH— Loupe shells out toclaudefor all AI work. - A Claude setup-token: run
claude setup-tokenand paste it into Loupe once (stored locally on your Mac,chmod 600, never logged). - (optional) the GitHub CLI (
gh), signed in (gh auth login) — only needed to approve a PR from the summary screen.
Loupe makes no network calls of its own — every AI request goes through your
claudeCLI with your token.
Homebrew (recommended)
brew install --cask JiwonKKang/loupe/loupeTo update: brew upgrade --cask loupe.
Or grab the DMG from Releases →
drag Loupe.app to /Applications.
The build is ad-hoc signed (no paid Apple Developer cert). The Homebrew cask strips the quarantine flag for you. If you install the DMG by hand and Gatekeeper complains:
xattr -dr com.apple.quarantine /Applications/Loupe.app.
- Launch Loupe → paste your
claude setup-token. - Top-left menu → Browse to a git repo → pick base and target branches → Open review.
- Walk the cards:
Spacepass ·←/→move ·⌘Ejump back to the previous card. - Drag across lines on a card to open an inline thread and ask away.
⌘-clicka line to open it in your editor; the bottom bar's logo picks IntelliJ / VS Code.
Installed alongside the app by the Homebrew cask.
loupe # current dir, auto base/target
loupe ~/code/myproject main feature/x # explicitIt resolves the range and opens the app straight into the review.
git 3-dot diff (base...target)
│
▼
tree-sitter symbol extraction → one card per changed function / type
│
▼
AI clustering + flow ordering (Claude Sonnet) ┐
per-cluster labels (Claude Haiku, in parallel) ┘ → data-flow ordered review
│
▼
SHA cache (SQLite) → unchanged range = instant, 0 AI calls
Inline threads run a separate agentic, read-only Claude (Read/Grep/Glob/LS only; no writes, no shell) confined to the repo, so answers are grounded in the real code.
| Language | Review granularity |
|---|---|
| Go, Java, Rust | Symbol-level (per function / type, via tree-sitter) |
| Everything else | File-level cards (still ordered & clustered) |
Adding a language is mostly wiring up its tree-sitter grammar — PRs welcome.
- Tauri 2 shell · React 19 (plain JS) front-end
- Rust engine:
git2(diff),tree-sitter(symbols),rusqlite(cache) - AI via the
claudeCLI (Claude Code) — Sonnet for structure, Haiku for labels
git clone https://github.com/JiwonKKang/loupe
cd loupe
npm install
npm run tauri dev # run
npm run tauri build # produce a universal .dmg / .appRequires Node, Rust, and the Tauri prerequisites.
- Your token is stored only on your Mac (
~/Library/Application Support/com.jiwon.loupe/),0600, and passed to theclaudechild process via env — never on a command line, never logged. - The app itself opens no network connections; AI traffic is the
claudeCLI on your machine.
Issues and PRs welcome — language grammars, editor integrations, and UI polish especially.
MIT © 강지원 (Jiwon Kang)