# 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 `gh` and `bkt` CLI 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
```bash
# Build from source (requires Rust 1.70+)
cargo build --release
cp target/release/prlens ~/.local/bin/
```
## Quick Start
```bash
# Launch the interactive TUI
prlens
# Print a plain table (non-TTY / scripting)
prlens list
# Filter by repo, org, or review status
prlens list --repo backend-api
prlens list --org acme --status pending
# Open a PR in your browser
prlens open 843
```
## Interactive TUI
Run `prlens` in any terminal to open the TUI.
| `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.
```toml
[github]
enabled = true
# Optional: limit to specific repos or exclude noisy ones
watch_repos = ["acme/backend", "acme/frontend"]
exclude_repos = ["acme/archived-service"]
[bitbucket]
enabled = true
workspace = "my-workspace"
username = "user@example.com"
# For Bitbucket Data Center (self-hosted) — omit for Cloud
base_url = "https://bitbucket.example.com"
# Token falls back to BITBUCKET_TOKEN env var or `bkt` CLI credentials
[display]
date_format = "relative" # "relative" (default) or "iso8601"
[jira]
base_url = "https://your-org.atlassian.net" # enables the J key shortcut
# Named filter profiles — switch between them with Tab in the TUI
[[profiles]]
name = "work"
org = "acme"
status = "pending"
[[profiles]]
name = "oss"
repo = "my-oss-project"
```
## Review Status
| `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 login` once; prlens calls `gh auth token` under the hood
- **Bitbucket Cloud** — run `bkt login` once, or set `BITBUCKET_TOKEN`
- **Bitbucket Data Center** — set `base_url` in config and provide a personal access token via `BITBUCKET_TOKEN` or 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
| 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
```bash
# Run tests
cargo test
# Run with verbose tracing
RUST_LOG=debug cargo run
# Check without building
cargo check
```
## License
MIT