v0.45.0

max-sixty/worktrunkv0.45.0Apr 27, 2026by github-actions[bot]

Upgrading?

AI Summary

Major release adding progress spinners for large file operations, remote-only base support, and exposing the LLM summary cache in configuration.

Key Highlights

  • `wt remove --foreground` and `wt step copy-ignored` now show TTY progress spinners.
  • `wt switch -c <new> --base <name>` now accepts remote-only branches.
  • LLM `wt step commit` summaries are now surfaced in `wt config state`.
  • Three on-disk caches (sha_cache, ci_status, summary) unified onto a shared module.

Breaking Changes

  • Library API: `Repository::clear_git_commands_cache` and `Repository::git_commands_cache_count` removed.
  • Library API: `copy_dir_recursive` now takes 4 parameters instead of 3.
  • Library API: `copy_leaf` now returns `Result<Option<u64>>` instead of `Result<bool>`.

New Features

  • TTY progress spinners for verbose removal and copying operations.
  • Remote-only base branch support in switch commands.
  • Exposure of LLM summary cache via `wt config state`.

Full Release Notes

## Release Notes

### Improved

- **`wt remove --foreground` shows a TTY progress spinner**: Removing a worktree with a fat `node_modules` (or any large trash payload) now prints `⠼ Removing 7,272 files · 64.5 MiB` to stderr while the unlink proceeds, with a matching `(N files · X MiB)` suffix on the success line. TTY-gated; pipes and the background path are byte-for-byte unchanged. Driven by the same machinery introduced for `wt step copy-ignored` in [#2413](https://github.com/max-sixty/worktrunk/pull/2413). ([#2420](https://github.com/max-sixty/worktrunk/pull/2420))

- **`wt step copy-ignored` shows a TTY progress spinner**: Large copies of `node_modules`, `build/`, or `target/` previously ran silently. A stderr-only spinner (`⠼ Copying 7,272 files · 64.5 MiB`) ticks while the copy proceeds, gated on TTY + `verbosity == 0` + not `--dry-run`, with a 300ms startup delay so sub-second copies stay quiet. ([#2413](https://github.com/max-sixty/worktrunk/pull/2413), thanks @tehdb for the suggestion)

- **`wt switch -c <new> --base <name>` accepts a remote-only base**: `--base releases/4.x.x` previously failed with `No branch, tag, or commit named "releases/4.x.x"` when the branch existed only as a remote-tracking ref. The bare name now resolves through the single matching remote (the existing safety code still unsets the new branch's upstream so a stray `git push` doesn't target the base). Multi-remote and zero-remote cases pass through unchanged. ([#2411](https://github.com/max-sixty/worktrunk/pull/2411), thanks @viicslen for reporting [#2410](https://github.com/max-sixty/worktrunk/issues/2410))

- **LLM `wt step commit` summaries surfaced in `wt config state`**: `wt config state get` now includes a `SUMMARY CACHE` table (and JSON section) listing per-branch entries, and `wt config state clear` removes them alongside markers/vars/CI status. Backed by a new content-addressed layout at `.git/wt/cache/summary/{branch}/{hash}.json` so a cache hit is a single file-existence check. ([#2407](https://github.com/max-sixty/worktrunk/pull/2407))

### Fixed

- **`wt config state clear` no longer reports "Cleared 0" when an I/O or config error actually occurred**: Across markers, vars, previous-branch, default-branch, and CI-status (single + aggregate), eleven `unwrap_or(false)` / `let _ = unset_config(...)` swallows silently turned real failures into "nothing to clear" messages. Genuine `git config --unset` failures and `read_dir`/`remove_file` errors now surface; the common "key didn't exist" exit-5 path stays silent. The shared `clear_*` machinery for the on-disk caches is now consolidated in `worktrunk::cache`. ([#2394](https://github.com/max-sixty/worktrunk/pull/2394), [#2400](https://github.com/max-sixty/worktrunk/pull/2400))

- **`wt config state ci-status clear <branch>` actually clears the cache file**: The single-branch path was still calling `unset_config("worktrunk.state.<branch>.ci-status")` from before the cache moved to `.git/wt/cache/ci-status/<branch>.json`. The command always took the info branch and never touched the real cache; `--all` was already correct. ([#2392](https://github.com/max-sixty/worktrunk/pull/2392))

- **`wt config state get/clear ci-status` for `origin/foo`-style branches when a same-named local branch exists**: A local branch literally named `origin/foo` would shadow the remote-tracking ref — `is_remote` resolved against the remote while the SHA used for cache keys came from the local branch, so `gh`/`glab` was invoked for the remote while the cache tracked the local. A single `for-each-ref` query now sources `is_remote`, the short name, and the HEAD SHA from the same ref. Tags and raw SHAs passed via `--branch` now return `BranchNotFound` instead of being accepted as "local branches" with nonsensical CI lookups. ([#2388](https://github.com/max-sixty/worktrunk/pull/2388))

### Documentation

- **`worktrunk.dev/llms.txt` plus `.md` companions for every page**: Each docs page is now also served as clean markdown at `worktrunk.dev/<page>.md`, with an `llms.txt` index per the [llms.txt spec](https://llmstxt.org/) so LLM tools can find the docs without scraping HTML. ([#2404](https://github.com/max-sixty/worktrunk/pull/2404))

- **Static command-output blocks for the GIF-heavy docs pages**: `merge`, `step`, `remove`, `hook`, and `llm-commits` now include realistic colorized command-output blocks driven by insta snapshots, alongside (or instead of) the GIFs — so they stay in lockstep with what `wt` actually prints. ([#2405](https://github.com/max-sixty/worktrunk/pull/2405), thanks @drewnoakes for reporting [#2403](https://github.com/max-sixty/worktrunk/issues/2403))

- **Conda / Pixi installation listed in the install section**: The README and worktrunk-page install table now mention the conda-forge package alongside Homebrew, Cargo, winget, and pacman. ([#2425](https://github.com/max-sixty/worktrunk/pull/2425), thanks @noamgot for reporting [#2424](https://github.com/max-sixty/worktrunk/issues/2424))

- **FAQ documents the new summary cache layout**: The "What files does Worktrunk create?" inventory now includes the `.git/wt/cache/summary/{branch}/{hash}.json` LLM-summary cache. ([#2408](https://github.com/max-sixty/worktrunk/pull/2408))

### Internal

- **Three on-disk caches unified onto a shared `worktrunk::cache` module**: `sha_cache`, `ci_status`, and the new `summary` cache now share one implementation of torn-write semantics, error policy, LRU sweep, and clear mechanics. The `summaries/` directory is renamed `summary/` to match the singular-operation convention used by every other kind (`ci-status`, `is-ancestor`, etc.); stale `summaries/` dirs are harmless. (Breaking library API: `Repository::clear_git_commands_cache` and `Repository::git_commands_cache_count` removed; `worktrunk::copy::copy_dir_recursive` now takes 4 parameters instead of 3 and `worktrunk::copy::copy_leaf` now returns `Result<Option<u64>>` instead of `Result<bool>` to thread the progress reporter.) ([#2407](https://github.com/max-sixty/worktrunk/pull/2407), [#2420](https://github.com/max-sixty/worktrunk/pull/2420))

- **`Repository::root()` no longer caches the fallback path** for callers outside any work tree, dropping the dedicated `prewarm_is_inside` sentinel cache — `worktree_roots.contains_key(path)` is now a reliable "path is inside a work tree" signal. No external behavior change. ([#2390](https://github.com/max-sixty/worktrunk/pull/2390))

- **MSRV bumped from 1.93 to 1.94** following the latest stable − 1 policy. ([#2423](https://github.com/max-sixty/worktrunk/pull/2423))

- **Claude Code plugin now uses the commit SHA for versioning**: The static `version: 1.0.0` in the plugin manifest hadn't moved despite ongoing changes to skills and hooks. Removing it lets Claude Code use the commit SHA, so every commit becomes an update for installed users. ([#2402](https://github.com/max-sixty/worktrunk/pull/2402))

- **Docs-sync pipeline simplification**: `--help-page` plain/web paths unified behind `PageMode` ([#2412](https://github.com/max-sixty/worktrunk/pull/2412)); blank-line corruption in mixed `$ cmd + output` blocks fixed at the root in `convert_dollar_console_to_terminal` and the `MARKER_OPEN_PREFIX`/`MARKER_CLOSE` constants extracted ([#2417](https://github.com/max-sixty/worktrunk/pull/2417), [#2418](https://github.com/max-sixty/worktrunk/pull/2418)); three sync tests collapsed into `test_docs_are_in_sync` and dead inner snapshot wrappers stripped ([#2419](https://github.com/max-sixty/worktrunk/pull/2419)); mirrored close form retired in favour of bare with a `test_no_nested_auto_generated_markers` invariant guard ([#2422](https://github.com/max-sixty/worktrunk/pull/2422)); two more sync helpers aligned with the per-file error channel ([#2427](https://github.com/max-sixty/worktrunk/pull/2427)); `write_tracked` helper extracted and 14 auto-generated outputs marked `linguist-generated=true` so PR diffs collapse them ([#2409](https://github.com/max-sixty/worktrunk/pull/2409)). `running-tend` skill leads bug-triage asks with `wt -vv <command>` so a single gist URL replaces multi-step diagnostic chains ([#2415](https://github.com/max-sixty/worktrunk/pull/2415), thanks @viicslen for the feedback in [#2410](https://github.com/max-sixty/worktrunk/issues/2410)).

- **`CiBranchName::from_branch_ref` takes `&BranchRef`** instead of `(&str, bool)`, removing the historical "string from one source, bool from another" footgun. ([#2391](https://github.com/max-sixty/worktrunk/pull/2391))

## Install worktrunk 0.45.0

### Install prebuilt binaries via shell script

```sh
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/max-sixty/worktrunk/releases/download/v0.45.0/worktrunk-installer.sh | sh && wt config shell install
```

### Install prebuilt binaries via powershell script

```sh
powershell -ExecutionPolicy Bypass -c "irm https://github.com/max-sixty/worktrunk/releases/download/v0.45.0/worktrunk-installer.ps1 | iex"; git-wt config shell install
```

### Install prebuilt binaries via Homebrew

```sh
brew install worktrunk && wt config shell install
```

## Download worktrunk 0.45.0

|  File  | Platform | Checksum |
|--------|----------|----------|
| [worktrunk-aarch64-apple-darwin.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.45.0/worktrunk-aarch64-apple-darwin.tar.xz) | Apple Silicon macOS | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.45.0/worktrunk-aarch64-apple-darwin.tar.xz.sha256) |
| [worktrunk-x86_64-apple-darwin.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.45.0/worktrunk-x86_64-apple-darwin.tar.xz) | Intel macOS | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.45.0/worktrunk-x86_64-apple-darwin.tar.xz.sha256) |
| [worktrunk-x86_64-pc-windows-msvc.zip](https://github.com/max-sixty/worktrunk/releases/download/v0.45.0/worktrunk-x86_64-pc-windows-msvc.zip) | x64 Windows | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.45.0/worktrunk-x86_64-pc-windows-msvc.zip.sha256) |
| [worktrunk-aarch64-unknown-linux-musl.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.45.0/worktrunk-aarch64-unknown-linux-musl.tar.xz) | ARM64 MUSL Linux | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.45.0/worktrunk-aarch64-unknown-linux-musl.tar.xz.sha256) |
| [worktrunk-x86_64-unknown-linux-musl.tar.xz](https://github.com/max-sixty/worktrunk/releases/download/v0.45.0/worktrunk-x86_64-unknown-linux-musl.tar.xz) | x64 MUSL Linux | [checksum](https://github.com/max-sixty/worktrunk/releases/download/v0.45.0/worktrunk-x86_64-unknown-linux-musl.tar.xz.sha256) |



### Install via Cargo

```sh
cargo install worktrunk && wt config shell install
```

### Install via Winget (Windows)

```sh
winget install max-sixty.worktrunk && git-wt config shell install
```

### Install via AUR (Arch Linux)

```sh
paru worktrunk-bin && wt config shell install
```

Related Repositories