Skill Tracer
Skills › Compound Engineering › ce-commit-push-pr › gh-stack-cli.md

gh-stack-cli.md

83 lines · skills/ce-commit-push-pr/references/gh-stack-cli.md at 3449230

Open on GitHub
1# `gh stack` semantics this skill relies on
2
3Verified against `gh stack version 0.1.0`. `gh stack <command> --help` is authoritative — if it
4disagrees with anything here, follow `--help` and say so in your report. (`gh stack help <command>`
5does not work; it prints top-level help.)
6
7Only the behavior that changes a decision in stack mode is listed. This file is self-contained on
8purpose: do not depend on the user having a separate `gh-stack` skill installed.
9

gh stack semantics this skill relies on

Verified against gh stack version 0.1.0. gh stack <command> --help is authoritative — if it disagrees with anything here, follow --help and say so in your report. (gh stack help <command> does not work; it prints top-level help.)

Only the behavior that changes a decision in stack mode is listed. This file is self-contained on purpose: do not depend on the user having a separate gh-stack skill installed.

Raw lines 1 to 9
10## Classifying a parent
12```bash
13gh stack checkout "<parent-pr-number>"
14```
16Resolve a parent by **PR number** whenever one exists — that is what pulls a stack down from
17GitHub. A bare branch name resolves against **local** stacks only, so a branch-only parent can be
18classified locally and no further.
20Branch on the exit code; status text goes to stderr and must not be parsed.
22| Exit | Meaning | What it means here |
23|---|---|---|
24| 0 | Success | Parent is in a stack, and `HEAD` has moved to it |
25| 2 | Not in a stack | Parent is standalone; nothing was checked out or fetched |
26| 5 | Invalid arguments | Fix the invocation; see `--help` |
27| 6 | Disambiguation required | Branch is in several stacks — check out a non-shared branch |
28| 9 | Stacked PRs unavailable | Not enabled on this repository; tell the user and stop |
30```bash
31gh stack view --json # JSON on stdout: trunk, currentBranch,
32 # branches[] { name, head, base, isCurrent, isMerged, needsRebase,
33 # pr { number, url, state } }
34```
36`base` is the parent SHA the branch was last known to contain, not the parent's current tip;
37`needsRebase` is true when that tip is no longer an ancestor. There is no field naming the top of
38the stack and no documented branch ordering, so do not derive position from this payload — use
39`add`'s exit 5 instead.

Classifying a parent

gh stack checkout "<parent-pr-number>"

Resolve a parent by PR number whenever one exists — that is what pulls a stack down from GitHub. A bare branch name resolves against local stacks only, so a branch-only parent can be classified locally and no further.

Branch on the exit code; status text goes to stderr and must not be parsed.

ExitMeaningWhat it means here
0SuccessParent is in a stack, and HEAD has moved to it
2Not in a stackParent is standalone; nothing was checked out or fetched
5Invalid argumentsFix the invocation; see --help
6Disambiguation requiredBranch is in several stacks — check out a non-shared branch
9Stacked PRs unavailableNot enabled on this repository; tell the user and stop
gh stack view --json    # JSON on stdout: trunk, currentBranch,
                        # branches[] { name, head, base, isCurrent, isMerged, needsRebase,
                        #              pr { number, url, state } }

base is the parent SHA the branch was last known to contain, not the parent's current tip; needsRebase is true when that tip is no longer an ancestor. There is no field naming the top of the stack and no documented branch ordering, so do not derive position from this payload — use add's exit 5 instead.

Raw lines 10 to 40
41## Resolving a PR head
43`gh pr view "<n>" --json headRefName,headRefOid,author` identifies the head; `headRefName` alone
44does not, because a same-repo name can be absent or stale locally and can collide with an unrelated
45branch. Create a local branch at `headRefOid`, fetching `refs/pull/<n>/head` when that commit is not
46reachable — reachability leaves the commit with no branch to name.

Resolving a PR head

gh pr view "<n>" --json headRefName,headRefOid,author identifies the head; headRefName alone does not, because a same-repo name can be absent or stale locally and can collide with an unrelated branch. Create a local branch at headRefOid, fetching refs/pull/<n>/head when that commit is not reachable — reachability leaves the commit with no branch to name.

Raw lines 41 to 47
48## Building
50```bash
51gh stack init [--base "<trunk>"] "<branch>"...
52```
54Processes branches bottom to top and checks out the **last** one. **Existing branches are adopted;
55missing ones are created** — the first from the trunk, each later one from the branch before it.
56There is no separate adopt mode: existence decides. `--base` selects a non-default trunk, so a
57parent branch can serve as the trunk without joining the stack.
59```bash
60gh stack add "<branch>"
61```
63Must run from the **top** branch of the stack (or the trunk while it is still empty); anywhere else
64exits **5**. Exit 5 here means "you are not on the top", and moving there with `gh stack top` is a
65decision, not a fix: it changes which layer the new branch is parented to. Whether that is correct
66belongs to the caller — when a specific parent was named, it is not. Without `-Am`, `add` does not
67touch the working tree, so staged and unstaged changes follow onto the new branch.
69```bash
70gh stack submit --auto [--open]
71```
73`--auto` avoids a title prompt per new PR. `--open` creates PRs ready for review instead of drafts,
74and also marks pre-existing drafts ready.

Building

gh stack init [--base "<trunk>"] "<branch>"...

Processes branches bottom to top and checks out the last one. Existing branches are adopted; missing ones are created — the first from the trunk, each later one from the branch before it. There is no separate adopt mode: existence decides. --base selects a non-default trunk, so a parent branch can serve as the trunk without joining the stack.

gh stack add "<branch>"

Must run from the top branch of the stack (or the trunk while it is still empty); anywhere else exits 5. Exit 5 here means "you are not on the top", and moving there with gh stack top is a decision, not a fix: it changes which layer the new branch is parented to. Whether that is correct belongs to the caller — when a specific parent was named, it is not. Without -Am, add does not touch the working tree, so staged and unstaged changes follow onto the new branch.

gh stack submit --auto [--open]

--auto avoids a title prompt per new PR. --open creates PRs ready for review instead of drafts, and also marks pre-existing drafts ready.

Raw lines 48 to 75
76## Never
78- **`gh stack link`** — GitHub-only by design, creates no local tracking, so a later
79 `gh stack submit`, `gh stack view`, or `gh stack merge` will not see the layer. It exists for
80 branches managed by external tools (jj, Sapling, git-town).
81- **`gh pr merge`** on a stack member — it cannot merge a stack. Landing uses `gh stack merge`.
82- **Bare `view` / `submit` / `init` / `add` / `checkout`** — each prompts or opens a TUI that
83 blocks under a PTY. Always pass the arguments and flags shown above.

Never

  • **gh stack link** — GitHub-only by design, creates no local tracking, so a later gh stack submit, gh stack view, or gh stack merge will not see the layer. It exists for branches managed by external tools (jj, Sapling, git-town).
  • **gh pr merge** on a stack member — it cannot merge a stack. Landing uses gh stack merge.
  • **Bare view / submit / init / add / checkout** — each prompts or opens a TUI that blocks under a PTY. Always pass the arguments and flags shown above.
Raw lines 76 to 83