Stacked Git branches and PRs — fast, safe, and built for humans and AI agents.
Install · Quickstart · Commands · Docs
One giant PR is slow to review and risky to merge. A stack of small PRs is the answer — but managing stacks by hand with git rebase --onto is a footgun. stax makes stacks a first-class Git primitive.
- Stack, don't wait. Keep shipping on top of in-review PRs.
st create,st ss, done. - Native-fast. A single Rust binary that starts in ~25ms.
st lsbenches ~70× faster than Graphite and ~215× faster than Freephite on this repo. - Agent-native. Run parallel AI agents on isolated branches (
st lane), auto-resolve rebase conflicts (st resolve), and generate branch names, commit messages, and PR details from real diffs. - Undo-first. Every destructive op snapshots state.
st undo/st redorescue risky rebases instantly. - Batteries-included TUI. Run bare
stto browse the stack, inspect diffs, and watch CI hydrate live.
staxinstalls two binaries:staxand the short aliasst. This README usesst.
The shortest path on macOS and Linux:
brew install cesarferreira/tap/staxOther installation methods — cargo-binstall, prebuilt binaries, Windows, from source
cargo binstall staxDownload the latest binary from GitHub Releases:
# macOS (Apple Silicon)
curl -fsSL https://github.com/cesarferreira/stax/releases/latest/download/stax-aarch64-apple-darwin.tar.gz | tar xz
# macOS (Intel)
curl -fsSL https://github.com/cesarferreira/stax/releases/latest/download/stax-x86_64-apple-darwin.tar.gz | tar xz
# Linux (x86_64)
curl -fsSL https://github.com/cesarferreira/stax/releases/latest/download/stax-x86_64-unknown-linux-gnu.tar.gz | tar xz
# Linux (arm64)
curl -fsSL https://github.com/cesarferreira/stax/releases/latest/download/stax-aarch64-unknown-linux-gnu.tar.gz | tar xz
mkdir -p ~/.local/bin
mv stax st ~/.local/bin/
# Ensure ~/.local/bin is on your PATH:
# echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrcWindows (x86_64): download stax-x86_64-pc-windows-msvc.zip from Releases, extract stax.exe and st.exe, and place them on your PATH. See Windows notes.
Prereqs:
- Debian/Ubuntu:
sudo apt-get install libssl-dev pkg-config - Fedora/RHEL:
sudo dnf install openssl-devel - Arch:
sudo pacman -S openssl pkg-config - macOS: OpenSSL included
Then:
cargo install --path . --locked
# or
make install
# or
task installNo system OpenSSL? Use the vendored feature:
cargo install --path . --locked --features vendored-opensslVerify the install:
st --versionst setup handles shell integration, AI agent skills, and GitHub auth in a single step:
st setup --yesAlternative auth options
# Import from GitHub CLI
gh auth login && st auth --from-gh
# Enter a token interactively
st auth
# Or via env var
export STAX_GITHUB_TOKEN="ghp_xxxx"By default stax ignores ambient GITHUB_TOKEN. Opt in with auth.allow_github_token_env = true.
Now ship a two-branch stack end-to-end:
# 1. Stack two branches on trunk
st create auth-api
st create auth-ui
# 2. See the stack
st ls
# ◉ auth-ui 1↑
# ○ auth-api 1↑
# ○ main
# 3. Submit the whole stack as linked PRs
st ss
# 4. After the bottom PR merges on GitHub…
st update # sync trunk, restack this stack, update PRsPicked the wrong trunk? Run st trunk main or st init --trunk <branch> to reconfigure.
Next: Quick Start guide · Merge & cascade workflow
Spin up multiple AI agents on isolated branches, all tracked as normal stax branches:
st lane fix-auth-refresh "Fix the token refresh edge case from #142"
st lane stabilize-ci "Stabilize the 3 flaky tests in the checkout flow"
st lane api-docs "Update API docs for the /users endpoint"Each lane is a real Git worktree with normal stax metadata — it appears in st ls, participates in restack/sync/undo, and re-attaches via tmux any time. No hidden scratch directories, no lost work.
st wt # open the worktree dashboard
st wt rs # restack every lane at once when trunk moves
st ss # submit PRs for the ones that are ready→ Agent worktrees · Multi-worktree workflow
Merge from the bottom of the stack up to your current branch, with CI and readiness checks:
st merge # local cascade merge
st merge --when-ready # wait/poll until PRs are mergeable
st merge --ds # merge ancestors, rebase current branch
st merge --remote # merge remotely on GitHub while you keep working
st merge --all # merge the whole stack regardless of positionWhen a rebase stops on a conflict, st resolve sends only the conflicted text files to your configured AI agent, applies the result, and resumes the rebase automatically. If the AI returns invalid output, touches a non-conflicted file, or leaves extra conflicts behind, stax bails out and preserves the in-progress rebase so you can inspect or continue manually.
st resolve
st resolve --agent codex --model gpt-5.3-codexBefore each rebase, stax also runs a preflight repair that compares the
stored parent boundary against merge-base(parent, branch). When they diverge
sharply — the “my restack hit conflicts on files I never touched” case — stax
automatically uses the merge-base boundary for that rebase and prints a
one-line notice. Silence the notice with [restack] preflight_warn = false or
--quiet; disable the automatic correction with
[restack] preflight_auto_repair = false.
restack, submit, and reorder each snapshot branch state before they touch anything. Recovery is one command away.
st restack
st undo
st redoBare st launches a full-screen TUI for browsing stacks, inspecting branch summaries and cached patches, watching live CI hydrate, and running common ops without leaving the terminal.
st create --ai -a --yes # generate branch name + first commit message
st ss --ai --yes # generate PR titles/bodies during submit
st gen # interactive: PR body, PR title, or commit message (AI)
st generate --pr-body # non-interactive: refresh PR body from branch diff + context
st generate --pr-title # non-interactive: refresh PR title from branch diff
st generate --commit-msg # non-interactive: amend HEAD commit message with AI
st standup --ai # spoken-style daily engineering summary
st standup --ai --style slack # Slack-ready Yesterday/Today bulletsEach AI feature (generate, standup, resolve, lane) can use a different agent/model. st create --ai, st submit --ai, and st generate / st gen (PR body/title, commit message) share the generate setting. Configure with:
st config --set-ai→ PR templates & AI · Reporting
| Command | What it does |
|---|---|
st |
Launch interactive TUI |
st ls / st ll |
Show stack health and PR status (st ll adds PR URLs/details) |
st watch |
Live auto-refreshing stack status with CI and PR state (adaptive polling: 15s active CI → 60s open PRs → 120s idle) |
st watch --current |
Watch only the current stack |
st create <name> / st add <name> |
Create a branch stacked on current |
st create --ai -a --yes |
Generate branch name + first commit message |
st create <name> --below |
Insert a new branch below current, carrying tracked/untracked prepared changes with it |
st ss |
Submit the full stack, open/update linked PRs |
st merge |
Cascade-merge from bottom to current (--when-ready, --downstack-only/--ds, --remote, --all) |
st ci / st ci --oneline |
CI status — full per-check table, or one compact line per branch across the stack (multi-branch defaults to the roll-up) |
st ci -w --alert |
Watch CI until all checks finish, then play success/error sounds |
st ci -w --strict |
Watch CI but exit as soon as any check fails |
st rs / st rs --restack |
Sync trunk, clean merged branches, optionally rebase |
st update |
Sync trunk without merged-branch cleanup, restack current stack, then push/update PRs |
st update --force --yes --no-prompt |
Run update without sync or submit prompts |
st update --verbose |
Include detailed sync/restack/submit timing |
st restack |
Rebase current stack onto parents locally |
st cascade |
Restack + push + open/update PRs |
st split |
Split a branch into stacked branches (by commit or --hunk) |
st lane <name> "<task>" |
Spawn an AI agent on a new lane |
st wt |
Open the worktree dashboard |
st resolve |
AI-resolve an in-progress rebase conflict |
st create --ai |
Generate a branch name from local changes |
st gen / st generate |
AI: interactive picker, or --pr-body / --pr-title / --commit-msg |
st ss --ai |
Submit with AI-generated PR title/body suggestions |
st standup |
Summarize recent engineering activity |
st tmux status |
Print a tmux-formatted status string (branch, stack position, PR, CI) for status-right |
st tmux popup |
Open stax watch --current in a floating tmux panel |
st undo / st redo |
Recover / reapply risky operations |
st run <cmd> |
Run a command on each branch in the stack |
st doctor --fix |
Check repo/config health and apply safe local repairs after one confirmation |
st draft [branch] / st undraft [branch] |
Toggle a PR between draft and ready-for-review |
st pr / st pr body / st pr list / st issue list |
Open current PR · view/edit PR body · list PRs · list issues |
Full reference: docs/commands/core.md · docs/commands/reference.md
Benchmarked with hyperfine on this repo. Absolute times vary by repo and machine; the ratios do not.
| Benchmark | stax | vs Freephite | vs Graphite |
|---|---|---|---|
st ls |
baseline | 214.76× faster | 69.72× faster |
st rs (sync) |
baseline | 2.41× faster | — |
stax is wire-compatible with Freephite/Graphite for common stacked-branch workflows.
→ Full benchmarks · Compatibility notes
st config # open the config editor
st config --set-ai # pick AI agent + model
st config --reset-ai # clear saved AI pairing and re-promptConfig lives at ~/.config/stax/config.toml. When STAX_CONFIG_DIR is unset,
a repo-root stax.toml overlays only the values it sets:
[submit]
stack_links = "body" # "comment" | "body" | "both" | "off"
single_stack = "on" # "on" | "off" — when "off", skip stack-link sync while only one PR existsstax.tmux is a TPM-compatible plugin that puts your stack in the tmux status bar and adds keybindings for common actions:
- Live status bar — branch, stack position, PR state, CI state; auto-refreshes in the background
- Keybindings —
prefix + Spopup,prefix + ]/[up/down,prefix + M-ssync - Window auto-rename — tmux window title follows the current branch
Install via TPM:
set -g @plugin 'cesarferreira/stax.tmux'See the stax.tmux README for full setup and configuration options.
AI and editor integration guides:
Shared skill/instruction file used across agents: skills.md
st changelog can generate notes between refs, and st changelog find [query]
or st changelog --find [query] fuzzy-finds commits in the selected range.
Use --path to scope either mode to a subdirectory.
Windows notes — shell integration, worktrees, tmux
stax runs on Windows (x86_64) with prebuilt binaries on Releases. Most commands work identically, with these limitations:
- Shell integration is not available.
st setupsupports bash/zsh/fish only. On Windows:st wt c/st wt gocreate and navigate worktrees but cannot auto-cdthe parent shell. Manuallycdto the printed path.- The
swquick alias is not available. st wt rm(bare) cannot relocate the shell. Specify:st wt rm <name>.
- Worktree commands still work.
st wt c/go/ls/ll/cleanup/rm/prune/restackall function — only the shell-levelcdis missing. - tmux integration requires WSL or a Unix-like environment. The stax.tmux plugin is Unix-only.
Everything else — stacked branches, PRs, restack, sync, undo/redo, TUI, AI generation — works on Windows without limitation.
Before opening a PR, run:
make testTo cut a release, run:
make release # default minor bump
make release LEVEL=patch # patch bump
make release LEVEL=major # major bumpRelease automation now finalizes the next versioned entry in CHANGELOG.md from commits since the latest v* tag inside cargo release's pre-release hook, refreshes the compare links, and leaves a fresh Unreleased header for follow-up work. If there are no commits since the last tag, the release exits early instead of creating an empty changelog entry.
Project docs and architecture: docs/index.md. Contributor guidelines: AGENTS.md.
MIT © Cesar Ferreira

