stax 0.2.1

Fast stacked Git branches and PRs
stax-0.2.1 is not a library.
Visit the last successful build: stax-0.26.0

Why stax?

  • Fast - Native Rust binary with libgit2, runs in ~21ms
  • Modern UX - Clear error messages with actionable suggestions
  • Visual stack view - Beautiful tree rendering with colors and PR status
  • Flexible - Force flags, detailed logs, and smart defaults
  • Compatible - Uses same metadata format as freephite (migrate instantly)

Install

Homebrew (macOS/Linux)

brew tap cesarferreira/tap
brew install stax

Cargo binstall (prebuilt binaries)

cargo binstall stax

Cargo (build from source)

cargo install --git https://github.com/cesarferreira/stax

From source

git clone https://github.com/cesarferreira/stax
cd stax
cargo install --path .

Quick Start

# Authenticate with GitHub (for PR creation)
stax auth

# Create your first stacked branch
stax bc feat/my-feature

# Make changes, commit, then create another branch on top
stax bc feat/another-feature

# View your stack
stax s

# Submit all branches as PRs
stax ss

# When parent branch changes, sync and restack
stax rs --restack

Initialization

On first run, stax will initialize the repository by selecting a trunk branch (usually main or master). In non-interactive mode, it auto-detects the trunk if possible.

Commands

Shortcuts (freephite compatible)

Command Description
stax ss Submit stack - push branches and create/update PRs
stax rs Repo sync - pull trunk, delete merged branches
stax rs --restack Repo sync + restack branches
stax bco Branch checkout - interactive branch picker
stax create <name> Create a new stacked branch (alias: c, bc)
stax create -m "msg" Create branch, stage all, and commit with message
stax create -a Create branch and stage all changes (like git commit -a)
stax create -am "msg" Create branch, stage all, and commit (like git commit -am)
stax m Modify - stage all changes and amend to current commit
stax t Switch to trunk branch
stax pr Open the current branch's PR in browser
stax u / stax bu Move up the stack (to child branch)
stax u 2 Move up 2 branches
stax d / stax bd Move down the stack (to parent branch)
stax d 3 Move down 3 branches
stax top Move to the tip of the stack
stax bottom Move to the base of the stack (above trunk)

Full Commands

Command Alias Description
stax status s, ls Show the current stack (simple view)
stax log l Show stack with commits and PR info
stax create c, bc Create a new stacked branch
stax diff Show diffs for each branch vs parent + aggregate stack diff
stax range-diff Show range-diff for branches that need restack
stax sync rs Pull trunk, delete merged branches
stax sync --restack Also restack after syncing
stax restack Rebase current branch onto parent
stax restack --all Restack all branches that need it
stax submit ss Push and create/update PRs (interactive prompts)
stax submit --draft Create PRs as drafts
stax submit --no-pr Just push, skip PR creation
stax checkout [branch] co, bco Checkout a branch (interactive if no arg)
stax trunk t Switch to trunk branch
stax up [n] u Move up n branches (default: 1)
stax down [n] d Move down n branches (default: 1)
stax top Move to the tip of the stack
stax bottom Move to the base of the stack (above trunk)
stax continue cont Continue after resolving conflicts
stax modify m Stage all changes and amend to current commit
stax pr Open the current branch's PR in browser
stax auth Set GitHub personal access token
stax config Show config file path and contents
stax doctor Check stax configuration and repo health

Notable Flags and Behavior

Output and scripting

  • stax status --json --compact --stack <branch> --all --quiet
  • stax log --json --compact --stack <branch> --all --quiet
  • Status/log output includes PR state, ahead/behind counts, and CI status (cached with 5-min TTL).

Submit

  • Interactive prompts for new PRs: edit title, edit body in $EDITOR, choose draft or publish.
  • Prefills PR title/body from branch names, commit messages, and PR templates.
  • stax submit --reviewers alice,bob --labels bug --assignees alice --yes --no-prompt
  • Updates a single "stack summary" comment with PR links.
  • Prints PR URLs when done; use stax pr to open in browser.

Sync/Restack

  • Detects dirty working tree and offers to stash before restack/sync.
  • stax sync --safe avoids reset --hard when updating trunk.
  • stax sync --verbose shows detailed git output for debugging.
  • stax sync --continue and stax restack --continue resume after conflicts.

Branching and navigation

  • stax create -am "message" stages all changes and commits, like git commit -am.
  • stax create -a stages all changes without committing (like git add -A).
  • stax create --from <branch> chooses a base branch (defaults to current).
  • stax create --prefix feature -m "auth" overrides the configured prefix for this branch.
  • stax branch reparent --branch <name> --parent <name> reattach branches.
  • Parent selection is interactive when ambiguous; warnings when parent is missing on remote.
  • stax checkout --trunk, --parent, --child <n> quick jumps; picker shows commits/PR info/restack status.

Diffs

  • stax diff shows each branch vs parent plus an aggregate stack diff.
  • stax range-diff highlights restack effects.

Doctor

  • stax doctor checks repo health, remotes, and provider configuration.

Branch Commands

Command Alias Description
stax branch create <name> b c Create a new stacked branch
stax branch checkout b co Interactive branch checkout
stax branch track Track an existing branch
stax branch reparent Change the parent of a tracked branch
stax branch delete b d Delete a branch
stax branch fold b f Fold current branch into its parent
stax branch squash b sq Squash commits on current branch
stax branch up b u Move up the stack (to child branch)
stax branch down Move down the stack (to parent branch)

Upstack/Downstack

Command Alias Description
stax upstack restack us restack Restack all branches above current
stax downstack get ds get Show branches below current

Example Workflow

# Start on main
git checkout main

# Create a stacked branch for your feature (stages + commits if -m provided)
stax bc -m "Add auth API"

# Create another branch on top
stax bc -m "Add auth UI"

# Need to make changes? Amend them to the current commit
echo "fix" >> auth.rs
stax m                    # stages all + amends to current commit
stax m -m "new message"   # ...or with a new commit message

# View your stack
stax s
# │ ◉  feat/auth-ui   ← you are here
# │ ○  feat/auth-api
# ○─┘  main

# Navigate the stack
stax d       # move down to feat/auth-api (or: stax bd)
stax u       # move back up to feat/auth-ui (or: stax bu)
stax u 2     # move up 2 branches
stax top     # jump to the tip of the stack
stax bottom  # jump to the base (first branch above trunk)
stax t       # jump to trunk

# Submit all PRs
stax ss
# Submitting 2 branch(es) to owner/repo...
#   Pushing feat/auth-api... ✓
#   Pushing feat/auth-ui... ✓
# Creating/updating PRs...
#   Creating PR for feat/auth-api... ✓ #123
#   Creating PR for feat/auth-ui... ✓ #124

# If main gets updated, sync and restack
stax rs --restack

How It Works

stax stores stack metadata in Git refs (refs/branch-metadata/<branch>), the same format as freephite. This means:

  • No external files or databases
  • Metadata travels with your repo
  • You can use both stax and fp on the same repo

Each branch tracks:

  • Parent branch name
  • Parent branch revision (to detect when restack is needed)
  • PR info (number, state)

Configuration

Config is stored at ~/.config/stax/config.toml:

[branch]
prefix = "cesar/"      # Auto-prefix new branches (e.g., "my-feature" → "cesar/my-feature")
date = false           # Add date to branch names (e.g., "2024-01-15-my-feature")
replacement = "-"      # Character to replace spaces and special chars

[remote]
name = "origin"        # Remote name to use
provider = "github"    # github, gitlab, gitea
base_url = "https://github.com" # Web base URL
api_base_url = "https://api.github.com" # Optional (GitHub Enterprise)

View your config with stax config.

GitHub Authentication

GitHub token is stored separately from config (not in dotfiles).

Priority order:

  1. STAX_GITHUB_TOKEN env var (highest)
  2. GITHUB_TOKEN env var
  3. ~/.config/stax/.credentials file (lowest)
# Option 1: stax-specific env var (recommended)
export STAX_GITHUB_TOKEN="ghp_xxxx"

# Option 2: Generic GitHub token
export GITHUB_TOKEN="ghp_xxxx"

# Option 3: Use stax auth command (saves to credentials file)
stax auth

Migrating from freephite

stax uses the same metadata format as freephite, so migration is instant - just install stax and your existing stacks work:

# Your existing fp stacks just work
stax s  # shows your stack
stax rs # syncs repo
stax ss # submits PRs

Benchmarks

Measured with hyperfine --shell=none on a 10-branch stack:

Command Time
stax ls 21ms
fp ls 363ms
$ hyperfine 'stax ls' 'fp ls' --shell=none
Benchmark 1: stax ls
  Time (mean ± σ):      21.5 ms ±   2.0 ms
Benchmark 2: fp ls
  Time (mean ± σ):     362.7 ms ±  16.1 ms

Summary
  stax ls ran 16.87 ± 1.71 times faster than fp ls

License

MIT