Last updated 2026-05-07
The Stacked-diff Workflow
A diff is a single, reviewable, logical change. A feature is a stack of diffs that ship together. stax's CLI is built around this — every verb maps to a step in the loop.
The full loop
# Set upstax clone myorg/repocd repo
# Startstax feature "user auth"
# Iterate# ... edit code ...stax diff "Add login form"# ... edit more ...stax diff "Add JWT validation"
# Stay currentstax sync
# Open for reviewstax submit
# After approvalstax landStarting work
Pick the verb that matches the change type. They all do the same thing — the verb just sets the Conventional-Commit prefix used for diff titles and the branch prefix.
| Command | Branch prefix | Commit prefix |
|---|---|---|
stax feature <name> | feature/ | feat: |
stax fix <name> | fix/ | fix: |
stax docs <name> | docs/ | docs: |
stax chore <name> | chore/ | chore: |
stax start <name> | feature/ | (detected later) |
Each command auto-saves any uncommitted work on the current branch as
a WIP: auto-save before switching context commit, then
cuts a new branch from origin/main.
Saving a diff
stax diff [message]-
With
[message], the diff title is<type>(scope): <message>verbatim. -
Without a message, stax uses the local LLM helper
(
internal/llm) to generate a Conventional-Commit title from the diff content. -
--previewprints what would be staged without committing. -
--updateamends the diff currently being edited (seestax diff edit Dn).
Editing an earlier diff
stax diff edit D1 # focus on diff position 1# ... change code ...stax diff --update # amend itstax diff # leave edit mode and append a new diffRunning CI for a diff
stax diff check # run CI on the most recent diffstax diff check D2 # run CI on a specific diffTriggers the runner on the diff's commit and streams output. Useful for finding the exact diff that broke a test.
Splitting a sloppy diff
stax split # walk through hunks, group them into multiple diffsstax split --preview # see the proposed split without applying itStaying current
stax sync # rebase the stack on origin/mainstax sync --continue # after resolving conflictsstax sync --abort # bail out sync fetches origin/main, rebases the
feature branch, and re-orders diff metadata so the position numbers
stay correct. If a conflict occurs, you resolve it in your editor
and call stax sync --continue.
Switching context
stax features # list all featuresstax switch <query> # fuzzy-switch to another featurestax context # tell me where I amSwitching auto-saves uncommitted work on the current branch first. No work is lost.
Submitting for review
stax submit # opens or updates the PR via gh CLIstax submit --preview # see what would be pushed without doing it
Each diff in the stack becomes a commit on the PR branch. The PR
body lists the diffs in stack order. submit prints
both the GitHub URL and the local dashboard URL when both are
available.
Landing
stax land # land the lowest approved diff onto mainstax land D2 # land a specific diffstax land --force # skip approval / CI checks
Default behaviour: squash-merge the lowest-position diff that has
been approved on GitHub, advance origin/main, and
rebase the remaining stack on top.
Inspecting state
stax features # all features (with diff counts and current marker)stax diffs # diffs in the current feature, with file countsstax context # one-line "where am I" summarystax status # like git status, plus diff metadatastax log -n 50 # last 50 activity-log entriesRecovering
stax undo # undo the last actionstax undo --list # see what's undoableThe activity log records every state-changing command (start, diff, sync, switch, etc.) with enough metadata to reverse it.