Skip to content

Commit 5529729

Browse files
karan925claude
andcommitted
feat(init): add interactive fzf worktree picker for gtr cd
When `gtr cd` is called with no arguments and fzf is installed, an interactive picker launches showing all worktrees with a git log + status preview pane. Gracefully falls back to printing the worktree list with a hint when fzf is not available. Supported in bash, zsh, and fish shells. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c74f843 commit 5529729

4 files changed

Lines changed: 65 additions & 1 deletion

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ git gtr ai my-feature # Start claude
100100
git gtr run my-feature npm test # Run tests
101101

102102
# Navigate to worktree
103+
gtr cd # Interactive picker (requires fzf + shell integration)
103104
gtr cd my-feature # Requires: eval "$(git gtr init bash)"
104105
cd "$(git gtr go my-feature)" # Alternative without shell integration
105106

@@ -217,6 +218,7 @@ cd "$(git gtr go 1)" # Navigate to main repo
217218
eval "$(git gtr init bash)"
218219

219220
# Then navigate with:
221+
gtr cd # Interactive worktree picker (requires fzf)
220222
gtr cd my-feature
221223
gtr cd 1
222224
```

lib/commands/doctor.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ cmd_doctor() {
112112
fi
113113
fi
114114

115+
# Check fzf (optional, for interactive picker)
116+
if command -v fzf >/dev/null 2>&1; then
117+
echo "[OK] fzf: $(fzf --version 2>/dev/null | awk '{print $1}') (interactive picker available)"
118+
else
119+
echo "[i] fzf: not found (install for interactive picker: gtr cd)"
120+
fi
121+
115122
echo ""
116123
if [ "$issues" -eq 0 ]; then
117124
echo "Everything looks good!"

lib/commands/help.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ Setup:
365365
eval "$(git gtr init zsh --as gwtr)"
366366
367367
After setup:
368+
gtr cd # interactive worktree picker (requires fzf)
368369
gtr cd my-feature # cd to worktree
369370
gtr cd 1 # cd to main repo
370371
gtr <command> # same as git gtr <command>
@@ -549,6 +550,7 @@ SETUP & MAINTENANCE:
549550
Generate shell integration for cd support (bash, zsh, fish)
550551
--as <name>: custom function name (default: gtr)
551552
Usage: eval "$(git gtr init bash)"
553+
With fzf installed, 'gtr cd' (no args) opens an interactive picker
552554
553555
version
554556
Show version
@@ -572,6 +574,7 @@ WORKFLOW EXAMPLES:
572574
git gtr run feature/user-auth npm run dev # Start dev server
573575
574576
# Navigate to worktree directory
577+
gtr cd # Interactive picker (requires fzf)
575578
gtr cd feature/user-auth # With shell integration (git gtr init)
576579
cd "$(git gtr go feature/user-auth)" # Without shell integration
577580

lib/commands/init.sh

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,23 @@ _init_bash() {
8181
__FUNC__() {
8282
if [ "$#" -gt 0 ] && [ "$1" = "cd" ]; then
8383
shift
84+
if [ "$#" -eq 0 ]; then
85+
if command -v fzf >/dev/null 2>&1; then
86+
local _gtr_sel
87+
_gtr_sel="$(command git gtr list --porcelain | fzf \
88+
--delimiter=$'\t' \
89+
--with-nth=2 \
90+
--header='Select worktree (Ctrl-C to cancel)' \
91+
--preview='git -C {1} log --oneline --graph -15 2>/dev/null; echo "---"; git -C {1} status --short 2>/dev/null' \
92+
--preview-window=right:50%)" || return 0
93+
set -- "$(printf '%s' "$_gtr_sel" | cut -f2)"
94+
else
95+
echo "Tip: Install fzf for an interactive worktree picker (https://github.com/junegunn/fzf)" >&2
96+
echo "" >&2
97+
command git gtr list
98+
return 0
99+
fi
100+
fi
84101
local dir
85102
dir="$(command git gtr go "$@")" && cd "$dir" && {
86103
local _gtr_hooks _gtr_hook _gtr_seen _gtr_config_file
@@ -154,6 +171,23 @@ _init_zsh() {
154171
__FUNC__() {
155172
if [ "$#" -gt 0 ] && [ "$1" = "cd" ]; then
156173
shift
174+
if [ "$#" -eq 0 ]; then
175+
if command -v fzf >/dev/null 2>&1; then
176+
local _gtr_sel
177+
_gtr_sel="$(command git gtr list --porcelain | fzf \
178+
--delimiter=$'\t' \
179+
--with-nth=2 \
180+
--header='Select worktree (Ctrl-C to cancel)' \
181+
--preview='git -C {1} log --oneline --graph -15 2>/dev/null; echo "---"; git -C {1} status --short 2>/dev/null' \
182+
--preview-window=right:50%)" || return 0
183+
set -- "$(printf '%s' "$_gtr_sel" | cut -f2)"
184+
else
185+
echo "Tip: Install fzf for an interactive worktree picker (https://github.com/junegunn/fzf)" >&2
186+
echo "" >&2
187+
command git gtr list
188+
return 0
189+
fi
190+
fi
157191
local dir
158192
dir="$(command git gtr go "$@")" && cd "$dir" && {
159193
local _gtr_hooks _gtr_hook _gtr_seen _gtr_config_file
@@ -232,7 +266,25 @@ _init_fish() {
232266
233267
function __FUNC__
234268
if test (count $argv) -gt 0; and test "$argv[1]" = "cd"
235-
set -l dir (command git gtr go $argv[2..])
269+
set -l _gtr_cd_args $argv[2..]
270+
if test (count $_gtr_cd_args) -eq 0
271+
if command -q fzf
272+
set -l _gtr_sel (command git gtr list --porcelain | fzf \
273+
--delimiter=\t \
274+
--with-nth=2 \
275+
--header='Select worktree (Ctrl-C to cancel)' \
276+
--preview='git -C {1} log --oneline --graph -15 2>/dev/null; echo "---"; git -C {1} status --short 2>/dev/null' \
277+
--preview-window=right:50%)
278+
or return 0
279+
set _gtr_cd_args (printf '%s' "$_gtr_sel" | cut -f2)
280+
else
281+
echo "Tip: Install fzf for an interactive worktree picker (https://github.com/junegunn/fzf)" >&2
282+
echo "" >&2
283+
command git gtr list
284+
return 0
285+
end
286+
end
287+
set -l dir (command git gtr go $_gtr_cd_args)
236288
and cd $dir
237289
and begin
238290
set -l _gtr_hooks

0 commit comments

Comments
 (0)