Pull Requests are a state, not an event.
Stop letting PRs rot in silence. Unblockd is a native macOS menu bar app that shows you exactly which Pull Requests need your attention - without the notification spam.
Unified PR monitor for Bitbucket Cloud, GitHub, and GitLab.com.
No notification spam. No context switching. Just your PRs.
If you work across multiple repos and providers, you've felt this pain:
- 🌐 Provider chaos - Switching between Bitbucket, GitHub, and GitLab in browser tabs
- 📊 Scale problem - 10+ repositories? You've lost track of what needs review
- 🔔 Notification fatigue - Email/Slack alerts for every PR event (comment, CI, approval)
- 🎯 No unified view - "Which PRs are blocking my team right now?"
The traditional approach fails:
Open 3 browser tabs → Check each provider manually → Miss critical PRs anyway → Get interrupted by notification spam you've already muted.
Unblockd solves this with a unified workspace:
All your PRs (Bitbucket + GitHub + GitLab) in one menu bar. Smart filtering shows only what needs your attention. Check once/hour on your terms, not when an email decides to ping you.
🔄 One place for everything - Bitbucket, GitHub, GitLab - stop context switching between providers
📈 Scales with you - From 3 repos to 50+ across multiple providers (Bitbucket for work + GitHub personal + GitLab clients)
🎯 Smart filtering - Only shows PRs that you can act on right now (assigned reviews, your PRs waiting, team blockers)
🤫 Quiet by design - Checks at configurable intervals (default: 30 min). You're in control, not your notifications
⏰ Respects your schedule - Set office hours (9-5). Badge goes dark after work. Guilt-free evenings
🔒 Privacy-first - 100% local. No tracking. No servers. Your data stays on your Mac
- To Review - PRs where you're assigned and haven't acted yet
- Waiting - Open PRs you've already reviewed, waiting for others or merge
- Merged - PRs merged while your assigned review was still pending
- My PRs - Your open PRs (including drafts)
- Other / Team - Everything else your team is working on
- Snoozed - PRs you've temporarily hidden
- Bitbucket Cloud - Finally, a modern tool for Bitbucket
- GitHub - Public and private repositories
- GitLab - GitLab.com (cloud)
- Draft PR detection across all providers
- Repository discovery and monitoring
- Adapts automatically to macOS light/dark appearance
- Active days/hours scheduling
- Configurable refresh intervals (15-120 min)
- Launch at login
- Secure token storage in macOS Keychain
- Local rate-limit tracking per provider
- Battery-aware polling
- Lightweight memory footprint
brew install --cask mpassion/tap/unblockdIf macOS warns that it cannot verify the app, use right-click Open once.
Quick steps are in macOS Security Note.
git clone https://github.com/mpassion/unblockd.git
cd unblockd
swift buildOpen Preferences → Account and add your credentials:
Bitbucket Cloud
- Create token: https://id.atlassian.com/manage-profile/security/api-tokens
- Required scopes:
read:user:bitbucket,read:repository:bitbucket,read:pullrequest:bitbucket
GitHub
- Create token: https://github.com/settings/tokens
- Fine-grained PAT (recommended): Pull requests (Read-only), Metadata (Read-only)
- Classic PAT:
repoorpublic_repo,read:user
GitLab
- Create token: https://gitlab.com/-/user_settings/personal_access_tokens
- Required scope:
read_api - Note: Requires at least Developer access to monitored projects
Go to Preferences → Discovery to search and add repositories you want to monitor.
In Preferences → Schedule, set your:
- Active days (e.g., Mon-Fri)
- Active hours (e.g., 9:00-17:00)
- Refresh interval (default: 30 min, configurable 15-120 min)
That's it! Unblockd will now quietly monitor your PRs during work hours.
The fundamental problem isn't just notification spam - it's fragmentation.
When your work spans Bitbucket, GitHub, and GitLab, you're forced to:
- Context switch between provider UIs
- Remember which repo lives where
- Check multiple places to answer "what needs me?"
- Piece together a mental model from scattered sources
Unblockd unifies this into a single view. All providers. All repos. One place.
Traditional tools treat PRs as a stream of events (comments, approvals, CI updates) and ping you for each one. This creates noise.
Unblockd treats PRs as ongoing state that you check when ready - like a dashboard, not an inbox.
- Check once/hour, not once/minute
- Passive awareness, not reactive alerts
- You decide when to engage, not your notifications
But here's the key: This doesn't mean "no notifications ever." It means notifications should be optional and smart - not the default mode of operation.
Whether you monitor 3 repos or 50, across one provider or three, Unblockd gives you:
Clarity - Smart filters show only actionable PRs
Control - Office hours, snooze, custom refresh intervals
Privacy - 100% local processing, no server dependencies
Early builds may be distributed without Apple notarization.
If macOS blocks app launch:
- Right-click
Unblockd.app→ Open - Confirm Open in the dialog
- If needed:
System Settings → Privacy & Security → Open Anyway
Terminal fallback (if you prefer CLI):
xattr -dr com.apple.quarantine /Applications/Unblockd.app
open -a "Unblockd"open -a starts the app, but the key step is removing quarantine (or approving once in Privacy & Security).
Note on Keychain Access: macOS may prompt you to allow Unblockd to access your Keychain when you first connect a provider. This is normal - click Allow to securely store your API tokens. You may see this prompt multiple times (once per provider).
- macOS 13.0+
- Xcode with Swift 6.2 (or newer)
swift testThe project uses SwiftLint via SwiftPM build tool plugin.
swift package plugin --allow-writing-to-package-directory swiftlintSources/Unblockd/
├── Core/ # Configuration, logging, extensions
├── Features/ # UI (Dashboard, Settings)
├── Services/ # Provider clients, auth, rules engine
└── Resources/ # Assets
Unblockd is designed to be lightweight and battery-friendly:
- Polling runs only during your configured active hours
- Conservative refresh intervals (default 30 min, configurable 15-120 min)
- Avatars cached in memory with bounded cache size
- Background refresh paused outside working window
This is a personal project, but thoughtful contributions are welcome:
- 🐛 Bug reports - Open an issue with reproduction steps
- 💡 Feature requests - Discuss in issues before implementing
- 🔧 Pull requests - Keep them focused and well-tested
MIT License. See LICENSE for details.
Built with:
- Swift - Apple's modern programming language
- SwiftUI - Declarative UI framework
- Love for developer productivity ❤️
Made for developers who value their focus.





