Kindra is a CLI tool for managing stacked git branches. Its kin command automates the tedious parts of working with dependent branches, such as rebasing descendants after a commit or moving an entire stack of work to a new base.
-
Stacked Commits: Automatically rebase all descendant branches when you commit in the middle of a stack.
-
Stack-Aware Absorb: Distribute staged changes into the commits that introduced the touched lines (via the git-absorb engine), fold them, and restack descendants in one pass.
-
Atomic Stack Moves: Move a branch and all its descendants onto a new base branch in one pass using
--update-refs. -
Fork-Aware Reordering: Edit branch parent relationships in your
$EDITOR, including creating or preserving forks. -
Smart Sync: Rebase the current stack onto
main/masterin one pass using--update-refs, while skipping already-landed lower PRs. -
Auto-Restack: Automatically identify and repair "floating" branches that were based on an old version of the current branch (e.g., after an
amendorrebase). -
Interactive Navigation: Quickly hop between branches in your stack with
up,down, andtopcommands. -
Visual Branch Splitting: Assign branches to specific commits in a linear history using your favorite
$EDITOR. -
Atomic Pushes: Push all branches in your stack simultaneously with
force-with-leasesafety. -
Run Commands Across Stack: Execute shell commands on each branch in your stack with
kin run. -
PR Workflow Helpers: Create/update stack PRs with automatic flatten/push preflight, flatten stack PR bases to upstream, open PRs in your browser, edit PR metadata, inspect review/check status, export threaded review comments as markdown, and merge stack PRs with readiness checks — retargeting child PR bases on GitHub so they aren't orphaned by the merge, then (unless
--no-cascade) restacking children onto the updated trunk and deleting the merged branch locally and on the remote (--method squash|rebase|merge,--no-cascade,--no-delete).
Kindra can be installed directly from GitHub:
cargo install --git https://github.com/Pajn/kindra.git kindra --bin kinIf you already use cargo-binstall, the git-based install works there too:
cargo binstall --git https://github.com/Pajn/kindra.git kindraYou can also install it from source:
# Clone the repository
git clone https://github.com/Pajn/kindra.git
cd kindra
# Build and install
cargo install --path .Kindra uses cargo-release to keep the Cargo version, version bump commit, and Git tag in sync. The GitHub release workflow runs when a v* tag is pushed.
cargo install cargo-release
# Review the planned version bump, commit, tag, and push.
cargo release 0.3.0
# Perform the release after reviewing the dry run.
cargo release 0.3.0 --execute- Start a stack: Create several branches, each building on the previous one — with plain
git checkout -b, orkin commit -b <name>to fork a branch and commit onto it in one step (add--insertto splice it into the middle of an existing stack). - Make a change: Checkout a branch in the middle of the stack and run
kin commit. - Watch the magic: Kindra will automatically rebase all branches that depend on your change.
- Move the stack: Ready to target a different feature?
kin move --onto mainto relocate the entire stack. - Sync after merges: If lower PRs landed, run
kin syncto rebase the remaining stack onto latestmain. - Reorder the stack: Need to reshuffle or fork branches? Run
kin reorderand edit the parent map in your editor. - Repair broken stacks: Amended a commit and left dependent branches "floating"? Run
kin restackto fix them. - Manage PRs in stack:
kin prto create/update your PRs, automatically flattening mismatched PR bases and pushing firstkin pr --allto include PRs in the stack that are authored by other GitHub userskin pr --no-pushto skip that preflight and use the old create/update behaviorkin pr opento open a PR from the stackkin pr editto edit title/body/labels/reviewerskin pr flattento retarget all open stack PRs to the resolved upstream base branch on GitHubkin pr statusto inspect reviewers, unresolved comments, and failing/running checkskin pr reviewto render PR review threads as markdown, optionally write them to a file, or copy them via OSC 52kin pr mergeto merge a stack PR only when reviews/checks are ready, or clearly explain/prompt when GitHub would still allow an override
- Run across stack:
kin run -c "cargo test"to run tests on each branch in the stack. - Undo a mistake: Didn't like the result of a
sync,reorder,move,restack, orsplit? Runkin undoto restore the previous branch tips (andkin redoto reapply, orkin reflogto review recent operations).
For a full list of commands and detailed examples, see the CLI Reference.
kin reorder opens a file with one row per branch:
branch feature-c parent main
branch feature-a
branch feature-b
branch <name> parent <parent>sets the branch parent explicitly.branch <name>means "make the branch on the previous line the parent".- The first row must have an explicit parent, usually your upstream branch.
- Forks are created by repeating the same explicit parent on multiple rows.
Example fork:
branch feature-c parent main
branch feature-a parent feature-c
branch feature-b parent feature-c
Commands that need an upstream/base branch (for example sync, split, push, commit, and move) resolve it in this order:
-
Repository override in
.git/kindra.toml:upstream_branch = "branch-name"
-
git config init.defaultBranch -
Built-in defaults:
main,master,trunk -
Remote fallbacks:
origin/<branch>
Kindra now includes an opinionated kin wt workflow for managed git worktrees:
kin wt mainensures a stable trunk worktree exists.kin wt review [branch]creates or reuses a fixed review worktree and repoints it safely.kin wt temp [branch]creates or reuses a branch-scoped disposable worktree, andkin wt temp -b <new-branch> [start-point]creates a new branch in one.kin wt add [branch]creates (or reuses) a durable worktree for a branch in a sibling directory, or in<repo>/worktrees/{branch}when the repository has no parent directory, andkin wt add -b <new-branch> [start-point]creates a new branch in one. Unliketemp, added worktrees are never auto-cleaned.kin wt listshows every git worktree and its current state (role, or-for plain worktrees).kin wt path <target>prints just the worktree path for shell/editor integrations.kin wt cd <target>changes directory into a worktree (needs shell integration — see below).kin shell-init <bash|zsh|fish>(top-level) prints the shell snippet that enableskin wt cd.kin wt remove <target>removes a worktree (by role or branch) with confirmation by default.kin wt cleanupremoves merged Kindra-managed temp worktrees.
By default Kindra stores the role worktrees (main/review/temp) under:
.git/kindra-worktrees/
That keeps disposable working trees out of the repo root while still making them easy to find and clean up. Durable kin wt add worktrees instead default to a sibling directory (../<repo>-worktrees/{branch}), or to <repo>/worktrees/{branch} when the repository has no parent directory, so they're visible to editors and git status.
# Ensure a persistent trunk worktree exists
kin wt main
# Reuse a stable review workspace for the current branch
kin wt review
# Switch the review workspace to another branch
kin wt review feature/auth
# Create or reuse a temp worktree for a branch
kin wt temp feature/auth
# Create a new temp worktree branch from the current branch
kin wt temp -b feature/spike
# Create a new temp worktree branch from origin/main
kin wt temp -b hotfix/main origin/main
# Create a durable sibling worktree for a branch you want to keep checked out
kin wt add feature/auth
# Use the resolved path in shell tooling
cd "$(kin wt path review)"
# Or, with shell integration enabled, cd straight into a worktree
kin wt cd feature/auth
# Remove a single managed temp worktree
kin wt remove feature/auth
# Clean up merged temp worktrees
kin wt cleanupkin wt cd <target> moves your shell into a worktree. Because a CLI process can't change its parent shell's directory, this needs a one-time wrapper (from the top-level kin shell-init) in your shell config:
# bash / zsh
eval "$(kin shell-init zsh)"# fish
kin shell-init fish | sourceThe wrapper intercepts kin wt cd and forwards everything else straight to kin. Without it, kin wt cd just prints the path (and tells you how to enable the integration).
kin shell-init also registers Kindra's shell completions by default, so that one line sets up both. Pass --no-completions if you install completions separately.
Managed worktrees use repo-local config in .git/kindra.toml:
[worktrees]
trunk = "main"
# Default location for `kin wt add` ({branch} required; sibling dir by default,
# falling back to <repo>/worktrees when the repo has no parent directory).
add_path_template = "../myrepo-worktrees/{branch}"
[worktrees.hooks]
on_create = []
on_checkout = []
on_remove = []
[worktrees.main]
path = ".git/kindra-worktrees/main"
[worktrees.review]
path = ".git/kindra-worktrees/review"
[worktrees.temp]
path_template = ".git/kindra-worktrees/temp/{branch}"
delete_merged = trueNotes:
mainis pinned to the configured trunk branch.reviewreuses a fixed path and refuses to discard local changes unless you confirm or pass--force.addworktrees default toadd_path_template; by default that is a sibling directory, or<repo>/worktrees/{branch}when the repo has no parent directory. Pass--pathto override. Unlike the role paths it isn't required to live under the managed root.cleanuponly targets Kindra-managedtempworktrees, nevermain,review, or plain/added worktrees.kin wt pathis the script-friendly command: it prints only the resolved path on success.- Use
branch:<name>withkin wt pathorkin wt removeto target a branch literally namedmainorreview. - Hooks run in the worktree directory and stop the action if they fail.
kin wt addruns only the global[worktrees.hooks]; role worktrees run global plus role-specific hooks.
kin restack bounds floating-branch discovery by default so very deep repositories do not pay for an unbounded first-parent scan.
Resolution order:
- CLI override:
kin restack --history-limit <n> - Repository config in
.git/kindra.toml - Global config in the standard platform config directory as
kindra/config.toml - Built-in default:
100
Use 0 to disable the bound and scan the full first-parent history.
Example repository config:
[restack]
history_limit = 250Commands that start a Git rebase (commit, move, sync, and restack) default to --no-autostash so dirty tracked changes do not get hidden implicitly.
Resolution order:
- CLI override:
--autostashor--no-autostash - Repository config in
.git/kindra.toml - Global config in the standard platform config directory as
kindra/config.toml - Built-in default:
false
Example config:
[rebase]
autostash = trueRun the permanent Criterion benchmarks for stack navigation (checkout top, co up, co down) across two repository shapes:
- 5,000 commits on
main+ 10,000 noise branches - 50,000 commits on
main+ 1,000 noise branches
cargo bench --bench checkout_topTraditional git workflows often involve large, monolithic Pull Requests or manual, error-prone rebasing when trying to keep multiple small, dependent PRs in sync. Kindra treats your branches as a stack, allowing you to focus on small, reviewable increments of code while it handles the plumbing.