prlens
One queue. All your PRs.
prlens is a CLI-first PR review dashboard for developers who work across GitHub and Bitbucket. It aggregates every pull request waiting for your attention into a single interactive view — so nothing slips through and you can stop bouncing between tabs.
prlens
╭──────┬──────────────────────────────────────────┬───────────┬──────────────────┬──────────┬────┬─────╮
│ # │ Title │ Author │ Repo │ Status │ CI │ Age │
├──────┼──────────────────────────────────────────┼───────────┼──────────────────┼──────────┼────┼─────┤
│ 843 │ feat: add retry logic to webhook handler │ alice │ acme/backend │ pending │ ✓ │ 2h │
│ 1204 │ fix: null pointer in payment service │ bob │ acme/payments │ pending │ ✗ │ 5h │
│ 391 │ refactor: extract config loader │ carol │ acme/infra │ approved │ ✓ │ 1d │
│ 77 │ ✏ WIP: new onboarding flow (draft) │ dave │ acme/web │ pending │ ⟳ │ 3d │
╰──────┴──────────────────────────────────────────┴───────────┴──────────────────┴──────────┴────┴─────╯
Features
- Multi-provider — GitHub and Bitbucket Cloud + Data Center in one view
- Zero new auth — reuses your existing
ghandbktCLI credentials - Interactive TUI — fuzzy search, detail overlay, Jira shortcuts, profile switching
- Non-interactive mode — pipe-friendly table output for scripts and aliases
- Resilient — one broken provider never hides results from the others
- Fast — concurrent API calls with a 60-second cache; sub-frame TUI latency
Installation
# Build from source (requires Rust 1.70+)
Quick Start
# Launch the interactive TUI
# Print a plain table (non-TTY / scripting)
# Filter by repo, org, or review status
# Open a PR in your browser
Interactive TUI
Run prlens in any terminal to open the TUI.
| Key | Action |
|---|---|
j / k or ↑ / ↓ |
Move up / down |
Enter |
Open selected PR in browser |
/ |
Open search bar (filter by title, author, or repo) |
Space |
Toggle detail overlay |
d |
Toggle draft PR visibility |
Tab |
Cycle between named filter profiles |
J |
Open linked Jira ticket (requires jira.base_url in config) |
q / Esc |
Quit |
The detail overlay shows the full PR picture: title, branch, author, labels, comment count, additions/deletions, review status, CI status, linked Jira key, and age.
Configuration
Config lives at ~/.config/prlens/config.toml. prlens works out of the box with sensible defaults (GitHub enabled, Bitbucket disabled) — no config file needed to get started.
[]
= true
# Optional: limit to specific repos or exclude noisy ones
= ["acme/backend", "acme/frontend"]
= ["acme/archived-service"]
[]
= true
= "my-workspace"
= "user@example.com"
# For Bitbucket Data Center (self-hosted) — omit for Cloud
= "https://bitbucket.example.com"
# Token falls back to BITBUCKET_TOKEN env var or `bkt` CLI credentials
[]
= "relative" # "relative" (default) or "iso8601"
[]
= "https://your-org.atlassian.net" # enables the J key shortcut
# Named filter profiles — switch between them with Tab in the TUI
[[]]
= "work"
= "acme"
= "pending"
[[]]
= "oss"
= "my-oss-project"
Review Status
| Status | Meaning |
|---|---|
pending |
Waiting for your initial review |
approved |
You approved; may have new commits |
changes-requested |
You left change requests |
mixed |
Multiple reviewers with conflicting states |
Authentication
prlens delegates token management entirely to the CLIs you already use:
- GitHub — run
gh auth loginonce; prlens callsgh auth tokenunder the hood - Bitbucket Cloud — run
bkt loginonce, or setBITBUCKET_TOKEN - Bitbucket Data Center — set
base_urlin config and provide a personal access token viaBITBUCKET_TOKENor the config file
No OAuth flows, no separate credential store.
Provider Architecture
Providers implement a common trait (name, check_auth, list_prs, get_pr_details). The registry fans out calls concurrently and merges results. Adding a new provider (GitLab, Azure DevOps, Gitea…) doesn't touch display or CLI code.
Stack
| Concern | Crate |
|---|---|
| CLI parsing | clap |
| TUI | ratatui + crossterm |
| HTTP | reqwest + rustls |
| GitHub API | octocrab |
| Config | toml + serde |
| Async runtime | tokio |
| Error handling | anyhow + thiserror |
Single static binary. No runtime, no dependencies to install.
Development
# Run tests
# Run with verbose tracing
RUST_LOG=debug
# Check without building
License
MIT