Skip to content

Repository files navigation

Happy PRs

macOS menubar app showing GitHub PRs and issues that need my input.

Happy PRs menubar popover

The menubar icon shows incoming|your-PRs|issues counts (PRs needing your approval, your own open PRs, and issues awaiting your response), each capped at 99+. The seal fills in when there are unread notifications. When nothing's pending it shows just the seal:

Menubar icon with counts Menubar icon empty

Buckets

  • Needs your approval: I (or my team) am a reviewer, and no one has approved the current HEAD yet.
  • Wants your approval: same as above, but someone else has already approved.
  • Mentions you: I'm @-mentioned in the body, a comment, a review summary, or an inline review thread. Additive, so it can overlap with the other buckets.

Stale-approval detection: catches PRs where my prior approval was dismissed by new commits but GitHub didn't re-request me.

Requirements

  • macOS 14 (Sonoma) or newer
  • gh, authenticated via gh auth login. The Homebrew cask installs gh automatically; the from-source path requires it to be installed already.
  • Xcode 16+ for the from-source / development paths only (not needed for Homebrew users).

Install

Homebrew (recommended)

brew install --cask frodi-karlsson/tap/happy-prs
open "/Applications/Happy PRs.app"

To have it start automatically on login, open Settings (⌘, from the menubar popover, or via the Settings… button in the footer) and toggle Open at login under the Startup section. macOS will prompt for permission the first time; once approved, Happy PRs starts at every sign-in.

From source (auto-starts on login)

./install.sh

This builds in release mode, bundles the binary into ~/Applications/Happy PRs.app, and registers a LaunchAgent so the app starts on login. Re-run after pulling changes to update. (You can also use the in-app Open at login toggle on the brew-installed app instead; both end up registering with launchd, just via different mechanisms.)

Development

./setup-hooks.sh # one-time: activates .githooks/ for this clone
./dev.sh         # swift run with the installed copy stopped
./check.sh       # run every CI check locally in one pass
swift test       # run just the test suite

check.sh runs swift-format lint, actionlint (workflow YAML linting; install once with brew install actionlint), debug + release builds, and the full test suite. Same toolchain and strictness as CI.

dev.sh runs the binary directly via swift run. You'll see a transient dock icon during development; that's expected (it goes away in the bundled .app).

The pre-commit hook (.githooks/pre-commit) regenerates the README screenshots whenever a commit touches Sources/, and re-stages any PNG whose content changed. Bypass with git commit --no-verify if you ever need to.

Releasing

./bump.sh {patch|minor|major} tags the next version and pushes it; the release workflow then builds the artifact, publishes the GitHub release, and bumps the Homebrew tap.

Changelogs are generated from commit messages by git-cliff. Install it once with brew install git-cliff (required by bump.sh). Keep commit subjects in Conventional-Commits style (feat:, fix:, docs:, refactor:, …): bump.sh regenerates CHANGELOG.md and both it and the release workflow fail the release if there are no changelog-worthy commits since the last tag, so every release gets notes.

Uninstall

./uninstall.sh

Removes the LaunchAgent, the app bundle, and stops the running process. UserDefaults settings remain unless you defaults delete com.frodikarlsson.happyprs.

Your PRs

The Your PRs tab tracks open PRs you authored that need attention:

  • approved: ready to merge or send to QA
  • conflict: has merge conflicts with the target branch
  • unresolved: has unresolved review threads where the last comment isn't yours
  • replied: has top-level comments awaiting your response

Issues

The Issues tab shows open GitHub issues awaiting your response: among issues that involve you (as assignee, author, mentioned, or commenter), the ones where the most recent activity isn't yours. Issues you've unsubscribed from or muted are excluded.

Each row has an actions menu to archive or snooze it, the same options as PRs:

  • Archive until activity: hidden until the issue gets new activity
  • Archive forever: hidden until you unarchive it
  • Snooze 1 day / 3 days / 1 week: hidden until the interval passes

Archived issues collapse into an Archived section at the bottom of the tab, and they don't trigger notifications until they resurface.

Notifications

Click the bell icon (footer) to open the notification history panel. It shows a timeline of every event the app has notified you about. Unread notification count shows as a badge on the bell icon; viewing the panel marks all as read. Each stream (incoming, your PRs, merged, issues) also marks itself read when you view its respective tab.

Configure which events trigger notifications in Settings: toggle incoming, your-PR, merged, and issues streams independently, and fine-tune per category within each stream (e.g. only .approved notifications for your PRs, or only .needsApproval for incoming). All four streams are on by default.

When a newer version is available, a subtle ⚠ Outdated indicator appears in the footer. Hover to see the version diff and brew upgrade command.

Settings

Open with ⌘, from the menubar popover (or click the Settings… button in the footer).

  • Refresh interval: how often the app polls GitHub (30s to 15m)
  • Open at login: register the app as a launch-on-login item
  • Hidden repos: PRs from these repos won't appear in the incoming list
  • Excluded comment authors: comments from these authors (e.g. bots) are ignored when computing awaiting-reply and unresolved-thread checks
  • Notification preferences: choose which events trigger notifications, by stream and category

Settings window

About

MacOS widget for monitoring PRs that need your attention

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages