How a Dashboard Arms Race Put Me on the App Store
It started with a shell script on Slack. Four days and 31 commits later, I had a native macOS app built entirely with Claude Code in a language I'd never touched.
A colleague shared a shell script on Slack. A few weeks later, I had a native macOS app on the App Store. I’d never written a line of Swift in my life.
The review pile-up
Since we started working with Claude Code at Mergify in early February, our output jumped. Commit volume on the main repo roughly doubled. PRs were piling up faster than anyone could get through them.
AI helps you write code faster than it helps you review it, because review still requires reading and understanding someone else’s intent. So everyone was shipping more, but reviews couldn’t keep up. I’d already been thinking about review workflows, including specific GitHub search filters to organize my review day. But bookmarking search URLs and switching between browser tabs stopped cutting it when you’re looking at 15 open reviews before lunch.
We needed better tooling.
Monday morning: a shell script
It started on a Monday. A colleague dropped a gh CLI alias in our #random Slack channel. It used the GitHub GraphQL API to list PRs waiting for his review, filtered out the ones he’d already approved, and printed clickable links in the terminal. Simple and useful, done in 20 minutes with Claude Code.
That sparked a PR on mergify-cli to add something similar but stack-aware, grouping PRs by their dependency chains.
That could have been the end of it.
Tuesday: “SKY IS THE LIMIT”
It wasn’t. By Tuesday afternoon, the colleague who’d been skeptical about gh wrappers had taken the original script, fed it to Claude, and built his own version. Then he told Claude to add an --html flag that generates a full dashboard and runs on a cron every five minutes.
He published a gist with his prompt/spec for generating PR dashboards with Claude. At that point it felt like a game.
Wednesday: the gist that changed my week
Another colleague took that gist, gave it to Claude, and came back with an even more polished web dashboard. Screenshots flew around Slack. Everyone loved it, everyone wanted one.
I looked at all these dashboards running on localhost, served by Python scripts or Node servers, refreshed by cron jobs, and I thought: I don’t want this. They were great, but I use my PR review tool every day, all day. I open it 30 times a day. I want it in my menu bar. I want native notifications. I want widgets on my desktop. I don’t want to remember which port my dashboard runs on.
I’d never touched Swift or SwiftUI. My background is web development.
Wednesday evening: 3.5 hours
At that point it had become a personal challenge. I sat down with Claude Code, the gist from Slack, and zero knowledge of Apple’s dev tools. About 3.5 hours later I had a working macOS app with:
- Custom views using any GitHub search query
- PR stack detection (stacked PRs displayed as expandable chains)
- CI status for every PR
- Grouped sections: work in progress, awaiting team review, awaiting my review
Eight commits in 3.5 hours. Not a prototype. A working app that I started using the next morning.
macOS system design is constrained enough that Claude couldn’t take weird liberties. There’s a right way to build a menu bar app, a right way to store tokens in Keychain, a right way to structure a WidgetKit extension. The constraints of Apple’s frameworks kept the AI output clean. I asked for Keychain token storage and got working code using the Security framework correctly on the first attempt. Far fewer hallucinated APIs than I expected.
Thursday: the feature avalanche
I kept going. Launch at login, VS Code and iTerm integration, desktop widgets in three sizes, notifications per view, drag-and-drop reordering, a PR detail panel with full activity timeline. I added tests covering the GraphQL client, view model logic, and widget timeline rendering. I got the app sandbox-ready for App Store distribution.
After one more evening: 31 commits, over 10,000 lines of Swift across 54 files. A real app, not a hack.
PullRequestPilot/
App/ # Entry point, dependency injection
Domain/Models/ # PullRequest, CheckRun, TimelineEvent
Features/
Dashboard/ # Main view model
PRDetail/ # PR activity timeline, check runs
ReviewQueue/ # PR rows, state icons, queue view
Settings/ # Token management, preferences
Infrastructure/
GitHub/ # GraphQL client, DTOs
Keychain/ # Secure token storage
LocalRepository/ # Git directory scanning
Persistence/ # Views and settings storage
PullRequestPilotWidget/ # WidgetKit extension
PullRequestPilotTests/
Can I read the code Claude wrote? Mostly, yes. SwiftUI is declarative enough that even without Swift experience, the structure is readable. When something breaks, I describe the problem to Claude and we fix it together. I don’t pretend I could maintain this app without AI assistance. But I couldn’t have written it at all six months ago, and now it exists, it works, and I use it every day.
The App Store was harder than the app
I decided to publish it. Bought the Apple Developer license, set up certificates, configured App Store Connect. The implementation had taken a few evenings. Getting through Apple’s review process took weeks.
The feedback comes one issue at a time. You fix it, resubmit, wait a few days, get the next issue. A missing Window menu item. A metadata correction. All legal and functional compliance, nothing about code quality. Apple never flagged the generated code itself. Four builds, four submissions, each round a multi-day wait for what amounts to a one-line fix.
There was something almost funny about it: I built an entire macOS app from scratch in a language I didn’t know, in a few evenings, and the bottleneck was filling out forms and waiting for humans to check a menu bar.
Pull Request Pilot is now live on the App Store. Free, no tracking, no data collection. Menu bar app, desktop widgets, notifications, IDE integration. Everything I wished the browser dashboards could do.
The cost of ambition
I’m a developer who built something I couldn’t have built before. The app exists because I had opinions about what a good review tool should feel like, and Claude turned those opinions into 10,000 lines of working Swift.
We all knew the review load was a problem. What nobody planned was the escalation from a 20-line shell alias to a working native app in four days, and an App Store listing a few weeks later. When building something takes an evening instead of a quarter, you don’t settle for “good enough.” You build what you actually want.