wt switch
Switch to a worktree; create if needed.
Worktrees are addressed by branch name; paths are computed from a configurable template. Unlike git switch, this navigates between worktrees rather than changing branches in place.
Examples
Section titled “Examples”wt switch feature-auth # Switch to worktreewt switch - # Previous worktree (like cd -)wt switch --create new-feature # Create new branch and worktreewt switch --create hotfix --base productionwt switch pr:123 # Switch to PR #123's branchwt switch https://github.com/owner/repo/pull/123 # ...or paste the PR's URLCreating a branch
Section titled “Creating a branch”The --create flag creates a new branch from --base — the default branch unless specified. Without --create, the branch must already exist. Switching to a remote branch (e.g., wt switch feature when only origin/feature exists) creates a local tracking branch.
A new branch tracks the remote branch it starts from only when the two share a name: --create release --base origin/release tracks origin/release, while --create feature --base origin/release gets no upstream. Publish such a branch with git push --set-upstream origin <branch>, or set git’s push.autoSetupRemote = true once.
Creating worktrees
Section titled “Creating worktrees”If the branch already has a worktree, wt switch changes directories to it. Otherwise, it creates one:
- Runs pre-switch hooks, blocking until complete
- Creates worktree at configured path (or at
--path) - Switches to new directory
- Runs pre-start hooks, blocking until complete
- Spawns post-start and post-switch hooks in the background
wt switch feature # Existing branch → creates worktreewt switch --create feature # New branch and worktreewt switch --create fix --base release # New branch from releasewt switch --create temp --no-hooks # Skip hooksCustom path
Section titled “Custom path”
--path places one worktree outside the worktree-path template, keeping the branch name intact:
wt switch --create feature/JIRA-1234 --path ../dark-modewt switch ../dark-mode # Switch by path...wt switch feature/JIRA-1234 # ...or by branchWorktrunk finds the worktree from git’s own records, so commands reach it by branch or path as usual. wt list marks it ⚐, since it isn’t at the path its branch implies, and wt step relocate offers to move it back to the template path.
Naming a worktree
Section titled “Naming a worktree”Worktrees are addressed by branch name, and every argument that takes one also accepts the path of the worktree itself — resolved after the branch, so a directory never shadows a branch sharing its name. A path names what a branch cannot: a detached worktree, or one of two checkouts of the same branch. Relative paths resolve against -C and a leading ~ against the home directory, so a path worktrunk printed can be pasted back.
Shortcuts
Section titled “Shortcuts”| Shortcut | Meaning |
|---|---|
^ | Default branch (main/master) |
@ | Current branch/worktree |
- | Previous worktree (like cd -) |
pr:{N} | GitHub PR #N’s branch |
mr:{N} | GitLab MR !N’s branch |
wt switch - # Back to previouswt switch ^ # Default branch worktreewt switch --create fix --base=@ # Branch from current HEADwt switch --create fix --base=pr:123 # Branch from PR #123's headwt switch pr:123 # PR #123's branchwt switch mr:101 # MR !101's branchShortcuts also apply to --base.
Interactive picker
Section titled “Interactive picker”When called without arguments, wt switch opens an interactive picker to browse and select worktrees with live preview. The candidate set widens with --branches (local branches without worktrees), --remotes (remote branches), and --prs (open PRs/MRs — see below).
The CI column shows each row’s PR/MR CI and review status, the same as wt list --full.
Keybindings:
| Key | Action |
|---|---|
↑/↓ | Navigate worktree list |
| (type) | Filter worktrees |
Enter | Switch to selected worktree |
Alt-c | Create new worktree named as entered text |
Alt-x | Remove selected worktree/branch (never forces; not the current worktree) |
Alt-y | Copy selected branch name to the clipboard |
Alt-o | Open the selected row’s PR/MR URL in the browser |
Alt-r | Refresh the list (pick up worktrees created elsewhere) |
Esc | Cancel |
Alt-1–Alt-8 | Jump to a preview tab |
Tab/Shift-Tab | Cycle available preview tabs forward/backward |
Alt-p | Toggle preview panel |
Ctrl-u/Ctrl-d | Scroll preview up/down |
On macOS, Alt is the Option key; the terminal needs to send it as Meta (e.g. Terminal.app’s Use Option as Meta key).
The filter matches each row’s branch, path, and — when it has a PR/MR — the PR/MR’s number, title, and author. Typing + narrows to linked worktrees, and @ to the current worktree.
Preview tabs:
- diff — One net diff from the comparison base through the current worktree: committed, staged, unstaged, and untracked changes
- working — Staged, unstaged, and untracked changes against
HEAD - committed — Committed changes since the comparison base
- log — Recent commits; commits already on the default branch have dimmed hashes
- remote⇅ — Ahead/behind diff vs upstream tracking branch
- summary — LLM-generated branch summary; requires
[list] summary = trueandcommit.generation - pr — The selected row’s PR/MR, for any row whose branch has one
- comments — The PR/MR’s comment thread, fetched from the forge for any row whose branch has one
The comparison base is the merge-base with the default branch, or with its upstream when the local default branch lags. The picker opens on diff for local rows and pr for a PR/MR listed by --prs but not available locally. A tab with no content for the selected row has a dimmed label, and the active tab’s label is underlined. Tab and Shift-Tab skip the dimmed tabs; Alt-1 through Alt-8 open any tab directly. After you choose a tab, that choice stays active while you navigate.
Pager configuration: The preview panel pipes diff output through git’s pager. Override in user config:
[switch.picker]pager = "delta --paging=never --width=$COLUMNS"Starting list-only: Set preview = false under [switch.picker] to open the picker with the preview hidden; Alt-p still shows it.
Pull requests and merge requests
Section titled “Pull requests and merge requests”The pr:<number> / mr:<number> shortcut and the PR/MR’s web URL both resolve to its branch. For same-repo PRs/MRs, worktrunk switches to the branch directly. For fork PRs/MRs, it fetches the ref (refs/pull/N/head or refs/merge-requests/N/head) and configures pushRemote to the fork URL.
wt switch pr:101 # GitHub PR #101wt switch https://github.com/owner/repo/pull/101 # ...the same PR, by URLwt switch mr:101 # GitLab MR !101wt switch https://gitlab.com/owner/repo/-/merge_requests/101 # ...the same MR, by URLwt switch --prs # Browse open PRs/MRs in the pickerBoth work anywhere a branch is accepted, including --base. The --create flag cannot be used with a PR/MR reference since the branch already exists.
If the PR or MR is on a fork, the local branch uses its branch name directly, so git push works normally. A pre-existing local branch with that name tracking something else requires renaming first.
The --prs flag adds the repository’s open PRs (GitHub) or MRs (GitLab) that aren’t already in the interactive picker. Selecting one switches to it as pr:<number> / mr:<number> would.
Requires gh (GitHub), glab (GitLab), or an equivalent CLI installed and authenticated; see forge platform for Gitea, Azure DevOps, and other supported platforms.
When wt switch fails
Section titled “When wt switch fails”- Branch doesn’t exist — Use
--create, or checkwt list --branches - Path occupied — Another worktree is at the target path; switch to it or remove it
- Stale directory — Use
--clobberto remove a non-worktree directory at the target path
To change which branch a worktree is on, use git switch inside that worktree.
See also
Section titled “See also”wt list— View all worktreeswt remove— Delete worktrees when donewt merge— Integrate changes back to the default branch
Command reference
Section titled “Command reference”wt switch - Switch to a worktree; create if neededUsage: wt switch [OPTIONS] [BRANCH] [-- <EXECUTE_ARGS>...]Arguments:[BRANCH]Branch, worktree path, shortcut, or PR/MR URLOpens interactive picker if omitted. Shortcuts: ^ (default branch), - (previous), @(current), pr:{N} (GitHub PR), mr:{N} (GitLab MR)[EXECUTE_ARGS]...Additional arguments for --execute command (after --)Each argument is expanded for templates and passed directly to the program.Options:-c, --createCreate a new branch-b, --base <BASE>Base branchDefaults to default branch. Supports the same shortcuts as the branch argument: ^, @, -,pr:{N}, mr:{N}.--path <PATH>Worktree directory for a new worktree Overrides the worktree-path template for this worktree. Relative paths resolve from thecurrent directory, as with git worktree add. The branch keeps its own name; afterwards,switch by branch or by path.-x, --execute <EXECUTE>Program to run after switchRuns one external program after switching, with full terminal control. Arguments after --go directly to that program without Worktrunk shell parsing. Program lookup and argumentdecoding follow the operating system. Shell syntax requires an explicit shell, for example-x sh -- -c 'npm install && npm test'. On Windows, shell shims need their extension (-xcode.cmd) or an explicit shell such as -x cmd.exe -- /C code.Without a branch argument, the interactive picker opens and the command runs against theselected worktree — so wt switch -x claude picks a worktree, then launches Claude Codethere.The program starts in the worktree the switch selected, whether or not your shell followsit there: --no-cd governs only the shell.Supports hook template variables ({{ branch }}, {{ worktree_path }}, etc.) and filters. {{base }} and {{ base_worktree_path }} describe the source: the selected base with --create,or the invoking worktree when switching to an existing worktree.A variable inside a shell body is substituted before that shell parses it, so a path withspaces splits into several arguments. Pass it as a separate argument instead — sh bindsthe first one to $0, so the path arrives as $1:wt switch feature -x sh -- -c 'cd "$1" && npm test' sh '{{ worktree_path }}'alias wsc='wt switch --create -x claude'wsc feature-branch -- 'Fix GH #322'Then wsc feature-branch creates the worktree and launches Claude Code. Arguments after --are passed to the command, so wsc feature -- 'Fix GH #322' runs claude 'Fix GH #322',starting Claude with a prompt.Template example: -x code -- '{{ worktree_path }}' opens VS Code at the worktree, -x tmux-- new -s '{{ branch | sanitize }}' starts a tmux session named after the branch.--clobberRemove stale paths at target--no-cdSkip directory change after switchingHooks still run normally, and an --execute program still starts in the worktree — onlyyour shell stays put, so wt switch feature --no-cd -x code -- . opens the worktree in aneditor and leaves your terminal where it was. Useful when hooks handle navigation (e.g.,tmux workflows) or for CI/automation. Use --cd to override.-h, --helpPrint help (see a summary with '-h')Picker Options:--branchesInclude branches without worktrees--remotesInclude remote branches--prsInclude open PRs/MRsAutomation:--no-hooksSkip hooks--format <FORMAT>Output formatJSON prints structured result to stdout. Designed for tool integration (e.g., Claude CodeWorktreeCreate hooks).Global Options:-C <path>Working directory for this command--config <path>User config file path--config-set <toml>Override config with inline TOML, e.g. --config-set list.full=true (repeatable)-v, --verbose...Verbose output (-v: info logs + hook/alias template variables on stderr; -vv: also debuglogs and raw subprocess output written to .git/wt/logs/). Set WORKTRUNK_VERBOSE=0|1|2 toapply the same level everywhere — including shell completion, which no flag can reach-y, --yesSkip approval prompts