claude-code-plugin-ref…
Explain plugin, skill, command, agent, and hook mechanics used here. Use when authoring or debugging plugins. Do not use for ops; use night-market-operations.
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.
$ npx -y skills add athola/claude-night-market --skill stack-mode --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/stack-modeContext preview
The summary Claude sees to decide when to auto-load this skill.
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.
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 model_hint: standard estimated_tokens: 1100 dependencies: - sanctum:stack-create - sanctum:stack-push - sanctum:stack-rebase - leyline:git-platform
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.
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.
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:
than requiring `--stack` explicitly.
downstream PRs with stale context.
The caller creates `TodoWrite` items:
1. `stack-mode:membership-resolved` 2. `stack-mode:iteration-complete` 3. `stack-mode:root-summary-posted`
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.
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`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[*]}"Walk both directions from `$PR_NUM`:
`$BASE`. Each visited head is a stack member.
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[*]}"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
doneIf 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`.
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 -
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.
Explain plugin, skill, command, agent, and hook mechanics used here. Use when authoring or debugging plugins. Do not use for ops; use night-market-operations.
States load-bearing decisions, invariants, and weak points. Use when judging a design change. Do not use for gating; use night-market-change-control.
Rebuild the dev environment: uv, Python tiers, pins, traps. Use when onboarding or toolchain breaks. Do not use for daily commands; use night-market-operations.
Classify, gate, and review changes. Use when landing a PR, releasing, or amending rules. Do not use for failure triage; use night-market-debugging-playbook.
Search and record project memory (Discussions, journal, ADRs). Use before re-investigating anything. Do not use for settled battles; see failure-archaeology.
Bind loop 'done' to unfakeable gates. Use to harden egregore/herald loops or promote completion_integrity. Not for QA gates; use night-market-validation-and-qa.