| Crates.io | stax |
| lib.rs | stax |
| version | 0.10.4 |
| created_at | 2025-12-25 14:38:09.666163+00 |
| updated_at | 2026-01-21 19:47:50.548882+00 |
| description | Fast stacked Git branches and PRs |
| homepage | |
| repository | https://github.com/cesarferreira/stax |
| max_upload_size | |
| id | 2004608 |
| size | 4,364,901 |
Instead of one massive PR with 50 files, stacked branches let you split work into small, reviewable pieces that build on each other (and visualize it as a tree).
Why this is great:
git blame)◉ feature/auth-ui 1↑
○ feature/auth-api 1↑
○ main
Each branch is a focused PR. Reviewers see small diffs. You ship faster.
stax is a modern stacked-branch workflow that keeps PRs small, rebases safe, and the whole stack easy to reason about.
stax ls on a 10-branch stack)stax undo / stax redo# Homebrew (macOS/Linux)
brew tap cesarferreira/tap && brew install stax
# Or with cargo binstall
cargo binstall stax
# 1. Authenticate with GitHub
stax auth
# 2. Create stacked branches
stax create auth-api # First branch off main
stax create auth-ui # Second branch, stacked on first
# 3. View your stack
stax ls
# ◉ auth-ui 1↑ ← you are here
# ○ auth-api 1↑
# ○ main
# 4. Submit PRs for the whole stack
stax ss
# Creating PR for auth-api... ✓ #12 (targets main)
# Creating PR for auth-ui... ✓ #13 (targets auth-api)
# 5. After reviews, sync and rebase
stax rs --restack
Run stax create without arguments to launch the guided wizard:
$ stax create
╭─ Create Stacked Branch ─────────────────────────────╮
│ Parent: feature/auth (current branch) │
╰─────────────────────────────────────────────────────╯
? Branch name: auth-validation
? What to include:
● Stage all changes (3 files modified)
○ Empty branch (no changes)
? Commit message (Enter to skip): Validate auth tokens
✓ Created cesar/auth-validation
→ Stacked on feature/auth
Run stax with no arguments to launch the interactive terminal UI:
stax
TUI Features:
o then Shift+↑/↓| Key | Action |
|---|---|
↑/↓ |
Navigate branches |
Enter |
Checkout branch |
r |
Restack selected branch |
s |
Submit stack |
o |
Enter reorder mode (reparent branches) |
n |
Create new branch |
d |
Delete branch |
? |
Show all keybindings |
Rearrange branches within your stack without manually running reparent commands:
o to enter reorder modeShift+↑/↓ to move the branch up or down in the stackEnter to apply changes and automatically restackSplit a branch with many commits into multiple stacked branches:
stax split
How it works:
stax split on a branch with multiple commitsj/k or arrowss to mark a split point and enter a branch nameEnter to execute - new branches are created with proper metadata| Key | Action |
|---|---|
j/k or ↑/↓ |
Navigate commits |
s |
Mark split point at cursor (enter branch name) |
d |
Remove split point at cursor |
Enter |
Execute split |
? |
Show help |
q/Esc |
Cancel and quit |
Example: You have a branch with commits A→B→C→D→E. Mark splits after B ("part1") and D ("part2"):
Before: After:
main main
└─ my-feature (A-E) └─ part1 (A, B)
└─ part2 (C, D)
└─ my-feature (E)
Split uses the transaction system, so you can stax undo if needed.
| Command | What it does |
|---|---|
stax |
Launch interactive TUI |
stax ls |
Show your stack with PR status and what needs rebasing |
stax create <name> |
Create a new branch stacked on current |
stax ss |
Submit stack - push all branches and create/update PRs |
stax merge |
Merge PRs from bottom of stack up to current branch |
stax rs |
Repo sync - pull trunk, clean up merged branches |
stax rs --restack |
Sync and rebase all branches onto updated trunk |
stax co |
Interactive branch checkout with fuzzy search |
stax u / stax d |
Move up/down the stack |
stax m |
Modify - stage all changes and amend current commit |
stax pr |
Open current branch's PR in browser |
stax copy |
Copy branch name to clipboard |
stax copy --pr |
Copy PR URL to clipboard |
stax standup |
Show your recent activity for standups |
stax undo |
Undo last operation (restack, submit, etc.) |
Struggling to remember what you worked on yesterday? Run stax standup to get a quick summary of your recent activity:

Shows your merged PRs, opened PRs, recent pushes, and anything that needs attention - perfect for daily standups.
stax standup # Last 24 hours (default)
stax standup --hours 48 # Look back further
stax standup --json # For scripting
Stax makes rebasing and force-pushing safe with automatic backups and one-command recovery:
# Make a mistake while restacking? No problem.
stax restack
# ✗ conflict in feature/auth
# Your repo is recoverable via: stax undo
# Instantly restore to before the restack
stax undo
# ✓ Undone! Restored 3 branch(es).
Every potentially-destructive operation (restack, submit, sync --restack, TUI reorder) is transactional:
refs/stax/backups/<op-id>/<branch> pointing to original commits.git/stax/ops/<op-id>.jsonIf anything goes wrong, stax undo reads the receipt and restores all branches to their exact prior state.
| Command | Description |
|---|---|
stax undo |
Undo the last operation |
stax undo <op-id> |
Undo a specific operation |
stax redo |
Redo (re-apply) the last undone operation |
Flags:
--yes - Auto-approve prompts (useful for scripts)--no-push - Only restore local branches, don't touch remoteIf the undone operation had force-pushed branches, stax will prompt:
stax undo
# ✓ Restored 2 local branch(es)
# This operation force-pushed 2 branch(es) to remote.
# Force-push to restore remote branches too? [y/N]
Use --yes to auto-approve or --no-push to skip remote restoration.
You're building a payments feature. Instead of one 2000-line PR:
# Start the foundation
stax create payments-models
# ... write database models, commit ...
# Stack the API layer on top
stax create payments-api
# ... write API endpoints, commit ...
# Stack the UI on top of that
stax create payments-ui
# ... write React components, commit ...
# View your stack
stax ls
# ◉ payments-ui 1↑ ← you are here
# ○ payments-api 1↑
# ○ payments-models 1↑
# ○ main
# Submit all 3 as separate PRs (each targeting its parent)
stax ss
# Creating PR for payments-models... ✓ #101 (targets main)
# Creating PR for payments-api... ✓ #102 (targets payments-models)
# Creating PR for payments-ui... ✓ #103 (targets payments-api)
Reviewers can now review 3 small PRs instead of one giant one. When payments-models is approved and merged:
stax rs --restack
# ✓ Pulled latest main
# ✓ Cleaned up payments-models (merged)
# ✓ Rebased payments-api onto main
# ✓ Rebased payments-ui onto payments-api
# ✓ Updated PR #102 to target main
Merge your entire stack with one command! stax merge intelligently merges PRs from the bottom of your stack up to your current branch, handling rebases and PR updates automatically.
Stack: main ← PR-A ← PR-B ← PR-C ← PR-D
Position │ What gets merged
────────────────┼─────────────────────────────
On PR-A │ Just PR-A (1 PR)
On PR-B │ PR-A, then PR-B (2 PRs)
On PR-C │ PR-A → PR-B → PR-C (3 PRs)
On PR-D (top) │ Entire stack (4 PRs)
The merge scope depends on your current branch:
# View your stack
stax ls
# ◉ payments-ui 1↑ ← you are here
# ○ payments-api 1↑
# ○ payments-models 1↑
# ○ main
# Merge all 3 PRs into main
stax merge
You'll see an interactive preview before merging:
╭──────────────────────────────────────────────────────╮
│ Stack Merge │
╰──────────────────────────────────────────────────────╯
You are on: payments-ui (PR #103)
This will merge 3 PRs from bottom → current:
┌─────────────────────────────────────────────────┐
│ 1. payments-models (#101) ✓ Ready │
│ ├─ CI: ✓ passed │
│ ├─ Reviews: ✓ 2/2 approved │
│ └─ Merges into: main │
├─────────────────────────────────────────────────┤
│ 2. payments-api (#102) ✓ Ready │
│ ├─ CI: ✓ passed │
│ ├─ Reviews: ✓ 1/1 approved │
│ └─ Merges into: main (after rebase) │
├─────────────────────────────────────────────────┤
│ 3. payments-ui (#103) ✓ Ready │ ← you are here
│ ├─ CI: ✓ passed │
│ ├─ Reviews: ✓ 1/1 approved │
│ └─ Merges into: main (after rebase) │
└─────────────────────────────────────────────────┘
Merge method: squash (change with --method)
? Proceed with merge? [y/N]
For each PR in the stack (bottom to top):
--no-wait to skip)If anything fails (CI, conflicts, permissions), the merge stops safely. Already-merged PRs remain merged, and you can fix the issue and run stax merge again to continue.
# Merge with preview only (no actual merge)
stax merge --dry-run
# Merge entire stack regardless of current position
stax merge --all
# Choose merge strategy
stax merge --method squash # (default) Squash and merge
stax merge --method merge # Create merge commit
stax merge --method rebase # Rebase and merge
# Skip CI polling (fail if not ready)
stax merge --no-wait
# Keep branches after merge (don't delete)
stax merge --no-delete
# Set custom CI timeout (default: 30 minutes)
stax merge --timeout 60
# Skip confirmation prompt
stax merge --yes
You can merge just part of your stack by checking out a middle branch:
# Stack: main ← auth ← auth-api ← auth-ui ← auth-tests
stax checkout auth-api
# This merges only: auth, auth-api (not auth-ui or auth-tests)
stax merge
# Remaining branches (auth-ui, auth-tests) are rebased onto main
# Run stax merge again later to merge those too
Already have open PRs on GitHub that aren't tracked by stax? Import them all at once:
stax branch track --all-prs
This command:
Perfect for onboarding an existing repository or after cloning a fresh copy.
You can have multiple independent stacks at once:
# You're working on auth...
stax create auth
stax create auth-login
stax create auth-validation
# Teammate needs urgent bugfix reviewed - start a new stack
stax co main # or: stax t
stax create hotfix-payment
# View everything
stax ls
# ○ auth-validation 1↑
# ○ auth-login 1↑
# ○ auth 1↑
# │ ◉ hotfix-payment 1↑ ← you are here
# ○─┘ main
| Command | What it does |
|---|---|
stax u |
Move up to child branch |
stax d |
Move down to parent branch |
stax u 3 |
Move up 3 branches |
stax top |
Jump to tip of current stack |
stax bottom |
Jump to base of stack (first branch above trunk) |
stax t |
Jump to trunk (main/master) |
stax prev |
Toggle to previous branch (like git checkout -) |
stax co |
Interactive picker with fuzzy search |
○ feature/validation 1↑
◉ feature/auth 1↓ 2↑ ⟳
│ ○ ☁ feature/payments PR #42
○─┘ ☁ main
| Symbol | Meaning |
|---|---|
◉ |
Current branch |
○ |
Other branch |
☁ |
Has remote tracking |
1↑ |
1 commit ahead of parent |
1↓ |
1 commit behind parent |
⟳ |
Needs restacking (parent changed) |
PR #42 |
Has open PR |
stax config # Show config path and current settings
Config at ~/.config/stax/config.toml:
[branch]
prefix = "cesar/" # Auto-prefix branches: "auth" → "cesar/auth"
[remote]
name = "origin"
provider = "github" # github, gitlab, gitea
[ui]
tips = true # Show contextual suggestions (default: true)
stax looks for a GitHub token in the following order (first found wins):
STAX_GITHUB_TOKEN environment variableGITHUB_TOKEN environment variable~/.config/stax/.credentials)# Option 1: stax-specific env var (highest priority)
export STAX_GITHUB_TOKEN="ghp_xxxx"
# Option 2: Standard GitHub env var (works with other tools too)
export GITHUB_TOKEN="ghp_xxxx"
# Option 3: Interactive setup (saves to credentials file)
stax auth
The credentials file is created with 600 permissions (read/write for owner only).
Teach Claude Code how to use stax by installing the skills file:
# Create skills directory if it doesn't exist
mkdir -p ~/.claude/skills
# Download the stax skills file
curl -o ~/.claude/skills/stax.md https://raw.githubusercontent.com/cesarferreira/stax/main/skills.md
This enables Claude Code to help you with stax workflows, create stacked branches, submit PRs, and more.
stax uses the same metadata format as freephite and supports similar commands:
| freephite | stax | graphite | stax |
|---|---|---|---|
fp ss |
stax ss |
gt submit |
stax submit |
fp rs |
stax rs |
gt sync |
stax sync |
fp bc |
stax bc |
gt create |
stax create |
fp bco |
stax bco |
gt checkout |
stax co |
fp bu |
stax bu |
gt up |
stax u |
fp bd |
stax bd |
gt down |
stax d |
fp ls |
stax ls |
gt log |
stax log |
Migration is instant - just install stax and your existing stacks work.
stax automatically discovers PR templates in your repository:
If you have one template at .github/PULL_REQUEST_TEMPLATE.md, stax uses it automatically:
stax submit # Auto-uses template, shows "Edit body?" prompt
Place templates in .github/PULL_REQUEST_TEMPLATE/ directory:
.github/
└── PULL_REQUEST_TEMPLATE/
├── feature.md
├── bugfix.md
└── docs.md
stax shows an interactive fuzzy-search picker:
stax submit
# ? Select PR template
# > No template
# bugfix
# feature
# docs
--template <name>: Skip picker, use specific template--no-template: Don't use any template--edit: Always open $EDITOR for body (regardless of template)stax submit --template bugfix # Use bugfix.md directly
stax submit --no-template # Empty body
stax submit --edit # Force editor open
| Command | Alias | Description |
|---|---|---|
stax status |
s, ls |
Show stack (simple view) |
stax log |
l |
Show stack with commits and PR info |
stax submit |
ss |
Push and create/update PRs |
stax merge |
Merge PRs from bottom of stack to current | |
stax sync |
rs |
Pull trunk, delete merged branches |
stax restack |
Rebase current branch onto parent | |
stax diff |
Show diffs for each branch vs parent | |
stax range-diff |
Show range-diff for branches needing restack |
| Command | Alias | Description |
|---|---|---|
stax create <name> |
c, bc |
Create stacked branch |
stax checkout |
co, bco |
Interactive branch picker |
stax modify |
m |
Stage all + amend current commit |
stax rename |
b r |
Rename branch and optionally edit commit message |
stax branch track |
Track an existing branch | |
stax branch track --all-prs |
Track all your open PRs | |
stax branch reparent |
Change parent of a branch | |
stax branch delete |
Delete a branch | |
stax branch fold |
Fold branch into parent | |
stax branch squash |
Squash commits on branch |
| Command | Alias | Description |
|---|---|---|
stax up [n] |
u, bu |
Move up n branches |
stax down [n] |
d, bd |
Move down n branches |
stax top |
Move to stack tip | |
stax bottom |
Move to stack base | |
stax trunk |
t |
Switch to trunk |
stax prev |
p |
Toggle to previous branch |
| Command | Description |
|---|---|
stax |
Launch interactive TUI |
stax split |
Interactive TUI to split branch into multiple stacked branches |
| Command | Description |
|---|---|
stax undo |
Undo last operation (restack, submit, etc.) |
stax undo <op-id> |
Undo a specific operation by ID |
stax redo |
Re-apply the last undone operation |
| Command | Description |
|---|---|
stax auth |
Set GitHub token |
stax config |
Show configuration |
stax doctor |
Check repo health |
stax continue |
Continue after resolving conflicts |
stax pr |
Open PR in browser |
stax ci |
Show CI status for branches in current stack |
stax ci --all |
Show CI status for all tracked branches |
stax ci --watch |
Watch CI until completion (polls every 15s, records history) |
stax ci --watch --interval 30 |
Watch with custom polling interval in seconds |
stax ci --json |
Output CI status as JSON |
stax copy |
Copy branch name to clipboard |
stax copy --pr |
Copy PR URL to clipboard |
stax comments |
Show PR comments with rendered markdown |
stax comments --plain |
Show PR comments as raw markdown |
stax standup |
Show your recent activity for standups |
stax standup --hours 48 |
Look back 48 hours instead of default 24 |
stax standup --json |
Output activity as JSON for scripting |
stax create -m "msg" - Create branch with commit messagestax create -a - Stage all changesstax create -am "msg" - Stage all and commitstax rename new-name - Rename current branchstax rename -e - Rename and edit commit messagestax submit --draft - Create PRs as draftsstax submit --yes - Auto-approve promptsstax submit --no-prompt - Use defaults, skip interactive promptsstax submit --template <name> - Use specific template by name (skip picker)stax submit --no-template - Skip template selection (no template)stax submit --edit - Always open editor for PR bodystax submit --reviewers alice,bob - Add reviewersstax submit --labels bug,urgent - Add labelsstax submit --assignees alice - Assign usersstax merge --all - Merge entire stackstax merge --method squash - Choose merge method (squash/merge/rebase)stax merge --dry-run - Preview merge without executingstax merge --no-wait - Don't wait for CI, fail if not readystax sync --restack - Sync and rebase all branchesstax status --json - Output as JSONstax undo --yes - Undo without promptsstax undo --no-push - Undo locally only, skip remoteCI/Automation example:
stax submit --draft --yes --no-prompt
stax merge --yes --method squash
| Command | stax | freephite | graphite |
|---|---|---|---|
ls (10-branch stack) |
22.8ms | 369.5ms | 209.1ms |
Raw hyperfine results:
➜ hyperfine 'stax ls' 'fp ls' 'gt ls' --warmup 3
Benchmark 1: stax ls
Time (mean ± σ): 22.8 ms ± 1.0 ms [User: 9.0 ms, System: 11.3 ms]
Range (min … max): 21.1 ms … 26.9 ms 112 runs
Benchmark 2: fp ls
Time (mean ± σ): 369.5 ms ± 7.0 ms [User: 268.8 ms, System: 184.2 ms]
Range (min … max): 360.7 ms … 380.4 ms 10 runs
Benchmark 3: gt ls
Time (mean ± σ): 209.1 ms ± 2.8 ms [User: 152.5 ms, System: 52.6 ms]
Range (min … max): 205.9 ms … 215.7 ms 13 runs
Summary
stax ls ran
9.18 ± 0.43 times faster than gt ls
16.23 ± 0.79 times faster than fp ls
MIT