One page for every PR you have in flight — joining GitHub, the review channel, the tickets they close, and the local Claude Code sessions that wrote them. Then it works out the parallel order they have to land in.
/plugin marketplace add Abhay-Sastha-S/pr-control
claude --resume.Every one of those answers already exists — just in four tools that don't join to each other. This does the join, and draws the order out of it.
Every PR in a column for its real state — first review, changes requested, approved-and-waiting-on-a-human, merged to dev — instead of one green "Open".
Scrub the last weeks and watch each PR open, collect its review ask, and land — so you can see where the time actually went.
The dependency tree. Independent chains sit in separate tracks that run in parallel; within a track, PRs in the same wave merge at once. Tick one and the wave it unlocks lights up.
Reads the whole graph and answers in plain words — what can I merge now, the critical path, who's waiting on me. It jumps the tree to a named PR and drafts a review ping. It never sends Slack or merges — that stays your call.
| Source | Meaning |
|---|---|
| Channel-stated chains | Someone said so in the review channel. Highest authority, hand-maintained in config because no API exposes it. |
| Branch stacks | b's base branch is a's head. Structural, so it's inferred. |
| Shared open tickets | Two open PRs closing the same ticket ship together. |
| Same-repo ordering | Older open PRs in a repo where you have one merge first, or you rebase. |
Ties break on a configurable service rank — shared libraries before services, services before user-facing apps — and the result is laid out as parallel tracks with the fan-out drawn as branching wires. Other people's PRs are pulled in only when they share an edge with one of yours, so the page stays about your work while still showing who you're waiting on.
The panel on the merge-order view reads the built graph — every dependency, who authored what, what's blocked on whom — and answers from your own data. Ask it what can I merge now and it names the set that's unblocked and can go in parallel; ask what's blocking web#99 and it walks the edges. Naming a PR jumps the tree to it and pulses it; mark it merged re-flows the graph so the wave it unlocks lights up.
It runs entirely client-side over the data already in the page, so there's no backend and no key to leak. And in keeping with the rule below, it drafts and deep-links — it never sends Slack or merges anything.
Your org, GitHub login, Slack workspace and channel, teammates, Linear workspace, and dependency chains all live in one config file. The release check fails the build if a config file, a Slack export, or a built page is ever staged — so the repo can't start leaking by accident.
cp config.example.json ~/.claude/pr-control/config.json $EDITOR ~/.claude/pr-control/config.json
The page template holds no organisation strings either — it labels itself at runtime from a meta block the build injects.
gh CLI you're already signed in to — PR metadata only.~/.claude/projects, read-only — your local Claude Code transcripts, scanned for PR URLs. Content never leaves your machine; only the session id, directory, and existing summary line are used.Everything runs locally. The only thing that goes anywhere is the finished page, and only when you publish it.
gh pr list ─────────────► prs.jsonl ──┐ slack search ──► slack_mentions.json ─┤ linear issues ─► linear_issues.json ──┼──► merge.py ──► prdata.json extract_sessions.py ──► sessions.json ┤ │ gh pr list (bodies) ──► tickets.jsonl ┘ ▼ build_page.py ──► pr-control.html │ scripts/smoke-page.mjs ──┴──► publish
That last step earns its place. The page is one large inline script, and a syntax check only proves it parses — a const used before its declaration parses perfectly and then renders a blank page. The smoke test executes the built page against a DOM shim and fails on load-time errors. It caught exactly that bug while this was being packaged.
/plugin marketplace add Abhay-Sastha-S/pr-control
/plugin install pr-control
/pr-control # rebuild the tracker from live data and republish
Requires the gh CLI signed in, and — for the Slack and Linear columns — those MCP servers connected in Claude. GitHub and local-session data refresh even without them.
Claude, Claude Code, and Anthropic are trademarks of Anthropic; GitHub, Slack, and Linear are trademarks of their respective owners. This project is unofficial and not affiliated with, endorsed by, or supported by any of them.