ccdwyer/stack-traffic-control

Claude Code mod,充當 gh stack 的出發看板:提供 `/stack` 面板、提示列上方的一行狀態,以及 Bash 防護 hook,將原始 force-push、rebase 與 PR 基底分支編輯導向 gh stack。
ccdwyer/stack-traffic-control

Stack Traffic Control 是給使用 GitHub 官方堆疊 PR 擴充功能 gh stack 的儲存庫使用的 Claude Code mod。/stack 指令會開啟面板,由頂到底列出堆疊;每個分支都會顯示 PR 編號、CI 檢查狀態,以及目前是否就緒、需要 rebase、正在佇列中或已合併落地,另外還有尚未推送的提交與未提交的變更,並附上重新整理按鈕。提示列上方的一行指示器會顯示你目前在堆疊中的位置;位於堆疊分支時,也會顯示 rebase 警告。防護 hook 會像 shell 一樣檢查 Bash 指令(引號、跳脫、重新導向、heredoc、; && || |、子 shell、替換、bash -c 與 eval、env/sudo/xargs 等包裝器,以及 cd/pushd/git -C 目錄追蹤),拒絕與堆疊工作流程衝突的原始指令,並把精確的 gh stack 等效指令顯示給模型。受保護的操作包括對堆疊分支與主幹執行 force-push 和刪除、rebase 到主幹或層級、rebase 或 merge 形式的 pull、對堆疊 PR 執行 gh pr edit --base,以及為堆疊分支執行 gh pr create。堆疊檔案無法讀取、目錄狀態無法得知、命令列無法解析,或單行指令先切換分支再 push 時,它會採預設拒絕。它會遵守 push refspec、push.default、branch.*.rebase、pull.rebase、pull.ff 與 git -c 覆寫值。已知限制都有文件說明;這是安全網,不是沙箱。需要 GitHub CLI、gh extension install github/gh-stack,並透過 ccdwyer-mods 外掛市集安裝。
請先查看作者 README,確認 marketplace 與外掛名稱;指令可能隨儲存庫結構而變動。
claude plugin marketplace add ccdwyer/stack-traffic-control claude plugin install stack-traffic-control

The band above the prompt, the /stack departure board, and a raw force-push refused with the gh stack alternative. MP4
A Claude Code mod that acts as a departure board for gh stack, GitHub's official stacked-PR extension.
/stack opens a pane listing the stack top to bottom. For each branch it shows the PR number, CI checks (✓ ✗ …), and whether the branch is ready, needs a rebase, is queued or has landed. It also shows unpushed commits (↑, or unpublished for a branch that has never been pushed) and uncommitted changes (✎). A refresh button updates it.
Above the prompt, when you're on a stacked branch: 🛫 stack 2/4 · feature-b · 1 needs rebase.
Guard. In a repo that uses gh stack, some raw commands are refused, and the model is shown the exact gh stack command to use instead and why. The repo's stack file (<git-common-dir>/gh-stack) decides what is protected: every branch of every stack, and their trunks, are protected from force-pushes and deletes, whichever branch you're on. Rebase, pull and PR rules apply when you're on a stacked branch.
| Raw command | Use instead |
|---|---|
| git push --force / -f / --force-with-lease / +refspec / --mirror / glob refspecs / --delete hitting a stack branch | gh stack push, gh stack submit --auto, gh stack sync --prune |
| git rebase onto the trunk, a layer or @{u} (also --onto=, or a bare git rebase) | gh stack rebase (--downstack, --upstack, --no-trunk) |
| git pull that would rebase or merge (flags and pull.rebase / pull.ff config; fast-forward-only pulls pass) | gh stack sync |
| gh pr edit --base on a stack PR | gh stack submit --auto / gh stack modify |
| gh pr create for a stack branch | gh stack submit --auto |
These commands still run, with a note attached for the model:
git rebase -i HEAD~3) runs, with a reminder to follow up with gh stack rebase --upstack.git rebase --continue, --abort and --skip run, with a reminder about the gh stack rebase equivalents.These pass untouched:
--repo)The guard reads the Bash line the way a shell would. It looks inside:
$( … ) is checked.;, &&, || and |( … ), groups { … }, if/while bodies, and $( … ) / backtick substitutionsbash -c '…' and evalenv, sudo, nohup, time, nice, command, exec, xargs, timeoutcd / pushd (including ~ and options), env -C, sudo -D, git -C, --git-dir and --work-tree. A cd inside a pipeline, a background job or an if body is handled the way the shell handles it. It also remembers where the Bash tool's persistent shell is across calls.It fails closed in four cases, but only in repos that use gh stack:
cd leaves the directory unknowable (cd -, cd $X, a cd that may not have run). Git steps are refused until a literal cd settles it.The guard also follows:
remote.<name>.push, remote.<name>.mirror) and push.default, including upstreambranch.<name>.rebase, pull.rebase and pull.ff, plus git -c overridesGIT_DIR / GIT_WORK_TREE prefixesgit rebase <upstream> <branch>, which rewrites <branch> whatever HEAD isKnown limits, as a safety net and not a sandbox:
$GIT push -f)bash script.sh / source with no git text on the linegit reset --hard and git merge on a stacked branch, which aren't checked"Needs rebase" combines gh stack's own flag with a check that each layer contains its parent layer's tip. Repos that have never used gh stack (no stack file) are never looked into further, so the guard costs nothing there.
gh extension install github/gh-stack/plugin marketplace add ccdwyer/claude-mods
/plugin install stack-traffic-control@ccdwyer-mods
/reload-plugins
claude plugin validate .
claude plugin test .
Events this mod hooks, as claude plugin validate reads the module:
session.startcommand.run{command=stack}turn.completetool.call{tool=Bash}ui.render{component=AbovePrompt}ui.render{component=PanerequestId=stack-board}Engine calls it makes: $.clock.now (via lookAt, stackAt), $.command.register, $.env.get (via shellContext), $.process.run (via run), $.state.get, $.state.set, $.ui.open, $.ui.resolve.
A tool.call hook sits in the middle of every tool call: it can see the call, refuse it, or add context to its result. This mod uses that only for the behaviour described above.
It uses your existing GitHub CLI (gh, with the gh stack extension) to read your stack and pull request status from GitHub, under your own account. Nothing is sent anywhere else.
The mod collects no analytics or telemetry, and its author receives no data from it.
Full policy: PRIVACY.md.
MIT