Skip to content
Development
Skill

/stack-mode

Detects shared stack membership and iterates a command across all PRs in base-to-tip order. Use when a command supports --stack flag for multi-PR iteration.

From plugin
claude-night-market
343200 skills60 agents162 commands1 MCP

Claude Code

$ npx -y skills add athola/claude-night-market --skill stack-mode --agent claude-code

SKILL.md

stack-mode.SKILL.md
name: stack-mode
description: Detects shared stack membership and iterates a command across all PRs in base-to-tip order. Use when a command supports --stack flag for multi-PR iteration.
alwaysApply: false
category: workflow-automation
tags:
- git
- stacked-diffs
- pr
- review
- fix-pr
- iteration
tools: []
complexity: medium
estimated_tokens: 1100
dependencies:
- sanctum:stack-create
- sanctum:stack-push
- sanctum:stack-rebase
- leyline:git-platform

Stack Mode

Shared contract for commands that need to operate across a whole stack of dependent PRs in one invocation. Used by `/pr-review --stack` and `/fix-pr --stack`.

The goal is one simple thing: when a PR is part of a stack targeting a common base branch, loop the command's normal workflow across every PR in the stack in base-to-tip order and emit one consolidated summary on the stack root.

When To Use

Load this skill when a command accepts a `--stack` flag (or auto-detects stack membership) and needs to iterate its normal workflow across multiple PRs.

Do NOT load this skill for single-PR workflows. The per-PR workflow stays unchanged; stack mode wraps it.

When NOT To Use

  • Creating the stack (use `sanctum:stack-create`)
  • Cascading a rebase through it (use `sanctum:stack-rebase`)

Contract

A calling command MUST:

1. Accept a `--stack` boolean flag AND a `--base <branch>` override (default: `master`). 2. Call Step 1 below to resolve stack membership BEFORE running its main workflow. 3. Run its main workflow per PR in the resolved order. 4. Emit per-PR outputs unchanged (thread replies, issue links, etc.). 5. Emit ONE stack-level summary comment on the root PR using the format in Step 4. 6. Respect per-PR Gate rules (every PR still needs its own thread resolution and issue tracking).

A calling command MAY:

  • Auto-detect stack membership and prompt the user rather

than requiring `--stack` explicitly.

  • Short-circuit iteration when a per-PR failure leaves

downstream PRs with stale context.

Required Progress Tracking

The caller creates progress items:

1. `stack-mode:membership-resolved` 2. `stack-mode:iteration-complete` 3. `stack-mode:root-summary-posted`

Step 1: Resolve Stack Membership (`membership-resolved`)

Given a starting PR number `$PR_NUM` and optional base `$BASE` (default: `master`), try three strategies in order and stop at the first that yields a stack of size >= 2.

Strategy A: Branch-name convention (cheapest)

START_HEAD=$(gh pr view "$PR_NUM" \
  --json headRefName -q .headRefName)

# stack/<feature-name>/<slice-name>
if [[ "$START_HEAD" =~ ^stack/([^/]+)/.+$ ]]; then
  FEATURE="${BASH_REMATCH[1]}"
  PREFIX="stack/${FEATURE}/"

  # All local branches with the same prefix
  STACK_BRANCHES=$(git branch --list "${PREFIX}*" \
    | sed 's/^[* ]*//' | sort)

  # Map branches -> PR numbers (skip branches with no PR)
  STACK_PRS=()
  for branch in $STACK_BRANCHES; do
    pr=$(gh pr list --head "$branch" \
      --json number --jq '.[0].number')
    [ -n "$pr" ] && STACK_PRS+=("$pr")
  done

  echo "strategy=A prs=${STACK_PRS[*]}"
fi

Strategy B: Stack summary comment (most reliable)

`stack-push` posts a `## Stack` markdown table on the root PR with columns `# | Branch | PR`. Parse it:

# Find the root PR of the stack containing $PR_NUM
# The current PR may be the root, or may link to it via
# a "Part of stack `stack/<feature>`" phrase in its body
BODY=$(gh pr view "$PR_NUM" --json body -q .body)

# Look for a "## Stack" table in THIS PR's comments
TABLE=$(gh pr view "$PR_NUM" --json comments \
  --jq '.comments[] | select(.body | contains("## Stack"))
        | .body' | head -1)

# If not on this PR, look for the root PR reference
if [ -z "$TABLE" ]; then
  ROOT_REF=$(echo "$BODY" \
    | grep -oE 'stack/[^ `]+' | head -1)
  # ... resolve ROOT_REF -> root PR number and re-fetch
fi

# Parse the table: extract all `#<num>` from the PR column
STACK_PRS=($(echo "$TABLE" \
  | grep -oE '#[0-9]+' | tr -d '#' | sort -un))

echo "strategy=B prs=${STACK_PRS[*]}"

Strategy C: Base-chain walk (fallback)

Walk both directions from `$PR_NUM`:

  • Up: repeatedly resolve `baseRefName` until it equals

`$BASE`. Each visited head is a stack member.

  • Down: find open PRs whose `baseRefName` equals one of

the visited heads. Recurse.

# Ascend from $PR_NUM to the root
CUR=$PR_NUM
CHAIN=($CUR)
while true; do
  BASE_REF=$(gh pr view "$CUR" \
    --json baseRefName -q .baseRefName)
  [ "$BASE_REF" = "$BASE" ] && break

  PARENT=$(gh pr list --head "$BASE_REF" \
    --state open --json number --jq '.[0].number')
  [ -z "$PARENT" ] && break

  CHAIN=("$PARENT" "${CHAIN[@]}")
  CUR=$PARENT
done

# Descend from the root collecting children
ROOT=${CHAIN[0]}
FRONTIER=("$ROOT")
while [ ${#FRONTIER[@]} -gt 0 ]; do
  PARENT=${FRONTIER[0]}
  FRONTIER=("${FRONTIER[@]:1}")

  PARENT_HEAD=$(gh pr view "$PARENT" \
    --json headRefName -q .headRefName)

  CHILDREN=($(gh pr list --base "$PARENT_HEAD" \
    --state open --json number --jq '.[].number'))

  for c in "${CHILDREN[@]}"; do
    CHAIN+=("$c")
    FRONTIER+=("$c")
  done
done

STACK_PRS=("${CHAIN[@]}")
echo "strategy=C prs=${STACK_PRS[*]}"

Ordering

Regardless of strategy, order the final list **base-to-tip** (root PR first, leaf PR last). The root is the PR whose `baseRefName` equals `$BASE`.

ROOT_PR=""
for p in "${STACK_PRS[@]}"; do
  base=$(gh pr view "$p" --json baseRefName -q .baseRefName)
  if [ "$base" = "$BASE" ]; then
    ROOT_PR=$p
    break
  fi
done

If the stack size is 1, the command MUST fall back to single-PR mode and emit a warning: `stack-mode: only one PR found; --stack has no effect, proceeding as single-PR`.

GitLab / Bitbucket

See `Skill(leyline:git-platform)` for `glab` / Bitbucket equivalents of the `gh` calls above. The three strategies translate directly: GitLab MR dependencies replace base-chain walks, and the `glab mr view --output json` shape matc

Read more
@athola
Ships withclaude-night-market

A plugin marketplace for Claude Code. Install only the plugins you need to run git workflows, code review, spec-driven development, and autonomous agents from inside your Claude Code session.

343200 skills60 agents1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
343
Star history of athola/claude-night-market on GitHub, a chart by star-history.com

Other skills on claude-night-market.

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills11d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc13d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react2d252k
@facebook@facebookInstall Skill

Questions about stack-mode.

Which coding agents can use stack-mode?
stack-mode installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.