| name | sapling |
| description | Use when the user indicates they want to work with Sapling; after that initial signal, prefer Sapling by default for the rest of the conversation. |
Sapling Stacked Diffs Workflow
Use Sapling (sl) for stacked diffs and PR management on local Git repositories.
Do not invoke this skill just because the repo could support Sapling or because stacked-diff workflow might be useful.
The user needs to give some signal that they want Sapling, such as explicitly invoking /sapling or $sapling, asking
to use Sapling, referring to sl, or otherwise making Sapling the requested tool.
After that first signal, treat Sapling as the default VCS workflow for the rest of the conversation unless the user asks
to switch away from it.
Sapling runs on top of an existing .git repo — no sl clone or .sl repo needed. Just run sl commands in any git
working tree.
Sandbox
ALL sl commands MUST be run with dangerouslyDisableSandbox: true. Sapling writes to .git/ (via .sl/ backing
store) and makes network requests to GitHub.
Critical Rules
- NEVER commit or amend unless the user explicitly asks, or asks to create/update/merge a PR for uncommitted local
changes. Requests such as "make a PR", "submit this stack", or "merge it" implicitly authorize creating the
necessary local commit(s) first when the working copy is dirty. Staging files (
sl add) is fine without asking.
- NEVER create or update PRs unless the user explicitly asks. Each PR operation requires fresh explicit consent.
- ALWAYS stack new commits on top of the current working copy parent while the stack is live. Never navigate to
trunk first just to start a new diff. Even if changes are logically independent, the default is to extend the stack.
Only start a new stack off trunk when explicitly asked.
- Use
sl pull --rebase when a merged PR changed trunk. Plain sl pull still updates the pulled remote graph and
bookmarks, but it does not rewrite local commits or the working copy. If a stack has landed ancestors or GitHub shows
stale parent diffs, start with sl pull --rebase. Only fall back to an explicit sl rebase repair when that still
leaves the stack parented on the pre-merge local commit.
- Always submit from the top of the stack. After rebases or
sl amend --to ..., the working copy may be left on a
lower commit. Running sl pr submit --stack from there can leave descendant PRs stale.
- Do not run
sl with --help or exploratory commands unless a command fails with an unexpected error.
Stack Visualization
Run sl (no arguments) or sl smartlog to display the commit graph. This shows your stack, the working copy position,
and commit hashes.
Use sl ssl (shorthand for sl smartlog -T {ssl}) to show the graph with GitHub PR status annotations.
Pay attention to landed ancestors. If sl ssl shows the bottom open commit parenting on a local commit annotated like
[Landed as ...], the stack is still based on the pre-merge local commit, not the landed main commit. That is a sign
you need to sync the stack before trusting GitHub's diffs. Usually that means sl goto top followed by
sl pull --rebase. If the landed ancestor is still in the chain after that, use an explicit sl rebase repair.
Core Operations
New commit on top of the stack
sl add <files>
sl commit -m "commit message"
Sapling has no staging index — sl commit includes all pending changes by default. Use sl add for new untracked
files, then sl commit captures everything. To commit only specific files, pass them directly:
sl commit -m "message" <file1> <file2>
Amend the current commit
sl amend
Folds all pending changes into the current commit. Automatically rebases descendant commits unless conflicts arise.
To also update the commit message:
sl amend -m "updated message"
To amend only specific files into the current commit:
sl amend <file1> <file2>
Amend a commit lower in the stack
sl amend automatically rebases all descendant commits. When there are no conflicts, restacking is fully automatic — no
manual rebase step needed.
The typical workflow for editing a commit in the middle of the stack:
sl goto <commit-hash>
sl amend
sl goto top
Alternatives that skip the navigation:
sl amend --to <commit-hash> — fold pending changes into a specific commit without navigating to it first.
sl absorb — automatically distribute pending changes to the correct commits in the stack based on which commit last
touched each edited line.
Both also auto-restack descendants.
Resolving conflicts during restacking
If sl amend (or sl rebase) hits a conflict, it stops and leaves conflict markers in the affected files. To resolve:
- Edit the conflicted files to resolve the markers.
- Run
sl rebase --continue to resume restacking.
To abandon instead: sl rebase --abort.
Navigate the stack
sl goto <commit-hash> — jump to a specific commit
sl next / sl prev — move up/down one commit in the stack
sl next <n> / sl prev <n> — move up/down by n commits
sl goto top — jump to the top of the stack
sl goto bottom — jump to the bottom of the stack
Rebase
sl rebase -d <destination>
Moves the current commit (and descendants) onto <destination>. Use -s <commit> to pick a different root.
To restack all commits in the current stack onto their latest parent versions:
sl rebase --restack
When a stack has been extended on top of a local commit that later landed on main, the normal repair is:
sl goto top
sl pull --rebase
Sapling documents sl pull --rebase as rebasing the current commit or current stack onto trunk. That is the right first
move after a lower PR lands.
If GitHub is still showing merged changes in an open PR after that, use a more explicit repair. Start from the top of
the stack, then use one of these:
sl rebase --restack
or, if the root of the open stack is clearly known:
sl rebase -s <bottom-open-commit> -d main
The second form is the safer repair when GitHub is still showing old merged changes in the bottom PR, because it names
the exact open sub-stack that should be moved onto main.
Fold commits together
sl fold --from <commit-hash>
Combines commits from <commit-hash> through the current commit into one.
Split a commit
sl split
Opens an interactive editor to split the current commit's changes into multiple commits.
Pull / sync with remote
sl pull --rebase
Fetches commits from the remote and rebases the current commit or current stack onto trunk.
Use this as the normal sync-before-edit and sync-after-merge operation.
Plain sl pull is still useful when you want remote graph and bookmark updates without rewriting local commits or the
working copy. If the stack still includes landed ancestors after sl pull --rebase, or if GitHub is still showing
changes from already-merged commits in an open PR, follow up with an explicit restack or targeted rebase.
Creating PRs
When the user asks to make a PR or submit the stack:
- If the working copy has uncommitted changes, treat that request as implicit authorization to create the necessary
commit first. Do not stop just because the changes have not been committed yet.
- Keep the commit message concise because its first line becomes the PR title.
- First move to the top of the stack so the full descendant chain is in scope for submission.
sl goto top
sl pr submit --stack
This creates or updates GitHub PRs for all commits in the stack. Each commit becomes its own PR, stacked on GitHub. The
--stack flag includes draft ancestor commits.
To submit only the current commit (not the full stack):
sl pr submit
To create PRs as drafts:
sl goto top
sl pr submit --draft --stack
After submitting, display the PR URLs from the output to the user. Use sl ssl to see PR status.
Update existing PRs
After amending commits, adding new commits, or rebasing the stack, re-run submission from the top:
sl goto top
sl pr submit --stack
If the bottom PR still shows diff from an already-merged ancestor after submit, the stack is probably parented on the
pre-merge local commit rather than the landed main commit. From the top of the stack, run sl pull --rebase first. If
that is still not enough, fix the ancestry with sl rebase --restack or sl rebase -s <bottom-open-commit> -d main,
then submit again from the top.
Merging PRs
Sapling does not have a merge command. Use gh to squash-merge:
gh pr checks <number> --watch --fail-fast
gh pr merge <number> --squash
Wait for CI to pass before merging. gh pr checks --watch --fail-fast blocks until all checks finish, exiting non-zero
on failure.
After every merge, sync and restack before doing anything else — including merging the next PR in the stack:
sl goto top
sl pull --rebase
sl goto top
sl pr submit --stack
This must happen between each merge. For a stack of five PRs, merge the bottom one, sl goto top, sl pull --rebase,
sl pr submit --stack, then merge the next one, and so on.
If sl ssl still shows the remaining stack hanging off a [Landed as ...] ancestor after sl pull --rebase, stop and
repair the ancestry explicitly with sl rebase --restack or sl rebase -s <bottom-open-commit> -d main before
resubmitting. The goal is that the next PR is rebased onto the real landed trunk commit, so GitHub does not keep showing
already-merged changes from the previous PR.
Undo
sl undo
Undoes the last Sapling operation. Use sl redo to reapply.
Commit Message Style
The first line of the commit message becomes the PR title. Keep it terse and imperative.
For the body, explain why the change was made when non-obvious. Err on the side of brevity.