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 list
Lists 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 :pick
If 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> --force
Prevents 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 active
Session 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)