I spend most of my working day in a terminal, and pull requests are the thing that keeps yanking me out of it. Someone asks for a review, CI goes red, a comment lands - and each time the answer is the same little ritual: alt-tab to the browser, find the tab, wait for GitHub to paint, squint at a diff, click into the Actions logs, scroll. By the time I’m back in my editor I’ve lost the thread of whatever I was doing.

perq is my attempt to stop doing that. It’s a terminal dashboard for the PRs you care about, built with Textual, with Claude Code folded in to do the reading-and-thinking parts - summarise a PR, review it, answer a question, or work out why a check is failing - streamed straight into the TUI.

uv run perq

The pitch

You open perq and you see three lists: the PRs you’ve opened, the ones waiting on your review, and the ones you’re otherwise tangled up in (assigned, mentioned, commented on). Each row tells you what you actually want to know at a glance - CI state, review decision, the diff size, how many comments, when it last moved.

Arrow-key to a PR, hit enter, and you’re in the detail view: five tabs for the overview, the conversation, code-review threads, individual CI checks, and the full diff. No page loads, no spinner, no thirty open browser tabs.

The dashboard refreshes itself every sixty seconds - silently, keeping your cursor exactly where it was - and tells you when something meaningful changes. Your CI just went green. Someone approved you. A new review got requested. You don’t go looking for those; they come to you.

Why a TUI

Because the terminal is already where I am, and a PR dashboard that lives in a browser tab has the same problem a cheat sheet in a browser tab has - the moment you have to leave what you’re doing to go look at it, you’ve paid the cost the tool was supposed to save you.

A TUI is always one keystroke away, renders instantly, and works the same over SSH on a bad train connection as it does at my desk. It doesn’t fight for focus and it doesn’t ask me to find the right tab. It’s just there when I press the key, and gone when I’m done.

Claude does the reading for you

The part I use most isn’t the dashboard - it’s the four things Claude Code can do once you’re looking at a PR:

All of this streams into a modal as it’s generated, so you’re reading the first sentence while the rest is still arriving. Crucially, it’s local and advisory - none of it is ever posted to GitHub. It’s the equivalent of a colleague leaning over and saying “this looks fine, but check the migration” - a private read, not a public comment. Press c to copy the output, escape to dismiss it.

When you do want to act, perq can write to GitHub too - a to approve, x to request changes, c to leave a comment, C to close. The line between “Claude helps me think” and “I act on GitHub” is deliberate and never blurry.

Technically

The whole thing hangs off a single GraphQL query. One round-trip to GitHub fills all three dashboard sections, and the detail view is a second query plus the raw diff. perq authenticates by shelling out to gh auth token, so if you’ve run gh auth login it just works (it falls back to $GITHUB_TOKEN).

The notifications are the bit I’m quietly pleased with. Every refresh is diffed against the previous snapshot, and only transitions raise a toast - CI failing or recovering, a review decision changing, comment counts going up, a new review request appearing. Absolute states never fire, so startup is silent and a PR simply showing up on your dashboard doesn’t nag you. If more than five things changed at once, they collapse into a single “dashboard updated” line instead of a wall of toasts. On macOS, when the terminal isn’t focused, the same events become desktop banners via osascript.

The Claude integration is a thin wrapper around the CLI. perq spawns claude -p --output-format stream-json --max-turns 1, feeds it a self-contained prompt, and parses the streaming JSON for text deltas as they come. The prompts ship everything Claude needs inline - the PR metadata, description, conversation, review threads, and the diff (truncated if it’s enormous) - and explicitly tell it not to use any tools. For diagnosis, perq fetches the Actions job logs, strips GitHub’s per-line ISO timestamps, and tails them to fit. It’s one turn, no agent loop, no tool calls: a fast, bounded, read-only ask. The streaming subprocess runs in its own process group so a cancel actually kills it and its children.

There’s a command palette too (ctrl+p): paste any GitHub PR URL or type a owner/repo#123 shorthand to jump to a PR that isn’t even on your dashboard, or fuzzy-search the ones that are.

It’s about 1,800 lines of Python - Textual for the UI, httpx for GitHub, and the gh and claude CLIs for auth and intelligence. Python 3.12+, managed with uv.

What it isn’t

perq isn’t trying to be the GitHub web UI in a terminal. There’s no merging, no branch management, no project boards, no notifications inbox. It’s the narrow slice of the PR experience I touch dozens of times a day - what’s waiting on me, what changed, and what does this diff actually do - made fast and keyboard-native, with an LLM doing the tedious reading.

If you want the full surface area of GitHub, it’s a browser tab away. If you want your pull requests to stop pulling you out of the terminal, this is for you.

Try it

It’s on github.com/tuckerwales/perq. You’ll need Python 3.12+, uv, the gh CLI logged in, and the claude CLI on your PATH for the summaries and reviews.

uv run perq

Then press s on your gnarliest open PR and see what Claude makes of it.