fwt is a sourceable shell function for jumping between Git worktrees with fzf.
It is a shell function, not a standalone executable, because a child process cannot change the working directory of the current shell.
gitfzffdfor recursive modeawk,sed,dirname,cat,printf
Source fwt.sh from an interactive shell:
source /path/to/fwt.shNixOS example:
environment.etc."fwt/fwt.sh".source = inputs.fwt + "/fwt.sh";
environment.interactiveShellInit = ''
source /etc/fwt/fwt.sh
'';fwt [options] [path]Arguments:
path— repo/path to inspect, or recursive scan root with-r. Defaults to the current directory.
Options:
-r,--recursive— recursively discover Git repos underpathand stream their worktrees intofzf.-b,--basename— display only each worktree directory name. Selection stillcds to the full real path.--after-cd <cmd>— overrideFWT_POST_CDfor one run. Use--after-cd=''to disable it for one run.-h,--help— print usage, options, and config variables.
Short options may be combined, e.g. fwt -rb is the same as fwt -r -b.
Examples:
fwt
fwt /path/to/repo
fwt -r
fwt -r /path/to/search-root
fwt --basename
fwt -r --basename ~/work
fwt -rb ~/work
fwt --after-cd 'zed . && omp'
fwt --after-cd='' ~/work/appRecursive discovery streams into fzf: the picker opens after the first worktree is found while the rest of the scan continues.
Each fzf row shows an aliased worktree path on the left and the branch label on the right:
~/code/app-auth [feature/auth]
~/code/app [main]
Paths under $HOME display with ~. The selected path is stored in a hidden field, so display aliases, truncation, and paths with spaces do not affect cd.
Branch labels are not truncated by fwt. If a row would exceed the display width, fwt shortens only the visible path and keeps the full [branch] label. If the branch alone is wider than the picker row, the terminal/fzf viewport can still clip it.
The picker header shows what will run after selection: after cd: fwt_after_cd() for the hook, after cd: <command> for FWT_POST_CD or --after-cd, and after cd: fwt_after_cd(); <command> when both are set. If neither is set, it points at the effective config file.
Optional config lives at:
~/.config/fwt/config.shExample:
FWT_FZF_OPTS=(
--height=40%
--reverse
--prompt='worktree> '
)
FWT_HOME_LABEL='~'
FWT_FZF_CHROME_COLUMNS=4
# FWT_DISPLAY_WIDTH=120
FWT_POST_CD='zed . && omp'Config variables:
FWT_CONFIG— config file path. Defaults to~/.config/fwt/config.sh.FWT_HOME_LABEL— alias for paths under$HOME. Defaults to~.FWT_DISPLAY_WIDTH— explicit row width override.FWT_FZF_CHROME_COLUMNS— columns reserved for fzf pointer/gutter whenFWT_DISPLAY_WIDTHis unset. Defaults to4.FWT_POST_CD— shell command shown in the fzf header and run aftercdin the selected worktree.FWT_FZF_OPTS— extra fzf options array.fwt_after_cd()— optional function hook shown in the fzf header and called aftercdwith selected path.
FWT_POST_CD runs after fwt changes into the selected worktree. Override it once with --after-cd <cmd> or disable it once with --after-cd=''. It is evaluated as local shell code, so only run commands you trust. If unset, the picker hint points at the effective config path from FWT_CONFIG, XDG_CONFIG_HOME, or ~/.config/fwt/config.sh.
For more control, define a function hook:
fwt_after_cd() {
printf 'entered %s\n' "$1"
}fwt_after_cd runs before FWT_POST_CD and receives the selected path.