A macOS menu-bar app that keeps the GitHub pull requests you care about one click away — the ones waiting on your review and the ones you opened. Every tab is a saved GitHub search; switching tabs re-filters the list live, and a badge on the menu-bar icon counts the PRs in the queries you choose.
- Lives in the menu bar. No dock icon, no window to manage. Click the git-pull-request mark to open a compact panel.
- Saved queries as tabs. Each tab is one GitHub search (e.g. To review,
My PRs). Build them from qualifier chips —
is:open,review-requested:@me,draft:false,label:"ready for review",repo:owner/name, … — the same syntax you type in GitHub's search box. - Live match count. The editor tells you how many open PRs a query matches as you add and remove qualifiers.
- Review-thread filters.
comments:unresolvedkeeps only PRs with at least one unresolved review thread;comments:resolvedkeeps the rest, including PRs nobody has commented on. GitHub's search syntax has no such qualifier — PR Radar applies these itself, and every row shows its unresolved count regardless. - Menu-bar badge. Opt any query into the badge; the icon shows the running total so you know when something needs you without opening anything.
- At-a-glance rows. Author avatar, repo, PR number, age, additions/deletions, CI status, review decision, and labels — per row.
- Drag to reorder tabs, light/dark aware, configurable refresh interval.
- Auto-updates via Sparkle.
-
macOS 14 (Sonoma) or later.
-
GitHub CLI (
gh) installed and authenticated — PR Radar uses it as its data layer. Authenticate once with:gh auth login
The app finds
ghin the usual locations (/opt/homebrew/bin,/usr/local/bin, …). If it's missing or logged out, the panel shows inline guidance.
-
Download the latest
PRRadar-*.zipfrom the Releases page. -
Unzip and move
PRRadar.appto/Applications. Finder shows it as PR Radar, but the file on disk isPRRadar.app. -
First launch only. The build is ad-hoc signed, not notarized, so macOS quarantines it. Clear the quarantine flag from the terminal:
xattr -dr com.apple.quarantine "/Applications/PRRadar.app"Tip: type
xattr -dr com.apple.quarantine(trailing space), then drag the app from Finder into Terminal to fill in the path — no typing the name.No terminal? Double-click the app, let it get blocked, then open System Settings → Privacy & Security, scroll to Security, and click Open Anyway. On macOS 15 (Sequoia) and later the old right-click → Open shortcut no longer bypasses Gatekeeper for non-notarized apps.
After that, Sparkle keeps it up to date automatically — every later version is verified by EdDSA signature, so the Gatekeeper dance is a one-time thing.
- Click the menu-bar icon to open the panel. It refreshes on launch, when the panel opens, on a background timer, and via the header refresh button.
- The two starter tabs — To review and My PRs — are ordinary saved queries: rename, edit, reorder, or delete them like any other.
+adds a new tab. The sliders icon at the end of the query row opens the editor for the active tab, where you compose qualifiers as chips and toggle Count in menu-bar badge.- Under the query box, PR Radar filters are one-tap chips for the filters
GitHub search can't express: unresolved comments (
comments:unresolved) and nothing unresolved (comments:resolved). They're applied to the fetched results, not sent to GitHub, and picking one clears the other. - The gear opens Settings: refresh interval (1 / 5 / 15 / 30 min), Check for Updates, and Quit.
State (your queries, the active tab, the refresh interval) is stored in
~/Library/Application Support/PR Radar/state.json.
Dev mode, for fast iteration:
swift build
swift run PRRadar # or: .build/debug/PRRadarA double-clickable, shareable .app bundle:
Scripts/build-app.sh # → dist/PRRadar.app (release, ad-hoc signed)
open dist/PRRadar.appThe bundle is dockless (LSUIElement), embeds the fonts
(ATSApplicationFontsPath) and Sparkle.framework, carries the PR-glyph icon,
and is ad-hoc signed. See Scripts/build-app.sh for the configurable bits
(bundle id, version, minimum macOS, Sparkle feed and key).
Installed copies poll an appcast and self-update — no Developer ID needed, because downloads are verified by EdDSA signature.
Scripts/release.sh 0.2.0 # build → zip → EdDSA-sign → gh release → appcast → pushThat builds dist/PRRadar.app at the given version, zips and signs it with the
Sparkle EdDSA key (private key in the login keychain), publishes a GitHub release
with the zip asset, then regenerates and pushes appcast.xml. The app's
SUFeedURL points at the raw appcast.xml; SUPublicEDKey in the Info.plist
verifies downloads. Requires gh installed and authenticated.
Each tab shells out to gh api graphql (search(type: ISSUE)), passing the
composed query as an opaque -f q= variable — one search call per tab. is:pr
is injected into every query. A saved query is just
{ id, name, tokens: [String], countInBadge }, and the search string is the
tokens joined by spaces.
comments:unresolved and comments:resolved are the tokens GitHub never sees:
review-thread state isn't searchable, so they are stripped from q and applied
to the returned rows (the state rides along in the same query for free). For
those queries the tab count is the number of kept rows rather than GitHub's
total, shown as N+ if a full page came back with more matches behind it.
For the domain language and the locked-in design decisions, see
CONTEXT.md and docs/adr/.
MIT © 2026 iYasha

