Sep 15, 2026

I took the GitHub Review Requests Raycast extension much further

I extended an existing Raycast extension into a focused GitHub review queue. It brings review requests, team ownership, watched repositories, replies, ageing, activity tracking, notifications, and saved filters into one hotkey, so developers can see what needs their attention without digging through GitHub.

Vitor Águila
by Vitor Águila
I took the GitHub Review Requests Raycast extension much further

The bottleneck in software has moved. Writing code got faster. Reviewing it didn't. A model can produce a plausible four-hundred-line pull request in the time it takes to describe one, and somebody still has to read it line by line, hold the system in their head, and decide whether it's right. That used to be typing. Now it's attention.

Then put that in the environment most of us actually work in. Microservices. A repo per service, or per team, or both. A change to one service needs eyes from the two teams downstream of it. Your review queue isn't one repository's worth of work, it's a queue assembled from a dozen repositories you don't watch, by people who assume GitHub told you. GitHub did tell you. It tells you about everything, which is the same as telling you about nothing. My notification inbox had four thousand unread. The signal was in there somewhere.

I'd already written about the reframe that fixed this for me: the useful question isn't what is open, it's whose turn is it. Your review was requested. Your team's was, and nobody picked it up. It's your pull request and someone asked you something. You joined a thread and someone replied after you. So I built it. Raycast is where I already live, it's the one tool I'd fight to keep, the thing I hit before I've finished deciding what I want, and a review queue belongs behind a hotkey, not behind a browser tab I have to remember to open. Then someone from the Raycast team looked at what I'd built and said: there's already an extension for this. Go contribute to that one.

he right answer, and not the one I wanted

My honest first reaction was deflation. You build a thing, you want the thing to be yours.

The second reaction was that they were obviously right, for a reason that has nothing to do with etiquette. There were already people using resessh/github-review-requests. They knew its icon. They had its hotkey in muscle memory, its preferences filled in, its search command wired into how they work. Shipping a second extension that does the same job with a different name doesn't help any of them, it just makes them choose, and most people resolve that choice by doing nothing.

Contributing means they wake up to more capability in the thing they already had.

It also meant giving up control of the design, which is the part nobody mentions. You inherit someone else's decisions. My job stopped being "build what I want" and became "add what I need without breaking what anyone else depends on."

That constraint turned out to improve the work.

What went in

The original extension answered what is open, and what's its review status. I extended it toward the more useful question, whose turn is it, while keeping the existing command, icon, preferences, and menu intact. The main additions were:

  • A pull request list organised around responsibility. The category picker covers Needs my review, My team's review, My open PRs, Awaiting my reply, and Watching, alongside any saved filters. Team membership is detected from GitHub, watched repositories can surface work that nobody explicitly assigned to you, and ignored authors keep bots from filling the queue. Each row shows the repository, activity, ageing, comment counts, unresolved threads, and whether anything changed since the last time you looked.
  • A complete review view inside Raycast. Opening a pull request shows its description, activity timeline, labels, reviewers, status, conversation state, and diff size in one detail pane. Review threads can be opened, replied to, resolved, or reopened without switching to a browser. Conversation comments and review bodies count alongside inline threads, and every deep link lands on the specific comment that needs attention.
  • Authentication that fits the tools people already use. The extension has no login screen and stores no token. It checks the GitHub CLI and borrows the credential that gh already keeps in the system keychain. Every command checks that the CLI, token, API access, and required scopes are ready. If something is missing, the extension explains what needs fixing and shows the command to run instead of displaying a mysteriously empty list. GitHub Enterprise is supported through a configurable host preference.
  • Ageing that describes the real debt. Every pull request has separate values for how long it has been open, how long it has been untouched, and how long someone has been waiting for your reply. A recent comment does not erase a three-week-old question. The list uses fresh, ageing, stale, and stalled bands, while category summaries show counts and median idle time. Opening a pull request marks its current activity as seen, so later activity gets a NEW tag.
  • An Activity Inbox that keeps the signal. The background watcher checks GitHub on a schedule and records new review requests, comments, and replies in a rolling 72-hour inbox capped at 500 entries. The detail pane loads the actual comment, and each item links directly to the relevant place in GitHub. The first run establishes a baseline, so installing the extension does not create a wall of notifications about old activity.
  • A menu bar count for work waiting on you. The menu bar keeps a live count visible even when Raycast is closed. It can show the category that matters most to you, limit how many pull requests appear inline, and move the rest into a submenu so the menu stays useful when the queue grows.
  • Notifications that stay under your control. Desktop banners are off by default and separate from the inbox. When enabled, they support per-event switches, quiet hours that can cross midnight, sound control, a test banner, baseline reset, and a per-check cap that folds extra activity into a summary. Banners are grouped by pull request so a busy thread does not create a stack of duplicate interruptions.
  • Saved filters for the cases the built-ins cannot cover. Filters can be assembled from fields such as role, subject, state, organization, and repository, or entered as a raw GitHub search string. The extension previews the query before sending it and adds the saved filter to the same category picker as the built-in views.

Twenty-two commits. Eighty files. Around ten and a half thousand lines added.

Making the extension dependable

Eight rounds of review from the Raycast team, with nine automated review passes alongside them, focused the work on the parts of the extension users only notice when they fail: posting comments safely, keeping activity when checks overlap, and proving that the fixes work against real failure scenarios.

Safe comment posting. The GitHub GraphQL client retries failed requests, which is useful for reads and dangerous for writes. If GitHub accepts a comment but the response is lost, retrying can post the same comment twice. The extension now treats that situation as unconfirmed and asks the user to check the pull request before trying again. It also distinguishes the different responses GitHub can return: a comment with an adjacent error can still mean success, while a missing mutation result, a null response body, or an error list containing null must be treated as unconfirmed. The result is a composer that does not turn an ambiguous network failure into a duplicate comment.

Activity that survives overlapping checks. The scheduled watcher and a manually started check are separate processes that share storage. The original inbox stored everything in one array under one key, so two checks could read the same state, write different results, and silently erase one another's activity. The extension now stores entries individually, protects recent entries from being removed by the size cap, and includes the date in change tracker keys. A check can remove its own dated key without colliding with a different check that is writing new activity.

The review also shaped the regression suite. There are now 128 tests covering the fake storage layer, scripted HTTP responses, and a temporary fake CLI binary. The scenarios include the exact ordering that makes overlapping checks race, as well as every ambiguous response the comment composer can receive. Each new test is checked against the failure it is meant to catch, so a passing test represents a working guarantee rather than just a green status.

What this contribution adds

The contribution turns a scattered set of GitHub signals into a queue built around responsibility. It brings together review requests, team ownership, watched repositories, replies, ageing, and saved searches, then gives each item enough context to act on it immediately. Building on an extension that already had users kept the familiar command, icon, preferences, and workflow in place while adding the features needed for a multi-repository team.

The result is a review queue people can trust with the awkward cases too: authentication failures, partial results, interrupted responses, and multiple processes touching the same data. The work now lives in an extension with real users, review standards, and a regression suite, so future improvements can build on the same foundation.


The pull request is open and in review. Built with TypeScript, the GitHub GraphQL API, and the Raycast API. Credit to resessh for the extension I got to build on, and to the Raycast team for the redirect I didn't want and needed.

Continue Reading