GitHub - utkarsh261/pho: TUI for Github Pull Requests

GitHub

6 min read Original article ↗

image

A TUI for GitHub pull requests.

readme-dashboard

Features

  • Dashboard - Auto-discovers repos, lists PRs across My PRs, Needs Review, Involving, All (open PRs, loaded as you scroll), and Recent tabs with a live preview pane.
  • Jump to repo/PR - Ctrl+P to fuzzy-find and jump to any PR; inside a PR, Ctrl+P jumps to any file in its diff.
  • Open a PR directly - pho pr 123 to launch straight into a PR's detail view.
  • PR detail - Browse description, diff, comments, and commits. Sidebar for files and CI checks.
  • Stacked PRs - PRs built on another open PR's branch, and GitHub's native stacks, are listed together with a rail joining them, and the preview maps the whole stack with each PR's CI and review state. In a PR, {/} step down/up the stack on the same tab and S lists it.
  • CI logs - Enter on a GitHub Actions check shows the end of its job log with error lines highlighted; n/N jumps between errors and r re-runs the job.
  • Diff navigation - Line-by-line cursor, gg/G, Ctrl+d/Ctrl+u, visual mode for selecting ranges.
  • Open in your editor - e on a diff line opens the file at that line in $VISUAL/$EDITOR. If your local checkout isn't on the PR's head commit, pho offers to check out the branch first.
  • Inline reviews - Draft inline comments on diff lines, edit, discard, and batch-submit with a review event. Just like Github web UI.
  • Comments & approvals - Post top-level comments, review comments, or approve directly.
  • PR actions - Edit title/body (E), merge (with method selection), close/reopen, and checkout the branch locally.
  • Commit view - Inspect individual commits and their diffs.
  • Search - / to search within diffs and descriptions; n/N to jump between matches.
  • Themes - Catppuccin Mocha, Tokyo Night, Gruvbox, Nord, Dracula and Rosé Pine. Press T to preview them live.
  • Works with Github Enterprise as well.

Install

With Homebrew (macOS and Linux):

brew install utkarsh261/tap/pho

Or with Go:

go install github.com/utkarsh261/pho/cmd/pho@latest

Binary lands in $(go env GOPATH)/bin/pho. To pin a version, swap @latest for a tag from the releases page, e.g. @v0.1.49.

Add it to the $PATH:

echo 'export PATH="$(go env GOPATH)/bin:$PATH"' >> ~/.zshrc

Requirements

  • Git
  • GitHub CLI (gh), logged in with gh auth login. pho reuses its token, including for GitHub Enterprise hosts.
  • Go 1.25+, only if you install with go install or build from source

Usage

pho looks at the current directory and its direct children for git repos with a GitHub remote. Start it in a directory holding your clones:

or point it at one:

pho --root ~/path/to/dir/containing/all/cloned/repositories

To open a pull request straight in its detail view:

Flags work before or after pr <number>:

Flag Description
--root <dir> Directory to scan for git repos (default .)
--theme <name> Theme for this run, overriding the config file
--config <path> Config file to use (default ~/.config/pho/config.toml)
--debug Log at debug level (also PHO_DEBUG=1)
--reset Clear the SQLite and repo discovery caches before starting
--version Print the version and exit
--changelog Print the latest release notes and exit

Configuration

pho reads $XDG_CONFIG_HOME/pho/config.toml, which defaults to ~/.config/pho/config.toml. It runs fine without one. Every key is optional; the values below are the defaults.

[repos]
pin = []                   # "owner/repo" entries to list first
exclude = []               # "owner/repo" entries to hide

[dashboard]
max_prs = 300              # open PRs the All tab loads at most
group_stacks = true        # list a stack's PRs together, top of the stack first

[palette]
max_prs = 300              # PRs the Ctrl+P jump list holds

[diff]
collapse_lines = 1000      # files with more changed lines start collapsed
collapse_line_width = 5000 # so do files with a line longer than this
max_lines = 5000           # files past this can only be opened on GitHub
max_line_width = 20000     # same, for line length
row_budget = 20000         # past this many diff rows, the largest files collapse

[ui]
theme = "pho-default"      # see Themes below
background = "theme"       # or "terminal"

[cache]
dir = "~/.cache/pho"       # where cache.db lives
max_memory_mb = 16         # in-memory cache size

[logging]
file = "~/.local/state/pho/debug.log"
level = "info"             # debug, info, warn or error

[updates]
whats_new = true           # mention a new version in the status bar after an upgrade
check = true               # look for a newer release once a day

What's new

After you upgrade, the dashboard's status bar says so for a few launches. Press W on the dashboard to read the release notes, at any time. pho --changelog prints them in the terminal.

Once a day pho also checks whether a newer release is out and, if so, says so in the dashboard's status bar. If you installed with Homebrew, press U there and confirm with Enter to run brew upgrade utkarsh261/tap/pho without leaving pho; restart pho afterwards to use the new version.

pho talks to GitHub's public API for both, without your token. Set [updates] whats_new = false or [updates] check = false to turn either off, or PHO_NO_UPDATE_CHECK=1 for both; W and --changelog still work. pho remembers the last version you saw and the last check in ~/.local/state/pho/state.json.

Themes

pho-themes

Press T anywhere to open the theme picker. Arrowing through it repaints the screen with each theme; Enter keeps one and saves it to your config, Esc puts the old one back. You can also set it in the config:

[ui]
theme = "catppuccin-mocha"  # pho-default (the default), catppuccin-mocha, tokyo-night,
                            # gruvbox-dark, nord, dracula, rose-pine
background = "theme"        # or "terminal" to keep your terminal's own background

or for one run with pho --theme nord.

Themes paint their own background so text stays readable whatever your terminal is set to. With background = "terminal" (handy for transparent terminals) contrast is only guaranteed when your terminal background matches the theme's. Colours are checked for contrast on truecolor and 256-colour terminals; on 16-colour terminals the cursor row switches to reverse video.

Logs

tail -f ~/.local/state/pho/debug.log

Development

just build      # go build -o pho ./cmd/pho
just test       # go test ./...
just test-race  # go test -race -count=1 ./...
just vet        # go vet ./...

Benchmarks

just bench-quick           # micro benchmarks, about 30s
just bench                 # everything: frames, launches, scaling, heap, soak
just bench-compare main    # this tree against main, interleaved runs
just bench-live            # `pho pr` against real GitHub, cold and warm
just profile FrameScroll   # CPU profile one benchmark in pprof

Reports land in bench-out/report.md. Frame benchmarks time each keypress to a settled frame; launch benchmarks run the real program against an in-process GitHub (internal/testutil/fakegh) at local, 40ms and 250ms round trips. Every PR gets the comparison against main as a comment; it never fails the build. Set PHO_CPUPROFILE, PHO_MEMPROFILE or PHO_TRACE to a path to profile a real session.

Why

So that i can build it exactly how i want a tool which i use on a regular basis to be.