Release Notes
Improved
-
sanitize_dbtemplate filter caps output at 48 chars (was 63 — PostgreSQL's identifier limit). The new budget leaves headroom for users composing the output into longer paths or identifiers, e.g., Unix socket paths capped at 107 bytes. The 3-character hash suffix is unchanged, so collision avoidance is preserved at the new budget; only the truncated base shrinks. (Breaking: branches whose previoussanitize_dboutput exceeded 48 chars get a different identifier — most names are well under 48 and pass through unchanged.) (#2467, thanks @yajo for #2397) -
New
hashtemplate filter:{{ value | hash }}produces a 3-character base36 digest of the input — useful for composing custom truncate-with-collision-avoidance recipes whensanitize_db's 48-char budget still isn't tight enough. (#2453) -
Background hook announces collapse to one line per command:
wt merge(with removal) previously emitted two or three separate◎ Running …lines forpost-remove + post-switchandpost-merge. Hooks across all phases of a single command now share one combined announce:◎ Running post-remove: user:cleanup; post-switch: user:notify; post-merge: user:sync. (#2457) -
Picker-driven
post-switchhooks now receivetarget/target_worktree_pathtemplate variables, matching hooks fired fromwt switch <branch>. Closes a pre-existing asymmetry where interactive switching exposed strictly fewer variables than the non-interactive path. (#2470)
Fixed
-
wt <alias>stdout is pipeable again:wt my-alias | tr …(and any other downstream pipe) silently produced no output because the foreground executor redirected every alias body's stdout to wt's stderr — a hook-only redirect that PR #2089 inherited uniformly. Aliases now pass stdout through; hooks andwt step for-eachkeep the merged-stderr behavior so their output stays ordered with wt's own status messages. (#2479, thanks @davidmyersdev for reporting #2478) -
wt switch <symlink>resolves to the existing worktree instead of failing withNo branch named …. The path-based fallback inRepository::worktree_at_pathpreviously compared paths via lexical normalization only, so symlink-equivalent spellings never matched. The same symlink-aware comparison is now used everywhere the library identifies a worktree by path. (#2466) -
Deleted-CWD recovery handles symlinked subdirectories: When a worktree is removed while a shell sits in a subdirectory whose parents include a symlink (e.g.
~/link/repo.feature/src),wtnow finds the parent repository and recovers as expected. Previously the symlink-aware path compared only file names and bailed for any path deeper than the worktree root. (#2464) -
Merge safety backups for slash branches:
WorkingTree::create_safety_backup()flattened/to-in the ref path, so distinct branches likea/banda-bcollided at the samerefs/wt-backup/a-bref — the latest backup for one could clobber the other, and the documentedrefs/wt-backup/<branch>recovery path didn't match what was actually written. Slashes are valid in git ref names; the branch name is now used as-is. (#2463) -
Nushell wrapper migrates to function-level
@complete: Per fdncred's recommendation in nushell/nushell#18128, the wrapper replaces the parameter-level[...args: string@"nu-complete wt"]with a function-level@completeattribute on an untyped[...args]rest, and the completer signature moves from[context: string](with manualsplit row " "reconstruction) to[spans: list<string>]. Net deletion of seven lines of fragile token reassembly; once nushell/nushell#18131 ships in stable nu the wrapper will automatically benefit from--flag="value"quote stripping and~expansion. (#2458)
Internal
-
Hook dispatch unified: A single
HookAnnouncerorchestrates per-command announces across phases, replacing scatteredCommandOrigin-keyed dispatch with closures, and the various background-hook entry points now share one path. Switch and merge sites assemble template variables through a singleTemplateVarsbuilder. (#2457, #2470, #2472, #2477) -
wt listrendering modes collapse: The internalRenderTargetenum replaces three parallel rendering paths, the JSON path skips the per-result render that the formatter never used, and deadis_ttyplumbing is removed. (#2469, #2473) -
Push handling switches to a
PushKindenum instead of sniffing verb strings (#2468);try_aliasandstep_aliasshare one help-intercept implementation (#2471); lazy template expansion in the command executor lives in one place viaresolve_command_str(#2476).
Install worktrunk 0.46.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/max-sixty/worktrunk/releases/download/v0.46.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.46.0/worktrunk-installer.ps1 | iex"; git-wt config shell installInstall prebuilt binaries via Homebrew
brew install worktrunk && wt config shell installDownload worktrunk 0.46.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