to-stack
Skill19 starsChanged 32 days agoMITView on GitHub
Split a large branch or PR into a stack of small PRs, verified layer by layer, and open them as linked drafts.
- Installs packages
- Commits and pushes
In this repository42 other files it gives its agents.
- AGENTS.mdAGENTS.md
- a11y-auditSkill
- architecture-auditSkill
- buildSkill
- checkSkill
- codebase-designSkill
- code-reviewSkill
- commitSkill
- create-skillSkill
- debateSkill
- debugSkill
- deps-auditSkill
- domain-modelingSkill
- feedbackSkill
- frontend-ui-engineeringSkill
- grillSkill
- guideSkill
- handoffSkill
- hardenSkill
- i18nSkill
- perf-auditSkill
- prototypeSkill
- refactorSkill
- researchSkill
- retroSkill
- reviewSkill
- reviseSkill
- safe-repoSkill
- setupSkill
- source-drivenSkill
- tddSkill
- teachSkill
- to-adrSkill
- to-docSkill
- to-prSkill
- to-releaseSkill
- to-specSkill
- to-ticketsSkill
- triageSkill
- visual-reviewSkill
- wait-whatSkill
- zoom-outSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 4 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 38
Back up: Run git branch <branch>-full <tip>.
- Very specific: line 46
Call the Skill tool with check.
- Distinctive: line 53
Commit each fix on the layer that owns the code.
- Distinctive: line 55
When adjacent edits conflict, keep both sides' intent.
- Very specific: line 75
Default: PR 1 keeps the whole-change description, because its squash is what lands, with the stack and "this PR's own diff" on top.
- Distinctive: line 87
Default: merge from the top down, squashing each PR into the one below.
- Distinctive: line 90
Keep the backup branch until PR 1 merges.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
To Stack
Turn one large change into a stack: PR 1 on the base branch, each later PR on the one below it. Reviewers read one concern at a time, and the top of the stack is byte-for-byte the tree you already tested.
Arguments: $ARGUMENTS
- A PR number or URL, or a branch. None → the current branch and its PR.
--each— land each PR on the base in order, each with its own version bump and CHANGELOG section. Default: merge from the top down into PR 1, which lands as one squash and one release.
Workflow
Resolve.
- Dirty tree → stop and ask to commit or stash.
- A PR →
gh pr view <PR> --json headRefName,baseRefName, thengh pr checkout <PR>. A branch → check it out. Its head is<tip>; its base is the PR'sbaseRefName, else the default branch. git fetch origin <base>, then diff against the remote base, since a stale local base inflates the diff:git diff --stat origin/<base>...<tip>andgit log --oneline origin/<base>..<tip>.- Tip conflicts with the base, or the base already released the planned version → merge the base in and bump first. A collision belongs to the whole change, not to one layer.
- Under ~600 changed lines without lockfiles → say a split isn't worth it, and stop unless the user insists.
Done when the scope is stated: "Splitting
feat/x(#42) vsmain: 49 files, +3432".- Map. Record what every changed file needs: its imports, and for each test case the mocks, globals, helpers and options it touches. Group the changes into concerns. For shared files (manifest, entry barrel, types index, core module, README, CHANGELOG), assign each changed line to a concern. Done when every changed line has an owner. Ownership rules: references/layering.md.
Plan. Order the concerns so each layer depends only on layers below it: manifest and config first, then the core, then features, then deprecated or compatibility code, so a future major deletes one layer. Each layer is tight:
- one concern, under ~600 changed lines without lockfiles
- green on its own
- nothing in it waits on a later layer to be used: move a reader with its writer
Present a table of layer, branch, contents, approximate lines and base, plus the merge strategy. An existing PR becomes PR 1, and its branch gets rewritten. Wait for an unambiguous yes. It covers building, pushing (
--force-with-leasefor the rewritten branch) and opening the PRs.- Back up. Run
git branch <branch>-full <tip>. Every later check compares against it. Done when the backup points at the tip. Build bottom-up. For each layer, on a new branch from the one below:
- Files that land whole:
git restore --source=<backup> --staged --worktree -- <paths>, listing both sides of a rename. Unlikegit checkout, it also applies deletions. - Shared files: write only this layer's slice. In tests, keep the final cases this layer can run. If a core behavior would go untested, write the smallest stand-in case; a later layer restores the final version.
- Manifest: only this layer's fields, then regenerate the lockfile (
npm install --package-lock-only --ignore-scripts, or the repo's equivalent). The version bump goes in layer 1. With--each, each layer bumps from the one below by its own change type, so the top's version can be above the backup's. - Docs: only this layer's README and CHANGELOG lines, under the one version heading, or the layer's own heading with
--each. - Stage explicit paths. Delete any generated output the base doesn't ignore yet, such as build shims, before the checks.
- Call the Skill tool with
check. Commit only if it's green: chain with&&. One conventional commit per layer.
Done when every layer has its commit and
checkpassed on that exact tree.- Files that land whole:
- Verify the stack.
git diff --quiet <backup> <top>must pass, because the top layer is the original tree. With--each, run it with-- . ':!<manifest>' ':!<lockfile>' ':!CHANGELOG.md', then check thatgit diff <backup> <top> -- <manifest> <lockfile> CHANGELOG.mdshows only version lines and version headings. If it fails, find the layer that lost or gained lines, fix it there, and restack as in step 7. Done when the diff is empty. Fold in fixes, only when the user asked for changes along with the split.
- Commit each fix on the layer that owns the code.
- Restack everything above it:
git rebase --update-refs --onto <layer> <layer>@{1} <top>. - When adjacent edits conflict, keep both sides' intent.
- Then check that each layer's files outside the fix still match the tree that passed
check:git diff <green-sha> <layer> -- . ':!<fix paths>'.
Done when the top differs from the backup by exactly the fixes.
Open the drafts.
- Push each layer branch with
-u, and the rewritten PR 1 branch with--force-with-lease. - Bottom-up, skip a layer that already has a PR:
gh pr list --head <branch> --state open. - Otherwise run
gh pr create --draft --base <layer below> --head <branch> --title <title> --body "Part N of M". PR 1's base is the base branch. - Record each PR number from the printed URL.
Done when every layer has a PR whose base is the layer below.
- Push each layer branch with
Write the bodies. One per layer, on the repo's PR template (
.github/pull_request_template.mdor its variants). Each body holds:Part N of Mand a one-sentence summary- the stack as a numbered list of the PR numbers, with
← this PR - what the layer adds
- review notes on anything that arrives in a later layer
- the evidence from step 5
- Default: PR 1 keeps the whole-change description, because its squash is what lands, with the stack and "this PR's own diff" on top. Retitle it to the whole change with
--title. --each: PR 1 lands alone, so its body and title cover its own layer, like the others.
Apply each body with
gh pr edit <n> --body-file <file>.Done when every PR body links the whole stack.
Report
A table of # | PR | Branch | Lines | Tests, then how to land it:
- Review from PR 1 up.
- Default: merge from the top down, squashing each PR into the one below. PR 1 merges to the base last, so no layer needs a rebase.
--each: merge PR 1 into the base, then rebase PR 2 onto the squashed commit (git fetch origin <base>, thengit rebase --onto origin/<base> <old PR 1 tip> <PR 2>) and retarget it, and so on up the stack.- A fix on a lower layer: commit it there, restack with
--update-refs, and push the layers above with--force-with-lease. - Keep the backup branch until PR 1 merges.
Next: /hb:feedback <PR 1> once reviews arrive.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

