Skip to content

feat(cd): add 'wt cd' to switch between existing worktrees - #117

Merged
timvw merged 2 commits into
mainfrom
feat/cd-command
Aug 10, 2026
Merged

feat(cd): add 'wt cd' to switch between existing worktrees#117
timvw merged 2 commits into
mainfrom
feat/cd-command

Conversation

@timvw

@timvw timvw commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Closes #103.

Why

wt co already has a fuzzy picker and auto-cd, but its list comes from getAvailableBranches() — every local and remote branch — and picking a branch without a worktree creates one. The request in #103 is narrower: jump between the worktrees that already exist, which is what cd $(wt ls | fzf | cut -d' ' -f1) does today.

What

wt cd [branch] (alias wt sw):

  • Without arguments: fuzzy picker over existing worktrees only, including the main checkout. The current worktree is labelled (current); detached worktrees fall back to their directory name.
  • With a branch: navigates directly, or fails with no worktree found for branch: X / Use 'wt checkout X' to create one.
  • Never creates a worktree or a branch.
  • --format json emits the usual envelope with path / navigate_to, and requires an explicit branch argument (same rule as checkout and remove).

Tab completion for cd/sw added for bash, zsh, fish and PowerShell, completing existing worktree branches (unlike remove, the main checkout is included). Docs updated in README, llms.txt, AGENTS.md, the wt examples catalog, and the Claude Code skill.

One implementation note

wt cd prints ✓ Switched to worktree: <path> before the cd marker. That is not just cosmetic: the shell wrapper extracts the path with grep '^wt navigating to: ', and script(1) can prefix the first output line with a control character (^D), which makes the anchored grep miss it and silently skips auto-cd. Every other navigating command happens to print a status line first, so this was never hit before. The e2e suite reproduced it immediately.

Testing

  • New e2e/scenarios/cd.yaml: navigate to existing worktree, sw alias, refusal to create, return to the main checkout, JSON behaviour.
  • New unit tests for target building ((current) marking, detached fallback, bare worktree skipped) and path containment.
  • New pty test TestInteractiveCdWithoutArgs asserting the picker offers a branch with a worktree and not one without.
  • go test ./..., go vet ./..., go run e2e/run.go (310 passed, 0 failed).

TestBashTabCompletionForCheckoutBranch and TestBashTabCompletionForCommands fail on my macOS box (bash 3.2), but they fail identically on main — unrelated to this change.

Unrelated harness bug spotted

e2e/run.go never resets __exit_code between steps, and uses ${__exit_code:-0}, so any zero-exit step following a non-zero-exit step inherits the old 1 and fails. I worked around it by splitting a scenario rather than touching shared infra here — happy to send a separate one-line fix.

@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 41.11111% with 53 lines in your changes missing coverage. Please review.
✅ Project coverage is 36.91%. Comparing base (57d7103) to head (48f3221).

Files with missing lines Patch % Lines
cmd/cd.go 26.98% 45 Missing and 1 partial ⚠️
cmd/shellenv.go 73.07% 7 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #117      +/-   ##
==========================================
+ Coverage   36.70%   36.91%   +0.20%     
==========================================
  Files          27       28       +1     
  Lines        3111     3199      +88     
==========================================
+ Hits         1142     1181      +39     
- Misses       1884     1931      +47     
- Partials       85       87       +2     
Files with missing lines Coverage Δ
cmd/examples.go 67.74% <ø> (ø)
cmd/root.go 70.45% <100.00%> (+0.33%) ⬆️
cmd/shellenv.go 78.51% <73.07%> (-0.26%) ⬇️
cmd/cd.go 26.98% <26.98%> (ø)

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

timvw added 2 commits August 10, 2026 16:45
'wt co' offers every local and remote branch and creates a worktree when
one is missing, so switching between the worktrees you already have means
scrolling past hundreds of irrelevant branches (issue #103).

'wt cd' (alias 'wt sw') selects only from worktrees that already exist,
including the main checkout, and never creates anything. With a branch
argument it navigates directly; without one it opens the same fuzzy
picker used by the other interactive commands.

The status line before the cd marker is deliberate: the shell wrapper
greps for '^wt navigating to: ', and script(1) can prefix the first
output line with a control character, which would silently break auto-cd.

Closes #103
script(1) does not propagate the child's exit status on every platform
(util-linux returns its own status without -e), so the shellenv wrapper
reports 0 for a failed command on Linux. Every other non-zero-exit
scenario in the suite already uses skip_shellenv + $WT_BIN for this
reason.
@timvw
timvw merged commit a81a147 into main Aug 10, 2026
16 checks passed
@timvw
timvw deleted the feat/cd-command branch August 10, 2026 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide something like "wt cd" to easily switch from one worktree to another one

1 participant