Skip to content
Development
Skill

/gh-stack

Manages stacked PRs and splits multi-part work into reviewable branches with gh-stack. Use for stack creation, viewing, edits, push, submit, sync, rebase, merge, or checkout; when asked to split or isolate work for review; whenever a user mentions a stack, branch layers,

From plugin
sherifabdlnaby-skills
827 skills
Install
$ npx -y skills add sherifabdlnaby/skills --skill gh-stack --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/gh-stack

Context preview

The summary Claude sees to decide when to auto-load this skill.

Manages stacked PRs and splits multi-part work into reviewable branches with gh-stack. Use for stack creation, viewing, edits, push, submit, sync, rebase, merge, or checkout; when asked to split or isolate work for review; whenever a user mentions a stack, branch layers,

SKILL.md

gh-stack.SKILL.md
name: gh-stack
description: >
  Manages stacked PRs and splits multi-part work into reviewable branches with gh-stack.
  Use for stack creation, viewing, edits, push, submit, sync, rebase, merge, or checkout;
  when asked to split or isolate work for review; whenever a user mentions a stack,
  branch layers, dependent PRs, or gh stack; or when a stack is checked out.
metadata:
  author: github
  version: "0.1.0"

gh-stack

`gh stack` is a [GitHub CLI](https://cli.github.com/) extension for stacked branches and pull requests. A stack is an ordered chain of branches rooted on a trunk, where each branch has one PR based on the branch below it, so a reviewer sees only that layer's diff.

`gh stack` prints a stack trunk-first, left to right:

(main) <- auth <- api <- frontend

Left is the **bottom**, right is the **top**. `auth` is based on `main` and merges first; `frontend` merges last. `up` moves toward the top, away from trunk; `down` moves toward it. Foundational work belongs at the bottom, code that depends on it above. For how to choose the layers, read `references/stack-design.md`.

Setup

gh extension install github/gh-stack
git config rerere.enabled true         # remember conflict resolutions
git config remote.pushDefault origin   # required if the repo has more than one remote

Non-interactive use

`gh stack` branches on whether **stdout is a TTY**. Piped, most commands error cleanly or print static text; under a PTY the same commands open a prompt or a full-screen TUI and block forever. Agent harnesses differ, so always pass the flags below instead of relying on that detection.

**Multiple remotes:** never run `push`, `submit`, `sync`, `rebase`, or `link` without `--remote <name>` unless `remote.pushDefault` is configured. `checkout` and `trunk` have no `--remote` flag and require the config.

| Always run | Never run bare | Why | |---|---|---| | `gh stack view --json` | `gh stack view` | opens a TUI under a PTY | | `gh stack submit --auto` | `gh stack submit` | prompts for a title per new PR | | `gh stack merge <target> --yes` | `gh pr merge` | `gh pr merge` cannot merge a stack | | `gh stack init <branch>...` | `gh stack init` | prompts for branch names | | `gh stack add <branch>` | `gh stack add` | prompts for a name, and fails even when piped | | `gh stack checkout <target>` | `gh stack checkout` | opens a selection menu | | `gh stack up` / `down` / `top` / `bottom` | `gh stack switch` | `switch` is menu-only | | — | `gh stack modify` | TUI-only, no non-interactive path |

  • `view --short` is safe in both modes, but it is formatted for humans. Use `--json` to parse.
  • **`checkout <pr>` when a different local stack already covers those branches** cannot be forced.

Run `gh stack unstack --local` first (this keeps the stack on GitHub), then retry.

Branch placement

  • **Starting multi-part work:** create the stack before writing files. Do not implement every

concern on trunk and split it later. Put one dependent concern in each layer, bottom to top.

  • **Editing an existing stack:** check out the layer that owns the change before editing. Never

commit a lower layer's concern on the current top branch. Run `gh stack view --json`; if ownership is unclear, inspect `git log --all -- <path>`. Then check out the owner, edit, commit, rebase upstack, and return to top.

gh stack down                   # or: gh stack checkout api
git add ... && git commit -m "Add get-user endpoint"
gh stack rebase --upstack       # replay every branch above onto the change
gh stack top                    # return to where you were
gh stack push

Core loop

gh stack init auth              # create the stack and check out its branch
git add ... && git commit -m "Add auth middleware"
gh stack add api                # next layer, branched from the current one
git add ... && git commit -m "Add API routes"
gh stack submit --auto          # push every branch and open draft PRs
gh stack view --json            # confirm

Add `--open` to `submit` to create PRs ready for review instead of drafts. Branch names are verbatim — `gh stack add refactor/foo` creates `refactor/foo`.

Staying in sync

gh stack sync                   # fetch, reconcile with GitHub, rebase, push, refresh PR state
gh stack sync --prune           # also delete local branches for merged PRs

Pruning never happens without `--prune` when non-interactive. If the local and remote stacks have diverged, `sync` prints both chains, makes no changes, and exits 0 with `Sync aborted` — see `references/troubleshooting.md`.

Merging

Scope the merge with an argument:

gh stack merge 42 --yes          # PR #42 plus every unmerged PR below it
gh stack merge 7 --yes           # every unmerged PR in stack #7
gh stack merge 42 --yes --squash # or --merge, --rebase, --merge-method <method>

Pass a PR number to merge that PR and every unmerged PR below it, or a stack number to merge every unmerged PR in that stack. The operation is all-or-nothing: if any PR in that set cannot merge, none do.

Without a method flag the last-used method is reused. If the base branch uses a merge queue, the stack is queued instead and the queue picks the method, ignoring any flag you passed with a warning; queued PRs may land in separate groups.

Reading state

`gh stack view --json` writes JSON to **stdout**. Status messages go to **stderr** — do not parse them, branch on exit codes instead.

trunk           string
currentBranch   string
branches[]      name, head, base, isCurrent, isMerged, isQueued, needsRebase
branches[].pr   number, url, state ("OPEN" | "MERGED" | "QUEUED"); absent when no PR exists

`base` is the saved SHA of the parent branch that this branch was last known to contain. It may be older than the parent's current tip. `needsRebase` is true when the current parent tip is no longer an ancestor of the branch.

Exit codes

| Code | Meaning | Recovery

Read more
Ships withsherifabdlnaby-skills

🍣 Hand-rolled AI Skills distilled from my everyday experience. Git & Mise (...and others).

Get the whole plugin
Stats
8
Stars
1
Forks
Active
Maintenance
Python
Language
11d ago
Last commit
3mo ago
Created

Repo: sherifabdlnaby/skills

Other skills on sherifabdlnaby-skills.