Skip to content

pallaoro/ship-worktree

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ship-worktree

Per-task git worktrees, automatic tmux session-per-project, never clobber another session.

ship feature-x     # creates worktree off latest origin/main, opens it in tmux
ships              # list every worktree of the current repo
land               # remove the current worktree (branch + tmux session too)

Why

If you work on multiple branches in parallel — especially with AI coding agents running long-running tasks — sharing one git checkout across sessions is a foot-gun. A git checkout or git pull in one terminal silently yanks state out from under another, and gh pr merge --delete-branch can fail because some other worktree has main checked out.

ship-worktree solves that by:

  • One worktree per task. Each ship NAME creates a fresh worktree at <repo>/.worktrees/NAME branched from the latest origin/main (fetched fresh every time — fails loudly if the fetch fails, so you never branch off stale state).
  • Per-project tmux sessions. Session names are <repo>-<NAME>, so ship claude in acme and ship claude in widgets open two independent sessions.
  • Safe cleanup. land removes the worktree, deletes the branch, kills the tmux session. Run with no args inside a worktree to clean up the one you're in.

Install

Manual

git clone https://github.com/pallaoro/ship-worktree.git ~/.ship-worktree
echo 'export PATH="$HOME/.ship-worktree/bin:$PATH"' >> ~/.zshrc
exec zsh

Homebrew

Not yet published. Coming soon.

Usage

Command What it does
ship Create or attach worktree claude
ship NAME Create or attach worktree NAME
ships List every worktree (git worktree list)
land Remove the current worktree (if you're in one) — otherwise prompt
land NAME Remove worktree NAME

When ship finds the worktree directory already exists (e.g. previous session wasn't landed cleanly), it offers:

  • use it — attach to whatever branch is currently checked out there
  • replace — wipe the worktree + branch, recreate fresh off origin/main
  • cancel

Configuration

All env vars are optional. Set them in your shell init.

Variable Default Meaning
SHIP_SPAWN bash Command to launch inside the new tmux session. Set to claude (or any other shell-agent CLI) to drop straight into it.
SHIP_BASE_BRANCH main Branch new worktrees are forked from.
SHIP_REMOTE origin Remote ship fetches the base branch from.
SHIP_WORKTREE_DIR .worktrees Path (relative to the repo root) where worktrees are created.

Example: drop straight into Claude Code, store worktrees under .claude/worktrees:

export SHIP_SPAWN=claude
export SHIP_WORKTREE_DIR=.claude/worktrees

Requirements

  • git (≥ 2.20 for git worktree ergonomics)
  • tmux
  • bash ≥ 4

How merge should pair with ship

Most "merge this branch" flows do something like:

git checkout main
git merge --ff feature
git push

That's the operation that silently yanks state out from another worktree session if they happen to share a working tree. With ship, the recommended merge flow is GitHub-side only:

# inside the feature worktree
git push -u origin HEAD
gh pr create --fill
gh pr merge --squash      # NO --delete-branch — gh tries to switch your local
                          # checkout back to main, which fails when main is
                          # checked out in another worktree.
land                      # then clean up locally

That keeps every concurrent ship session safe.

License

MIT — see LICENSE.

About

Per-task git worktrees, automatic tmux session-per-project, never clobber another session.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages