Release Notes
Improved
-
--format=jsonextends to seven more commands:wt step rebase,wt step push,wt step commit,wt step squash,wt step relocate,wt step copy-ignored, andwt hook shownow accept--format=json. Shapes follow the existing pattern (additive on stdout; human prose stays on stderr) and use stable snake_caseoutcomediscriminators where the result has multiple variants. (#2560) -
wt step commitandwt step squashgain--dry-run: Renders the prompt, prints the shell invocation that would call the LLM, calls the LLM and prints the generated message in three labeled sections (PROMPT, COMMAND, MESSAGE), then exits without staging, running hooks, or committing. Forcommit,--stageis honored against a temporary index — the previewed prompt matches what a real run would send the LLM, but the user's real index is never touched.--show-promptis now hidden from--helpbut kept working for piping the rendered prompt to another LLM. (#2557) -
New
dirnameandbasenametemplate filters: Two new filters exposePath::parentandPath::file_name, enabling path traversal that previous filters couldn't express. They unblock the bare-repo-in-hidden-directory layout (myproject/.git), where{{ repo }}resolves to.git: users can write{{ repo_path | dirname | basename }}to recovermyproject. (#2592, #2605, thanks @seakayone for reporting #1279 and @Xilis for raising theparent_dirquestion) -
New
[remove] delete-branchconfig option: Settingdelete-branch = falsedefaultswt removeto keeping branches, equivalent to passing--no-delete-branchevery time. CLI flags still override the config either direction. (#2589, thanks @jameslairdsmith for #2587) -
wt-perf timelinesubcommand for trace capture: One command runswt, captures stderr, parses[wt-trace]records, and prints a column-aligned text timeline (sorted by start time, with subprocess totals and externally-measured wall) or emits Chrome Trace Format JSON for Perfetto. Replaces the previousRUST_LOG=debug wt … 2>&1 | wt-perf trace > trace.jsondance. (#2558) -
wt listskips redundant merge-tree probes on dirty worktrees: For dirty worktrees with no unmerged entries, the dirty-tree probe is authoritative and the HEAD-only probe is skipped — one merge-tree subprocess per dirty row instead of two. The dirty probe also reflects the current working state, so when uncommitted changes resolve a HEAD conflict,wt listno longer reports it as conflicting. (#2602) -
Faster alias dispatch: Two changes compound to cut warm alias-dispatch latency by ~25 ms —
Repository::prewarmoverlaps the three independent pre-dispatch reads (rev-parse, git config, user-config TOML) on scoped threads instead of running them in series, andbuild_hook_contextonly executes the four shell-out blocks (default_branch,primary_worktree,commit/short_commit,remote/remote_url/upstream) when the alias body actually references those template variables. (#2556, #2573) -
Short-SHA display honors
core.abbrev: Sites that abbreviated a commit SHA previously sliced&sha[..7]or ran ad-hocgit rev-parse --shortcalls — 7-char prefixes regularly collide in larger repos and none of the slicing sites respectedcore.abbrev. Thestep commit/step squashsuccess lines, thestep push --no-ff"Merged to" line, the{{ short_commit }}template variable, post-remove hook context, the safety-backup ref display, the orphan-check(detached <sha>)label, andwt listrow display all route through one canonical helper now. (#2576, #2577, #2584) -
Shell-integration hint escalates after repeat showings:
worktrunk.hints.<name>migrates from"true"to an integer counter so the system tracks how many times a hint has been displayed. After 5+ displays of the shell-integration install hint, it appends awt config showpointer so users who keep seeing it can investigate why their wrapper isn't intercepting. Legacy"true"values parse as 0, so the next display normalises to 1; first-time-skip behaviour is unchanged. (#2603) -
Cleaner
wt config showshell-integration section for new users: Several follow-ups smooth the section's first impression. "Not configured" rows render as peer status lines (○) with bold shell name, matchingAlready configuredandSkipped, instead of looking like a sub-bullet. Thetype wtverification hint only fires under the user's actual shell, not under every configured shell. On a stock zsh-only macOS,bash/fish/nuno longer render fourSkipped; ~/.foorc not foundrows — a newShell::is_installed()PATH lookup filters them unless the binary is present. The status text now distinguishes "not configured" (no working integration anywhere) from "not active" (installed but not loaded in this session), with the install hint moved directly under the warning, and theSkippedrow's shell name renders bold to match other status rows. (#2562, #2572, #2574, #2579)
Fixed
-
wt step pruneno longer trips a debug_assert on multi-line git errors: Whengit configfailed mid-prune, the multi-line stderr propagated as a top-level anyhow message with an empty chain — exactly the caseprint_command_error'sdebug_assert!(false, "Multiline error without context")is designed to nag on. Debug builds (includingcargo test) exited 101 instead of rendering the error. Targeted.context(...)wrappers on the prune call sites route prune errors through the structured rendering path. (#2567) -
wt config updateno longer prints a redundantwt config updateself-suggestion: Everywtinvocation against a deprecated config emitted a deprecation warning followed by ato apply updates, run wt config updatehint — silly when the user was already runningwt config update. The update command latches warning suppression beforeRepository::prewarm, then renders per-pattern warnings inline alongside its diff.--printis also fully silent on stderr now, matching its pipe-friendly intent. (#2590) -
wt config showiterates PowerShell uniformly with other shells: PowerShell's status row went through a separate code path, producing a slightly different layout on Windows than on Unix. The shell loop now iterates the full set uniformly, so PowerShell renders the same way asbash/zsh/fish/nu. (#2581)
Internal
-
Library API rework (Breaking library API):
cargo-semver-checksreports several breaking changes — removed public exports (worktrunk::git::interrupt_exit_code/worktrunk::git::exit_codein #2611,worktrunk::shell_exec::trace_instantin #2554, structworktrunk::config::LoadedConfigsin #2573); changed parameter count (worktrunk::config::format_alias_variablesnow takes 2 parameters instead of 1, in #2556); newremovefield onResolvedConfig,UserConfig, andUserProjectOverrides(#2589). -
Typed error variants gain a
Diagnostictrait:Displayis now a single-line label suitable for embedding informat!strings, JSON output, or log files;Diagnostic::renderproduces the styled multi-line block (emoji, color, gutter, follow-up hints). Implemented forGitError,WorktrunkError,HookErrorWithHint,TemplateExpandError, andCommandError. The renderer informat_command_errorwalks the anyhow chain viatry_render_diagnosticonce instead of per-type downcast branches. (#2580, #2611) -
Trace spans carry dynamic context: Alias execution spans carry the alias name (
try_alias:deploy,run_alias:deploy);template_rendercarries the command label; the concurrent-group span moved inside the per-command map so each render emits its own record.Cmd::run/Cmd::pipe_intotrace emission consolidated behindWtTraceLog::record_result. (#2554, #2555, #2613) -
HookLog::Sharedfor branch-agnostic logs: The trash sweep atsweep_stale_trashis repo-wide, butHookLog::path()always prefixed a branch segment, so the call site worked around this by passing a fake"wt"branch. The newShared(InternalOp)variant resolves to{log_dir}/internal/{op}.logdirectly, alongside the other top-level shared logs. (#2595)
Install worktrunk 0.48.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/max-sixty/worktrunk/releases/download/v0.48.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.48.0/worktrunk-installer.ps1 | iex"; git-wt config shell installInstall prebuilt binaries via Homebrew
brew install worktrunk && wt config shell installDownload worktrunk 0.48.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