theolundqvist/pr-cockpit

Keyboard-first GitHub pull request client for macOS and Linux, with a review queue, local cache, and CLI for coding agents.

43

stars

196

commits

TypeScript

primary language

Sep 5, 2026

updated

prcockpit.com/
ai-agents
cli
code-review
developer-tools
electron
github
keyboard-shortcuts
macos
productivity
pull-requests
sqlite
svelte

README

PR Cockpit

GitHub pull requests at local speed.

PR Cockpit is a keyboard-first macOS app that keeps pull requests, diffs, threads, checks, and images warm on your Mac. Reads feel immediate, while comments, reviews, edits, and merges sync through your existing gh login. GitHub remains the source of truth.

Website · Install · CLI · Self-host relay · Shortcuts

GitHub PRs at local speed

The local server serves the queue and open pull request from SQLite instead of rebuilding every screen from GitHub. Webhook markers trigger targeted refreshes, WebSocket invalidations update the UI, and a poller repairs missed events.

Warm-cache opens of the large private pull request scape-app/scape#8132:

Productp50p95p99
PR Cockpit0.082 s0.112 s0.121 s
Cursor Origin1.738 s3.702 s5.606 s
GitHub3.381 s4.880 s5.678 s

A separate 12-run comparison of the common interactions, each a cold first open:

InteractionPR Cockpit p50GitHub p50Faster
Open a PR0.020 s1.421 s71.8×
Open a diff0.041 s1.487 s36.2×
Search PRs0.049 s0.839 s17.1×

At p99, PR Cockpit painted the same pull request 47× faster than GitHub. Methodology and reproduction.

Search from anywhere

Press ⌥⌘K from any app, type, enter. The full pull request opens from the local cache.

Global pull request search opening a cached pull request

One queue. Three lanes.

Ready to merge, your move, and waiting are separate lanes, already sorted by what needs attention. Stacked pull requests stay together. Checks, conflicts, unresolved threads, and review state are available without tab-hopping.

PR Cockpit review queue with ready, your move, and waiting lanes

Hide tests. See the change.

Press x to fold test files out of the diff. In graphql/graphql-js#4692, that leaves the one-line fix on screen.

Pressing x folds the five regression-test diffs, leaving the one-line source change open

One key from review to change

The review stays in one context:

  • p opens the pull request in the configured coding agent with the current review context.
  • e edits the open file and commits the patch back to the pull request.
  • Revert hunk removes one focused change instead of rewriting the file.
  • h walks file history without leaving the review.
AgentEdit
Agent prompt opened from PR CockpitEditing a pull request file inside PR Cockpit
Revert hunkHistory
Revert hunk menu inside a pull request diffFile history inside PR Cockpit

Agents: listen, don't poll.

The installer adds the open-source pr-cockpit CLI. It reads the same local cache as the app, returns compact agent-shaped output, and revalidates only when that cache is stale.

pr-cockpit owner/repo#123                    # state, checks, unresolved threads
pr-cockpit owner/repo#123 --diff             # cached diff
pr-cockpit owner/repo#123 --file src/app.ts  # full file at the PR head
pr-cockpit owner/repo#123 --jobs             # cached queued, running, and completed jobs
pr-cockpit owner/repo#123 --logs [check]     # cached failed and cancelled logs
pr-cockpit resolve owner/repo#123 HANDLE     # resolve a review thread
pr-cockpit update                            # fast-forward and rebuild

Waiting on CI, review, or a new comment? Block on the local fingerprint instead of polling GitHub:

pr-cockpit listen owner/repo#123

listen blocks until substantive cached state changes — a push, check result, review, or comment — then prints only what changed. --ci-only and --comments-only narrow the wake signal.

Under the hood

GitHub webhooks reach the local PR Cockpit server through a relay; the server keeps SQLite and the UI warm and serves agents over CLI and API

  • GitHub is authoritative. The local database is a warm read model, not a fork of pull-request state.
  • The relay carries markers, not pull-request payloads. It also carries compact Actions run and job state, including runner assignment, but never full pull-request payloads or job logs.
  • Writes stay authenticated. Comments, reviews, edits, thread resolution, and merges use the existing GitHub CLI login.
  • Humans and agents share one cache. The app uses WebSocket invalidations; the CLI and API expose the same refreshed state.
  • Self-hosting is one Worker. Deploy the relay to Cloudflare, create a GitHub App, and connect its URL—no separate database, server, or tunnel. Complete self-hosting guide.

Install

curl -fsSL https://raw.githubusercontent.com/theolundqvist/pr-cockpit/main/scripts/bootstrap | bash

The installer checks macOS prerequisites, asks before installing anything, shows each stage, and opens the four-step setup. Only after installation succeeds does it optionally offer to teach local coding assistants to use the cache-aware CLI. Run pr-cockpit update to upgrade. A legacy private installation is replaced while local pull-request data and settings are preserved.

Linux server (private remote access)

From a clone on the Linux host, install the loopback-only systemd user service:

./scripts/install-linux

Edit ~/.config/pr-cockpit/server.env, then run systemctl --user restart pr-cockpit.service. To update the checkout and rebuild the UI without replacing that file, run git pull && ./scripts/install-linux again.

For SSH access, leave TCP port 4820 closed and tunnel it instead:

ssh -N -L 4820:127.0.0.1:4820 user@host

Then open http://127.0.0.1:4820.

For phone access, keep the loopback binding and put a mesh VPN in front of it. A VPN whose agent runs on the same host reaches 127.0.0.1:4820 directly, so nothing has to listen on a public address. With Twingate, install a Connector on the host and define a Resource with address 127.0.0.1, an alias, and TCP restricted to port 4820; Tailscale Serve and Cloudflare Access work the same way. Add each exact browser origin to the comma-separated COCKPIT_ALLOWED_ORIGINS value in server.env (for example, COCKPIT_ALLOWED_ORIGINS="http://cockpit.example.internal:4820") and restart the service, because unsafe requests and the event socket reject untrusted origins. Never bind PR Cockpit publicly or open port 4820.

Start in four steps

  1. Connect your existing GitHub CLI login.
  2. Choose repositories.
  3. Enable live updates.
  4. Open the review queue.

Run Settings → Run setup again whenever you want to change repositories or live updates.

Shortcuts

KeyAction
⌥⌘KSearch pull requests from any app
j / kMove
enter / escOpen / back
dConversation / Files
c / rComment / reply
pOpen in the configured agent
eEdit the open file
xHide / show test files
hFile history
mMerge
?Full cheatsheet
Configuration

Settings live in the app. Optional shell overrides live in ~/.config/pr-cockpit/config.

VariablePurpose
COCKPIT_REPOSComma-separated owner/repo list
COCKPIT_PORTLocal HTTP port; defaults to 4820
COCKPIT_DEFAULT_REPORepository assumed when a PR number is passed alone
COCKPIT_REPO_ROOTSPaths containing local checkouts
COCKPIT_RELAY_URLSelf-hosted webhook relay

Contributions welcome

Functionality, themes, visual polish, and fixes for rough UI edges are all welcome.

New functionality must default off. Styling must be opt-in unless it is minor polish that preserves the default appearance.

Every pull request must attach before-and-after screenshots showing its effect in the app.

Contributors

theolundqvist

170 commits

Macludde

18 commits

moritzcodes

8 commits

theolundqvist/pr-cockpit

Keyboard-first GitHub pull request client for macOS and Linux, with a review queue, local cache, and CLI for coding agents.

43

stars

196

commits

TypeScript

primary language

Sep 5, 2026

updated

prcockpit.com/
ai-agents
cli
code-review
developer-tools
electron
github
keyboard-shortcuts
macos
productivity
pull-requests
sqlite
svelte

README

PR Cockpit

GitHub pull requests at local speed.

PR Cockpit is a keyboard-first macOS app that keeps pull requests, diffs, threads, checks, and images warm on your Mac. Reads feel immediate, while comments, reviews, edits, and merges sync through your existing gh login. GitHub remains the source of truth.

Website · Install · CLI · Self-host relay · Shortcuts

GitHub PRs at local speed

The local server serves the queue and open pull request from SQLite instead of rebuilding every screen from GitHub. Webhook markers trigger targeted refreshes, WebSocket invalidations update the UI, and a poller repairs missed events.

Warm-cache opens of the large private pull request scape-app/scape#8132:

Productp50p95p99
PR Cockpit0.082 s0.112 s0.121 s
Cursor Origin1.738 s3.702 s5.606 s
GitHub3.381 s4.880 s5.678 s

A separate 12-run comparison of the common interactions, each a cold first open:

InteractionPR Cockpit p50GitHub p50Faster
Open a PR0.020 s1.421 s71.8×
Open a diff0.041 s1.487 s36.2×
Search PRs0.049 s0.839 s17.1×

At p99, PR Cockpit painted the same pull request 47× faster than GitHub. Methodology and reproduction.

Search from anywhere

Press ⌥⌘K from any app, type, enter. The full pull request opens from the local cache.

Global pull request search opening a cached pull request

One queue. Three lanes.

Ready to merge, your move, and waiting are separate lanes, already sorted by what needs attention. Stacked pull requests stay together. Checks, conflicts, unresolved threads, and review state are available without tab-hopping.

PR Cockpit review queue with ready, your move, and waiting lanes

Hide tests. See the change.

Press x to fold test files out of the diff. In graphql/graphql-js#4692, that leaves the one-line fix on screen.

Pressing x folds the five regression-test diffs, leaving the one-line source change open

One key from review to change

The review stays in one context:

  • p opens the pull request in the configured coding agent with the current review context.
  • e edits the open file and commits the patch back to the pull request.
  • Revert hunk removes one focused change instead of rewriting the file.
  • h walks file history without leaving the review.
AgentEdit
Agent prompt opened from PR CockpitEditing a pull request file inside PR Cockpit
Revert hunkHistory
Revert hunk menu inside a pull request diffFile history inside PR Cockpit

Agents: listen, don't poll.

The installer adds the open-source pr-cockpit CLI. It reads the same local cache as the app, returns compact agent-shaped output, and revalidates only when that cache is stale.

pr-cockpit owner/repo#123                    # state, checks, unresolved threads
pr-cockpit owner/repo#123 --diff             # cached diff
pr-cockpit owner/repo#123 --file src/app.ts  # full file at the PR head
pr-cockpit owner/repo#123 --jobs             # cached queued, running, and completed jobs
pr-cockpit owner/repo#123 --logs [check]     # cached failed and cancelled logs
pr-cockpit resolve owner/repo#123 HANDLE     # resolve a review thread
pr-cockpit update                            # fast-forward and rebuild

Waiting on CI, review, or a new comment? Block on the local fingerprint instead of polling GitHub:

pr-cockpit listen owner/repo#123

listen blocks until substantive cached state changes — a push, check result, review, or comment — then prints only what changed. --ci-only and --comments-only narrow the wake signal.

Under the hood

GitHub webhooks reach the local PR Cockpit server through a relay; the server keeps SQLite and the UI warm and serves agents over CLI and API

  • GitHub is authoritative. The local database is a warm read model, not a fork of pull-request state.
  • The relay carries markers, not pull-request payloads. It also carries compact Actions run and job state, including runner assignment, but never full pull-request payloads or job logs.
  • Writes stay authenticated. Comments, reviews, edits, thread resolution, and merges use the existing GitHub CLI login.
  • Humans and agents share one cache. The app uses WebSocket invalidations; the CLI and API expose the same refreshed state.
  • Self-hosting is one Worker. Deploy the relay to Cloudflare, create a GitHub App, and connect its URL—no separate database, server, or tunnel. Complete self-hosting guide.

Install

curl -fsSL https://raw.githubusercontent.com/theolundqvist/pr-cockpit/main/scripts/bootstrap | bash

The installer checks macOS prerequisites, asks before installing anything, shows each stage, and opens the four-step setup. Only after installation succeeds does it optionally offer to teach local coding assistants to use the cache-aware CLI. Run pr-cockpit update to upgrade. A legacy private installation is replaced while local pull-request data and settings are preserved.

Linux server (private remote access)

From a clone on the Linux host, install the loopback-only systemd user service:

./scripts/install-linux

Edit ~/.config/pr-cockpit/server.env, then run systemctl --user restart pr-cockpit.service. To update the checkout and rebuild the UI without replacing that file, run git pull && ./scripts/install-linux again.

For SSH access, leave TCP port 4820 closed and tunnel it instead:

ssh -N -L 4820:127.0.0.1:4820 user@host

Then open http://127.0.0.1:4820.

For phone access, keep the loopback binding and put a mesh VPN in front of it. A VPN whose agent runs on the same host reaches 127.0.0.1:4820 directly, so nothing has to listen on a public address. With Twingate, install a Connector on the host and define a Resource with address 127.0.0.1, an alias, and TCP restricted to port 4820; Tailscale Serve and Cloudflare Access work the same way. Add each exact browser origin to the comma-separated COCKPIT_ALLOWED_ORIGINS value in server.env (for example, COCKPIT_ALLOWED_ORIGINS="http://cockpit.example.internal:4820") and restart the service, because unsafe requests and the event socket reject untrusted origins. Never bind PR Cockpit publicly or open port 4820.

Start in four steps

  1. Connect your existing GitHub CLI login.
  2. Choose repositories.
  3. Enable live updates.
  4. Open the review queue.

Run Settings → Run setup again whenever you want to change repositories or live updates.

Shortcuts

KeyAction
⌥⌘KSearch pull requests from any app
j / kMove
enter / escOpen / back
dConversation / Files
c / rComment / reply
pOpen in the configured agent
eEdit the open file
xHide / show test files
hFile history
mMerge
?Full cheatsheet
Configuration

Settings live in the app. Optional shell overrides live in ~/.config/pr-cockpit/config.

VariablePurpose
COCKPIT_REPOSComma-separated owner/repo list
COCKPIT_PORTLocal HTTP port; defaults to 4820
COCKPIT_DEFAULT_REPORepository assumed when a PR number is passed alone
COCKPIT_REPO_ROOTSPaths containing local checkouts
COCKPIT_RELAY_URLSelf-hosted webhook relay

Contributions welcome

Functionality, themes, visual polish, and fixes for rough UI edges are all welcome.

New functionality must default off. Styling must be opt-in unless it is minor polish that preserves the default appearance.

Every pull request must attach before-and-after screenshots showing its effect in the app.

Contributors

theolundqvist

170 commits

Macludde

18 commits

moritzcodes

8 commits

Languages

TypeScript

45.5%

Svelte

32.6%

JavaScript

17.6%

Shell

3.5%