willow

module
v0.6.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 19, 2026 License: MIT

README

willow logo

willow

willow

A git worktree manager built for AI agent workflows.

GitHub release CI License

Spin up isolated worktrees for Claude Code sessions.
Switch between them instantly with fzf.
See which agents are busy, waiting, or idle.


demo

Why willow?

Running multiple Claude Code sessions on the same repo means constant context-switching, stashing, and branch juggling. Willow fixes this by giving every task its own isolated directory via git worktrees, then adding fzf-based switching and live agent status tracking on top.

~/.willow/
├── repos/
│   └── myrepo.git/              # bare clone (shared git database)
├── worktrees/
│   └── myrepo/
│       ├── main/                 # each branch = isolated directory
│       ├── auth-refactor/        # Claude Code running here
│       └── payments/             # another agent running here
└── status/
    └── myrepo/
        ├── auth-refactor/
        │   └── <session_id>.json   # {"status": "BUSY", ...}
        └── payments/
            └── <session_id>.json   # {"status": "WAIT", ...}

Install

Homebrew

brew install iamrajjoshi/tap/willow

From source

go install github.com/iamrajjoshi/willow/cmd/willow@latest

Requirements

  • git
  • fzf — for ww sw and ww rm interactive picker

Setup

1. Shell integration

# Add to .bashrc / .zshrc
eval "$(willow shell-init)"

# fish
willow shell-init | source

This gives you:

Command Description
ww <cmd> Alias for willow
ww sw fzf worktree switcher (cd's into selection)
wwn <branch> Create worktree + cd into it
www cd to ~/.willow/worktrees/

Optional: Set terminal tab title to the current worktree name:

eval "$(willow shell-init --tab-title)"

2. Claude Code status tracking (optional)

ww cc-setup

Installs hooks into ~/.claude/settings.json that write per-session agent status (BUSY / DONE / WAIT / IDLE) to ~/.willow/status/. Supports multiple Claude sessions per worktree. This powers the status column in ww ls, ww sw, ww status, and ww dashboard.

Quick start

# Clone a repo (one-time)
ww clone git@github.com:org/myrepo.git

# Create a worktree and cd into it
wwn auth-refactor

# Start Claude Code
claude

# In another terminal — create a second worktree
wwn payments-fix
claude

# Switch between worktrees (fzf picker with agent status)
ww sw

# Check on all agents
ww status

# Clean up when done
ww rm auth-refactor

Commands

ww clone <url> [name]

Bare-clone a repo and create an initial worktree on the default branch. Required entry point.

ww clone git@github.com:org/repo.git
ww clone git@github.com:org/repo.git myrepo    # custom name
ww clone git@github.com:org/repo.git --force    # re-clone from scratch

ww new <branch> [flags]

Create a new worktree with a new branch.

ww new feature/auth                    # create worktree
ww new feature/auth -b develop         # fork from specific branch
ww new -e existing-branch              # use existing branch
ww new feature/auth -r myrepo          # target a specific repo
wwn feature/auth                       # create + cd (shell integration)
Flag Description
-b, --base Base branch to fork from
-r, --repo Target repo by name
-e, --existing Use an existing branch
--no-fetch Skip fetching from remote
--cd Print only the path (for scripting)

ww sw

Switch worktrees via fzf. Shows Claude Code agent status per worktree, sorted by activity.

🤖 BUSY   auth-refactor        ~/.willow/worktrees/repo/auth-refactor
✅ DONE   api-cleanup          ~/.willow/worktrees/repo/api-cleanup
⏳ WAIT   payments             ~/.willow/worktrees/repo/payments
🟡 IDLE   main                 ~/.willow/worktrees/repo/main
   --     old-feature          ~/.willow/worktrees/repo/old-feature

ww rm [branch] [flags]

Remove a worktree. Without arguments, opens fzf picker with multi-select (TAB to toggle, Ctrl-A to select all).

ww rm auth-refactor              # direct removal
ww rm                            # fzf picker
ww rm auth-refactor --force      # skip safety checks
ww rm auth-refactor --prune      # also run git worktree prune
Flag Description
-f, --force Skip safety checks
--keep-branch Keep the local branch
--prune Run git worktree prune after

ww ls [repo]

List worktrees with status.

ww ls

Flag Description
--json JSON output
--path-only Paths only (one per line)

ww status

Rich view of Claude Code agent status. Shows per-session rows when multiple agents run in the same worktree, with unread indicators () for completed sessions you haven't reviewed.

ww status

Flag Description
--json JSON output

ww dashboard (alias: dash, d)

Live-refreshing TUI showing all Claude Code sessions across all repos. Includes diff stats, unread counts, and per-session activity.

ww dashboard          # default 2s refresh
ww dash -i 5          # 5s refresh interval

ww dashboard

ww cc-setup

One-time hook installation for Claude Code status tracking.

ww shell-init [flags]

Print shell integration script.

Flag Description
--tab-title Include terminal tab title hook (sets tab to repo/branch)

Agent status

After running ww cc-setup, Claude Code automatically reports its state:

Icon Status Meaning
🤖 BUSY Agent is actively working
DONE Agent finished its turn
WAIT Agent is waiting for user input
🟡 IDLE Agent session ended
-- No activity detected

Status appears in ww ls, ww sw, ww status, and ww dashboard. Stale BUSY/DONE status (>5 min) automatically degrades to IDLE. Completed sessions show a unread indicator until you switch to that worktree via ww sw.

Configuration

Config merges two tiers (local wins):

Priority Path Scope
1 ~/.config/willow/config.json Global defaults
2 ~/.willow/repos/<repo>.git/willow.json Per-repo
{
  "baseBranch": "main",
  "branchPrefix": "alice",
  "postCheckoutHook": ".husky/post-checkout",
  "setup": ["npm install"],
  "teardown": [],
  "defaults": {
    "fetch": true,
    "autoSetupRemote": true
  }
}

Terminal setup (Ghostty / iTerm / etc.)

Use --tab-title to automatically set your terminal tab to the worktree name:

eval "$(willow shell-init --tab-title)"

Each tab shows repo/branch (e.g. myrepo/auth-refactor) when inside a willow worktree.

Recommended Ghostty layout per worktree:

┌─────────────────────────────────────┐
│ Tab: myrepo/auth-refactor           │
├──────────────────┬──────────────────┤
│  claude          │  claude          │
│  (agent 1)       │  (agent 2)       │
├──────────────────┴──────────────────┤
│  shell (git diff, tests, etc.)      │
└─────────────────────────────────────┘

Contributing

# Build
go build -o bin/willow ./cmd/willow

# Test
go test ./...

Requires Go 1.25+ and fzf.

Website

The docs site is built with VitePress.

cd website
pnpm install
pnpm dev       # localhost:5173
pnpm build     # production build

Deployed automatically to GitHub Pages on push to main when website/ changes.

Releasing

Releases are automated via GoReleaser and GitHub Actions.

License

MIT

Directories

Path Synopsis
cmd
willow command
internal
cli
fzf
git
ui

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL