A Go-based CLI tool for managing Git worktrees with automatic tmux session management and editor integration.
# Build and install
go install .Or build a local binary:
go build -o wt .Priority (highest to lowest):
- Environment Variables
- Local Project Config —
.wt.tomlin repository root - Global User Config —
~/.config/wt/config.toml - Built-in Defaults
Default: ~/projects/worktrees
Base directory where worktrees are created.
Default: []
Files/patterns to copy from the main repository into new worktrees. Supports glob patterns (config/*.json, .env*, scripts/*).
Default: []
Windows to create when a new tmux session starts. Commands run in the worktree directory.
WORKTREE_BASE_DIR— Overridesworktrees_locationXDG_CONFIG_HOME— Changes the global config directory (default:~/.config)
Global (~/.config/wt/config.toml):
worktrees_location = "~/projects/worktrees"
copy_files = [".env.example", ".vscode/settings.json"]Project (.wt.toml in repo root):
copy_files = ["config/local.json"]
tmux_windows = [
{ name = "editor", command = "nvim ." },
{ name = "server", command = "pnpm dev" },
{ name = "tests", command = "pnpm test --watch" },
{ name = "terminal", command = "" }
]copy_filesandtmux_windowsarrays are merged (local appends to global;copy_filesdeduplicates)worktrees_locationin local config overrides global
--no-editor— Don't open the editor--no-tmux— Don't create/switch tmux sessions-v, --verbose— Verbose output for debugging
wt listLists all worktrees for the current repository. Use --all to list across all projects, --json for machine-readable output, --path-only for paths only.
# New branch
wt new <branch-name>
# Interactive — prompts for branch name
wt new
# From existing branch (name derived from branch)
wt new --from origin/release-1.2
# From existing branch with explicit worktree name
wt new release-1.2 --from origin/release-1.2
# Interactive branch selection
wt new --from :pickIf a worktree already exists for the branch, wt offers to switch to it instead of creating a duplicate.
wt open
# Browse across all projects
wt open --all
# Filter to a specific project
wt open --project <project-name>When inside a repository, lists that repo's worktrees directly. Outside a repository, shows a project picker first. If only one option exists, selection is skipped automatically.
# Interactive selection with confirmation
wt delete
# Delete specific worktree
wt delete <worktree-name>
# Skip confirmation
wt delete <worktree-name> --forcePrevents deletion of the main worktree. Kills the associated tmux session. Does not delete the underlying Git branch.
wt idle tracks which tmux panes have a Claude agent waiting for input, so you can jump directly to the right session without hunting through tmux ls.
Add to ~/.claude/settings.json:
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [{ "type": "command", "command": "wt idle register" }]
}
],
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [{ "type": "command", "command": "wt idle active" }]
}
]
}
}Both hooks exit 0 silently when not inside tmux, so they are safe to add globally.
# List sessions currently waiting for input
wt idle list
# Include active sessions (adds STATUS column)
wt idle list --all
# Switch to a session by ID or name (marks it active)
wt idle switch 1
wt idle switch my-session
# Remove records for sessions that no longer exist in tmux
wt idle clean
# Called automatically by hooks — also available manually
wt idle register # mark current pane as waiting
wt idle active # mark current pane as activeSession state is stored at ~/.local/share/wt/idle-sessions.json.
Add a popup picker to your ~/.tmux.conf:
bind I display-popup \
-w 75% \
-h 40% \
-E "~/.dotfiles/.scripts/idle-session-picker"Picker script (~/.dotfiles/.scripts/idle-session-picker):
#!/usr/bin/env bash
output=$(wt idle list 2>/dev/null)
if [ -z "$output" ] || [ "$output" = "No sessions." ]; then
echo "No idle Claude sessions."
sleep 1.5
exit 0
fi
header=$(echo "$output" | head -1)
rows=$(echo "$output" | tail -n +2 | grep -v '^$' | grep -v '^Note:')
if [ -z "$rows" ]; then
echo "No idle Claude sessions."
sleep 1.5
exit 0
fi
selected=$(echo "$rows" | fzf \
--header="$header" \
--reverse \
--prompt="Claude idle > " \
--no-sort \
--height=100%)
[ -z "$selected" ] && exit 0
id=$(echo "$selected" | awk '{print $1}')
wt idle switch "$id"go mod download # install dependencies
go run . <cmd> # run without building
go test ./... # run tests
go fmt ./... # format code- Create a feature branch from
main. - Run
go fmt ./...andgo test ./...before pushing. - Open a PR against
mainwith context and test results.
- Git
- Go 1.21+
- tmux (optional — for session management and idle tracking)
fzf(optional — only required for theidle-session-pickerscript above)$EDITOR(optional — for editor integration)- Claude Code (optional — for
wt idlehook integration)