Release Notes
Improved
-
Browse open PRs/MRs in the
wt switchpicker, with live CI: The picker now streams a live CI/review-status column per row — priming from the local cache, then fetching live (it previously showed only cached numbers with no network). A new--prsflag adds the repository's open PRs (GitHub) / MRs (GitLab) as rows alongside your worktrees, each withpr/comments/logpreview tabs loaded from the forge in the background; selecting one fetches its branch and switches. Rows whose branch is already shown aren't duplicated, so--prsdiffers from plainwt switchonly by the extra rows. Docs (#3128, #3169, #3189, #3252) -
main…±diff column shows by default inwt list: Themain…±column (lines changed since the merge-base with the default branch) now renders in the defaultwt listand picker, served from a persistent cache rather than a history walk.--fullnow adds only the columns that reach off-machine — CI status and LLM branch summaries — andwt list --format=jsonpopulatesmain.difffor every item, not just under--full. (#3236) -
[list] columnsselects and orders the columnswt listshows: A new[list] columnsuser-config key (also settable via--config-set) takes an ordered array of column names — built-in (branch,status,ci,path, …) and[list.custom-columns]headers alike — and renders exactly those, in that order. Where v0.61.0's custom columns add columns, this selects and reorders the whole set; omit the key for the default layout. (WORKTRUNK__LIST__COLUMNSisn't supported yet and warns if set.) (#3141) -
Picker PR preview shows full PR/MR detail: The
prtab now renders the PR/MR title, markdown description, author, draft state, comment count, bold branch name, and underlined URL for any row whose branch has an open PR — not just--prsrows — and thecommentstab fetches the real thread. The title and description ride the CI fetch the picker already makes; the comment thread is fetched lazily in the background, once per row. (#3167, #3197, #3223, #3195, #3231) -
Interactive picker runs on Windows: The
wt switchpicker was Unix-only because its preview-tab keys shelled out through a per-process state filecmd.exelacks; tab state moved to an in-memory atomic with native skim callbacks, lifting the platform gate. (#3217) -
Picker keyboard shortcuts:
Alt-ycopies the selected branch name,Alt-oopens the row's PR/MR in the browser, andAlt-rrefreshes the list (picking up worktrees created or removed elsewhere). (Breaking: in the picker, remove moved fromAlt-rtoAlt-x) (#3233) -
Picker uses the full terminal: List height scales with the terminal (a roughly even split with the preview, minimum 3 rows) instead of a fixed 12-row cap, the table lays out at full width so toggling the preview off with
Alt-preveals the freed columns with no reflow, and a scrollbar appears when the list overflows. (#3205, #3214, #3198) -
Picker filters on more of each row: Typing a gutter sigil filters by row kind (
+for linked worktrees,@for the current one), the fuzzy matcher ranks on the distinguishing path segment rather than the shared parent prefix, and rows with a PR/MR also match on its number, title, and author. (#3143, #3208, #3252) -
Picker visual polish: The legend recolored to dim-cyan and reordered so navigation leads, and preview loading placeholders moved to the dim-hint style (
↳transient,○settled,▲failed). (#3237, #3253) -
"Still waiting" status for slow commit-message generation: A configured
commit.generationcommand captures stdout, so a slow or hung LLM previously showed nothing whilewt step commit/squashwaited. After a 2s delay worktrunk now shows a dim, in-place○ Waiting for the commit message (Ns)status, escalating at 10s to reveal the exact shell-escaped invocation in a gutter beneath it; the block clears on completion, mirroringwt list's stall footer. (#3178) -
"Still waiting" status extended to more slow commands: The same waiting status now covers three more foreground commands that were silent while a captured subprocess ran — the
wt config show --fullcommit-generation self-test, thewt switch pr:/mr:host lookup, and thewt config show --fullversion check. The version check no longer caps its fetch at an aggressive 5s, instead showing the status while a slow-but-working request completes (with a generous ceiling so a non-interactive run can't hang). (#3183) -
wt config state logs profileperformance profiler: A new subcommand turns a-vv[wt-trace]capture (a path argument,-for stdin, or the defaulttrace.log) into a performance profile: subprocess time by command shape, the slowest calls, parallelism and peak concurrency, redundant cache-miss re-runs, and — forwt list/picker captures — derived latencies and a collect timeline.--format=jsonemits the same data, and every-vvbug-report bundle now inlines a rendered profile. (#3184, #3186) -
WORKTRUNK_VERBOSEenv var:WORKTRUNK_VERBOSE=0|1|2mirrors-v/-vv, combined with any flag viamax(the env sets a floor the flag can raise). Unlike the flags it's honored on the shell-completion path, which returns before flag parsing — so a slow tab-completion can be profiled for the first time. (#3166) -
Aliases inherit the wrapped command's completion: An alias that forwards
{{ args }}to a singlewtcommand (co = "wt switch {{ args }}") now completes that command's arguments and flags —wt co <Tab>completes branches likewt switch <Tab>— instead of a generic stub. Bare dispatchers and multi-{{ args }}aliases keep the stub. (#3172, thanks @yzx9) -
wt step copy-ignored --require-include: A new--require-includeflag makes the copy a no-op unless a.worktreeincludefile exists in the source worktree (matching Claude Code desktop, where that file is required), reporting why it skipped as a hint in text mode and areasonfield in--format=json. (#3196, thanks @yzx9) -
wt step tetherhonors-C: The global-C <path>flag now sets the tethered command's working directory (wt step tether -C frontend -- npm run dev); teardown still watches the worktree root, so the command is reaped when the worktree is removed. (#3207) -
Statusline rate-limit pace color grades by severity: The pace segment's color now deepens (dim → dim-yellow → yellow) with the projected throttling severity, so an early-window burst stays muted while a costly projected lockout stands out. The displayed pace number is unchanged. (#3229)
Fixed
-
Picker
Alt-xremoval updates the row in place: Removing a worktree no longer re-collects the whole list (a flicker that reset the cursor to the top): an unmerged worktree's row morphs into a branch-only row while the worktree is removed in the background, and a merged worktree's row drops with the cursor landing on the row that slid up. A removal that can't safely happen — the current or main worktree, or a dirty or locked one — is declined with the same diagnosticwt removeprints, rather than a dead keypress or a disruptivecdhome. The post-removal cursor lands by row identity, so it stays correct even under an active filter. (#3262, #3199, #3211, #3225) -
Picker preview refreshes when its background fetch lands: A diff/log/PR-view fetch that completed after its triggering keystroke used to sit unshown until the next keypress; the pane now updates on its own when the fetch lands. (#3247)
-
Picker rows stay aligned while filtering: Typing a filter no longer slides the matched row left and drops its leading sigil, and
Alt-l/Alt-hno longer scroll the list off its gutter. (#3213, #3226) -
fish completions no longer recurse to the call-stack limit: With worktrunk's fish lazy-load wrapper installed, completion could re-enter the wrapper and recurse until fish hit its call-stack limit. The package-manager registration now resolves the real binary via
type -Pinstead of calling the barewt, and the wrapper stub short-circuits in completion mode the way the bash and zsh wrappers already did. (#3241, #3250; fixes #3240, thanks @maciej-lech for reporting) -
wt switchchanges directory under fish withzoxide.fish: The fish integration used a barecd, which thekidonng/zoxide.fishplugin intercepts as a fuzzy query, so a switch reported success but failed withzoxide: no match found. The wrapper now usesbuiltin cd, bypassing any usercdoverride. (#3160, fixes #3159, thanks @anon-legion for reporting) -
wt switch pr:Nresolves Azure DevOps projects with encoded path segments: Azure returns decoded project names while git remotes store them URL-encoded, so a project likeproject with spacesfailed to match. Path segments are now canonicalized before comparing remotes and building Azure URLs. (#3204, fixes #3203, thanks @jonasherfort) -
Recommended Claude Code commit command preserves
apiKeyHelperauth: The suggested[commit.generation]command for Claude Code used--setting-sources='', which dropped user settings and broke authentication for setups that get their key viaapiKeyHelper. It now uses--safe-mode --setting-sources='user': the run stays hermetic (no hooks, plugins, MCP, skills, or CLAUDE.md) but loads user settings soapiKeyHelperworks (requires Claude Code ≥ 2.1.169). Existing user configs are not rewritten. (#3170) -
Claude Code paths honor
CLAUDE_CONFIG_DIR: worktrunk hardcoded~/.claudefor every Claude Code path, so on a machine that relocates the config tree viaCLAUDE_CONFIG_DIR,wt config showwrongly reported the plugin and statusline as not installed andinstall-statuslinewrote to a stray file Claude Code never reads. All three call sites now resolve throughCLAUDE_CONFIG_DIR, falling back to~/.claude. (#3215, thanks @tftio) -
Deprecated config keys migrate in
--config-set, env vars, and inline tables: Deprecated keys were rewritten to canonical form only in config files; passed any other way they fell through as unknown fields and were silently dropped.wt --config-set 'merge.no-ff=true',WORKTRUNK__MERGE__NO_FF=true, and the inlinemerge = { no-ff = true }form now all migrate and take effect. (#3152, #3158) -
wt config showcan't hang on the zsh compinit probe: The interactivezsh -icprobe that checks whether compinit is configured could hang indefinitely on compinit's insecure-directories prompt; it now has a 2s kill-on-timeout, declining to warn on timeout. (#3165) -
Empty branch-name arguments rejected at the parse boundary: An empty value (e.g.
wt step diff --branch=) was accepted and produced a garbled downstream diagnostic; all branch-name arguments now reject empty or whitespace-only values at the CLI edge with a standard usage error. A real missing branch still gets its normal "no worktree" diagnostic. (#3179)
Documentation
wt listJSON and help-text accuracy: Thewt listhelp text and web docs now note which--format=jsonobjects (ci,summary) require--full, and the status-symbol reference tables name each JSON field by type — correcting a wrong "only the first matching symbol is shown" note and an unreachableworktree.statevalue. (#3139, #3220, #3224)
Internal
- Richer
-vvdiagnostics:-vvnow also writes a machine-readabletrace.jsonl(one JSON object per event) alongsidetrace.log, segmentssubprocess.loginto per-command blocks joined to the trace by aseqfield, and lists each log path on its own line; worktrunk's own log sites moved to nativetracing. (#3232, #3182, #3163)
Install worktrunk 0.62.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/max-sixty/worktrunk/releases/download/v0.62.0/worktrunk-installer.sh | sh && wt config shell installInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/max-sixty/worktrunk/releases/download/v0.62.0/worktrunk-installer.ps1 | iex"; git-wt config shell installInstall prebuilt binaries via Homebrew
brew install worktrunk && wt config shell installDownload worktrunk 0.62.0
| File | Platform | Checksum |
|---|---|---|
| worktrunk-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| worktrunk-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| worktrunk-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| worktrunk-aarch64-unknown-linux-musl.tar.xz | ARM64 MUSL Linux | checksum |
| worktrunk-x86_64-unknown-linux-musl.tar.xz | x64 MUSL Linux | checksum |
Install via Cargo
cargo install worktrunk && wt config shell installInstall via Winget (Windows)
winget install max-sixty.worktrunk && git-wt config shell installInstall via AUR (Arch Linux)
paru worktrunk-bin && wt config shell install