Release Notes
Improved
-
wt switch --executetakes a program, not a shell string:-xnames one program, with everything after--passed as literal argv. Worktrunk spawns it as a child rather than running it in your interactive shell, so shell functions and itscdno longer reach you.-x sh -- -c '…'recovers shell syntax, not functions. (Breaking: existing-xstrings, plusWORKTRUNK_DIRECTIVE_EXEC_FILEandWORKTRUNK_SHELL.) (#3977, closes #2860, fixes #3944, thanks @omgreenfield for testing the migration path) -
Worktrunk decides tracking for the branches it creates: a new branch gets an upstream only when its name matches the remote branch it starts from, whatever
branch.autoSetupMergesays:--create release --base origin/releasetracks,--create feature --base origin/releasedoes not. UnderautoSetupMerge = falsethis previously exited 128 after creating the worktree. (#3913, #3950, fixes #3937, thanks @mjakl for reporting and diagnosing) -
Retired config keys are no longer read:
commit.generation.template-fileandsquash-template-fileare gone — put the file's contents intemplateorsquash-template. There is no migration: the key stays, warns as unknown on every load, and the prompt reverts to the built-in default. Setting bothtemplateandtemplate-fileused to fail the load; it now loadstemplate.switch.picker.timeout-mslikewise warns rather than being stripped. (Breaking.) (#3949) -
Project aliases and hooks can use
wt switch --execute: their bodies previously refused it. Worktrunk now starts the program itself instead of handing shell text to your shell, and the command-approval gate remains the control on project-defined commands. (#3977) -
Established automation and LLM customization interfaces are now stable:
wt step eval,wt step for-each,wt step prune, LLM branch summaries,wt config state vars, andcommit.generation.template-appendare no longer marked experimental. (#3949) -
wt step prunestages removals concurrently again: only thegit worktree removeteardowns serialize, so dirty checks, fsmonitor shutdown, and the trash rename overlap. Theprune_e2e/livebenchmark median went from 377 ms to 222 ms. (#3954) -
wt config approvals addreads as a review rather than a warning: it opens with a cyanReview 1 command for repo:instead of a yellow▲ … needs approval to execute. The execution-time gate is unchanged. (#3953)
Fixed
-
The
wt switchpicker survives a preview longer than 65,535 lines: skim keeps the pane's line count in au16, so a larger diff abortedwtwith exit 101 seconds after it painted — on screen the picker looked like it closed by itself. Panes now cap at 60,000 lines and say so. (#3959, fixes #3958, thanks @sandertammesoo for reporting and diagnosing) -
The nushell wrapper propagates exit codes without a POSIX shell: it reported a failing
wtby spawningsh, so on Windows every failing command printed aCommand `sh` not foundtrace and exit 1 whatever the real code was. Nushell's wrapper is a static file, so rerunwt config shell installto pick this up. (#3945) -
The picker no longer shows one detached worktree's diff for another: previews were keyed by branch name, so every detached row shared the key
(detached). Rows now key by canonical identity, which also letswt remove feature ~/repo.featureplan that worktree once instead of failing on the second. (#3926) -
wt switch pr:<n>givespre-switchhooks the real branch:branchandtargetheld the literalpr:3933, andtarget_worktree_pathwas unset even when that branch had a worktree.pr_numberandpr_urlare now set for same-repo PRs, not only forks. (#3941, fixes #3934, thanks @robsonpeixoto for reporting) -
wt config shell installno longer replaces an rc file created while it was checking: the missing-file path refuses to clobber and fails with a rerun hint. A dangling rc symlink is preserved and rejected rather than overwritten. (#3929) -
wt switch --create X --base pr:<n>works when the PR branch has no local branch: the fetch writes only the remote-tracking ref, and git won't expand a bare name to one, so the command failed withNo branch, tag, or commit named …. The base is now named under its remote. (#3951) -
wt switch --createstreamsgit worktree addinstead of stalling: where a sandbox denied the timed wait's pipe orsigaction, the command waited out git's entire run and then reportedFailed to wait for commandfor work that had already succeeded. (#3881) -
Claude Code activity markers stay on the session's launch worktree: the plugin's marker hooks pass
-C "$CLAUDE_PROJECT_DIR", so acdmid-session no longer marks another repository. A session launched outside a repository gets no marker. (#3956)
Documentation
-
--executedocuments how to get a variable into a shell body: each position is substituted verbatim, so a variable spliced intosh -ctext is re-parsed by that shell and splits on spaces. The help now shows passing it as a separate argument and referencing it positionally. (#3977) -
The clone-local default-branch override is documented:
wt config state default-branch setwritesworktrunk.default-branchto the clone's local git config — machine-local, never committed, and shared by every linked worktree.setwarns when the branch isn't checked out locally, andwt listskips its comparisons until it is. (#3947, #3948, fixes #3946, thanks @danielo515 for the request) -
The docs site renders code with the CLI's own colors: terminal examples reproduce each snapshot's exact ANSI roles, while command references and the homepage command comparison get clap and shell syntax color from paired light/dark themes. File excerpts gain a path tab, and code wraps instead of scrolling on mobile. (#3936, #3938, #3939, #3942)
-
The
pre-startupstream example uses--base: it showedwt switch --create feature origin/feature, whichwt switchrejects. (#3955)
Internal
-
Library API rework (Breaking library API):
cargo-semver-checksfails ten lints —RemoteRefProviderand its provider structs give way toForgeKinddispatch, the--executerework retires the fish and PowerShellShellEscapeModeescapes andWORKTRUNK_SHELL_ENV_VAR,BranchRefswapsfull_ref/worktree_pathforid, and accessors includingBranch::unset_upstreamandProjectConfig::ci_platformare gone. (#3913, #3926, #3949, #3963, #3977) -
Hook pipelines and
wt listcollection lost two indirection layers: the background pipeline carriesPreparedStepdirectly, and 15 marker task types collapse into one exhaustive dispatch. The synthesized---forcesubmodule path keeps its dirty re-check and destructive command under one lock, so prune's narrower locking doesn't widen that window. (#3964, #3954)
Install worktrunk 0.76.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/max-sixty/worktrunk/releases/download/v0.76.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.76.0/worktrunk-installer.ps1 | iex"; git-wt config shell installInstall prebuilt binaries via Homebrew
brew install worktrunk && wt config shell installDownload worktrunk 0.76.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