Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PR Stack Skill

Stacked pull requests your coding agent can actually drive — without hanging, and without silently breaking the stack.

A Claude Code plugin for GitHub's native stacked pull requests.

/plugin marketplace add XingLiu0923/pr-stack-skill
/plugin install pr-stack@xing-plugins

A stack, in one picture

Instead of one 40-file pull request nobody wants to review, a chain of small ones — each built on the last, each reviewable on its own.

main ── auth ─────────── api ─────────── ui
        PR #1            PR #2           PR #3
        5 files          8 files         12 files
        ▲                                ▲
        merges first                     merges last

        └────── each PR's diff = only that layer ──────┘

The problem

GitHub shipped native stacked PRs in July 2026 with a gh stack CLI. Two things go wrong the moment an agent starts using it.

It hangs

gh stack opens a prompt or a full-screen TUI whenever stdout is a terminal. Eight of its commands block forever in an agent session.

without pr-stack      with pr-stack

agent                 agent
  │ gh stack view       │ gh stack view
  ▼                     ▼
╔═══════════════╗     ┌───────────────┐
║   TUI opens   ║     │    DENIED     │
╚═══════════════╝     └───────────────┘
  │                     │  ~3 ms
  ▼                     ▼
blocks forever        "use --json"
(until you notice)    agent retries, works

GitHub documents this as a table in prose. A prose table stops nothing.

It breaks

One gh pr merge merges a single PR without retargeting the layers above it — and GitHub auto-closes them. It does not fail loudly. You find out later.

gh pr merge 1                   gh stack merge 1 --yes

main ── auth ── api ── ui       main ── auth ── api ── ui
        #1      #2     #3               #1      #2     #3
        │                               │
        ▼ merge                         ▼ merge
main ─────────  ✗       ✗       main ─────────── api ── ui
                #2      #3                       #2     #3
             AUTO-CLOSED                  base retargeted ✓

A plain git rebase is the same story: it moves one branch and leaves every branch above pointing at abandoned commits.

What this does about it

1. Your agent never hangs

Every session-blocking command is denied before it runs, with the working form handed back to the agent:

pr-stack: blocked `gh stack view`

A bare `gh stack view` opens a full-screen TUI under a PTY and blocks forever.
  to parse   : gh stack view --json
  to display : gh stack view --short
Instead of It runs
bare view gh stack view --json
bare submit gh stack submit --auto
bare init / add / checkout the form with an explicit argument
switch gh stack up / down / top / bottom
modify unstack --local then initmodify is TUI-only, with no non-interactive path at all

2. Your stack never silently breaks

Blocked Because
force-push a restack rewrites every branch above; the lease is the only protection → --force-with-lease
plain git rebase moves one branch and orphans the rest → gh stack rebase --upstack
gh pr merge cannot merge a stack (see above) → gh stack merge <n> --yes
git reset --hard, branch delete destructive; needs your explicit say-so

Only inside a repository that gh stack manages. Everywhere else this plugin is completely silent — git commit, git push, git rebase and the rest behave exactly as they always have. It is a guard, not a cage.

3. It splits the branch you already wrote

GitHub's advice is to plan the layers before writing code. Its own stack-design reference puts it bluntly:

The failure mode to avoid is writing everything on one branch and trying to split it afterwards.

True — and useless once the 40-file branch exists.

 before
   main ── feature ─────────────────────── 40 files, 1 PR
                                           "LGTM 👍" (nobody read it)

 after   /pr-stack:split
   main ── refactor ── schema ── api ── ui ── tests
           #1          #2        #3     #4    #5
           5 files     3         8      12    12

   proof   git diff <anchor> HEAD  →  empty
           nothing lost, nothing invented — or it stops and tells you

4. It tells you it won't work before you start

Stacked PRs aren't enabled on every repository, and gh stack only says so via exit code 9 — after a command has already failed halfway through your workflow. This checks first, every session:

gh=installed
ext=installed
auth=authenticated
repo=/Users/you/code/project
stacks=available
stack=main <- auth <- api* (2 layers, 2 PRs, 1 needs rebase)

Why it isn't just a skill

gh stack already ships an excellent agent skill, and this plugin doesn't duplicate it — it defers to gh stack <command> --help rather than restating flags that a v0.1.0 preview will change.

It's a plugin because a skill cannot stop a command from running. Skills advise; hooks enforce.

Skills pr-stack:stack · pr-stack:stack-setup · pr-stack:split-pr
Commands /pr-stack:status · /pr-stack:split
Hooks preflight check · the guard

Hooks run harness-side, so they cost zero model context.

Requirements

gh extension install github/gh-stack

Plus gh itself, authenticated. If anything's missing the plugin says so and walks you through it — run /pr-stack:status.

Small print

  • gh stack is v0.1.0 public preview; expect its flags to move.
  • Stacks are strictly linear — parallel work needs separate stacks, and layer order can't be changed non-interactively after the fact.
  • The guard covers the Bash tool. Quoted text and heredoc bodies are treated as data, so documentation mentioning a blocked command isn't itself blocked. Where a command is genuinely ambiguous it errs toward allowing — a parser quirk must never wedge a session.
  • Blocked-but-legitimate command? Approve it in plain words, then it may be re-run once prefixed with PR_STACK_ALLOW=1. The agent must never add that itself.
  • Every timeout and command path is an environment override — see scripts/config.sh. Nothing is hardcoded to a machine, a trunk name, or a build system.
  • No review/CI iteration skill yet. Planned for v0.2.

Development

bash tests/run-tests.sh        # 307 assertions, hermetic — no real repo or PR is touched
claude plugin validate .

License

MIT — see LICENSE.

About

PR Stack Skill — guard rails that make GitHub's native stacked PRs (gh stack) safe to drive from a coding agent. A Claude Code plugin.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages