Install
openclaw skills install @athola/nm-sanctum-stack-pushPushes all branches in a stack and opens or updates one dependent PR per slice. Use after stack-create to publish the stack or after adding commits to a slice
openclaw skills install @athola/nm-sanctum-stack-pushNight Market Skill — ported from claude-night-market/sanctum. For the full experience with agents, hooks, and commands, install the Claude Code plugin.
Push all branches in a stack and open (or update) one PR per slice, with each PR targeting its parent branch as base.
Run stack-push after stack-create has initialized the
branch topology and at least one commit exists on each
slice branch.
Also run it after adding commits to any slice to update
open PRs.
stack-create completed: branches exist with commitsgh CLI authenticated (gh auth status)Create TodoWrite items before starting:
stack-push:branches-listedstack-push:branches-pushedstack-push:prs-openedstack-push:stack-summary-postedbranches-listed)Identify all branches in the stack.
By convention they share a stack/<feature-name>/ prefix:
STACK=stack/my-feature
BASE=master
git branch --list "${STACK}/*" | sed 's/^[* ]*//'
Verify each branch has commits beyond the base:
for branch in $(git branch --list "${STACK}/*" \
| sed 's/^[* ]*//'); do
count=$(git rev-list --count \
"$(git merge-base ${BASE} ${branch})..${branch}")
echo "${branch}: ${count} commit(s)"
done
Any branch showing 0 commits must have work added before
pushing.
branches-pushed)Push every slice branch to the remote in stack order (base slice first):
for branch in $(git branch --list "${STACK}/*" \
| sed 's/^[* ]*//' | sort); do
git push --set-upstream origin "${branch}"
echo "pushed: ${branch}"
done
jj git push --all
prs-opened)Create one PR per slice, targeting its parent branch.
For the first slice the parent is master; for subsequent
slices the parent is the previous slice's branch.
PREV_BASE=master
for branch in $(git branch --list "${STACK}/*" \
| sed 's/^[* ]*//' | sort); do
# Check if a PR already exists for this branch
existing=$(gh pr list \
--head "${branch}" \
--json number \
--jq '.[0].number' 2>/dev/null)
if [ -n "${existing}" ]; then
echo "PR #${existing} already open for ${branch} -- skipping"
else
gh pr create \
--base "${PREV_BASE}" \
--head "${branch}" \
--title "[$(echo ${branch} | sed 's|.*/||')] <title>" \
--body "Part of stack \`${STACK}\`." \
--draft
echo "opened PR for ${branch} (base: ${PREV_BASE})"
fi
PREV_BASE="${branch}"
done
Fill in the actual PR titles and bodies before removing
the --draft flag.
Run Skill(sanctum:pr-prep) on each slice to generate
quality-gated descriptions.
stack-summary-posted)After all PRs are open, post a summary comment on the first PR (the root of the stack) listing the full chain:
ROOT_PR=$(gh pr list \
--head "${STACK}/$(git branch --list \
"${STACK}/*" | sed 's/^[* ]*//' | sort | head -1 \
| sed 's|.*/||')" \
--json number --jq '.[0].number')
# Build the stack table
BODY="## Stack\n\n| # | Branch | PR |\n|---|--------|----|\n"
N=1
for branch in $(git branch --list "${STACK}/*" \
| sed 's/^[* ]*//' | sort); do
pr_num=$(gh pr list --head "${branch}" \
--json number --jq '.[0].number')
BODY="${BODY}| ${N} | \`${branch}\` | #${pr_num} |\n"
N=$((N+1))
done
gh pr comment "${ROOT_PR}" --body "$(printf "${BODY}")"
--draft by default; promote slices to ready
individually as they pass reviewgit rebase --update-refs run, re-push with
git push --force-with-lease (never --force)Skill(sanctum:stack-rebase)
to cascade the rebase before updating the next PR's base