v0.58.0

max-sixty/worktrunkv0.58.0Jun 13, 2026by github-actions[bot]

Upgrading?

AI Summary

Improves hook concurrency and CI column visibility, consolidates cache commands, and adds a statusline rate-limit segment.

Key Highlights

  • Table-form `pre-*` hooks now run concurrently
  • CI column shows PR/MR number and review state
  • Consolidated cache command: `wt config state cache`
  • Statusline rate-limit segment shows used percentage near cap

New Features

  • Hook concurrency improvements
  • Enhanced CI column
  • Cache consolidation
  • Statusline rate-limiting

Full Release Notes

## Release Notes

### Improved

- **Table-form `pre-*` hooks run concurrently**: A multi-entry table hook (`[pre-merge]` with several keys) now runs its commands concurrently, completing the cut-over announced in v0.37.0: every hook type has one execution semantic, where table form is concurrent and pipeline form (`[[pre-merge]]` blocks) is serial. Configs that need ordering should use pipeline form; affected configs have warned on every invocation since v0.37.0, with `wt config update` offering a serial-preserving migration. Two adjacent inconsistencies are also gone: `wt hook <post-type>` foreground runs of multi-entry table hooks now run concurrently like their background counterpart, and single-entry table aliases write to stdout like the other alias spellings, so `wt <alias> | …` works for that spelling too. (Breaking: multi-entry table-form `pre-*` hooks no longer run serially) ([#3052](https://github.com/max-sixty/worktrunk/pull/3052))

- **CI column shows the PR/MR number and review state**: The CI column in `wt list --full` and the statusline shows the branch's open PR/MR reference (`#3041` on GitHub/Gitea/Azure DevOps, `!3041` on GitLab) instead of a plain dot: colored by CI status, hyperlinked to the PR, dimmed when stale or draft. Review state folds into the color, with magenta for changes requested and cyan for awaiting review. `wt list --format=json` gains `ci.number` and `ci.review_state`. ([#3041](https://github.com/max-sixty/worktrunk/pull/3041), [#3044](https://github.com/max-sixty/worktrunk/pull/3044))

- **Hook and alias templates render when each step runs**: Templates are syntax-checked before the first step runs and rendered as each step executes, so `{{ vars.* }}` always reads fresh values and hooks and aliases share one expansion model. Two consequences: a pipeline step with an undefined variable fails when that step is reached (earlier steps run first), and a template error in a background hook surfaces in the hook log rather than failing the foreground command. The background runner also labels template errors the way the foreground does. ([#3042](https://github.com/max-sixty/worktrunk/pull/3042), [#3047](https://github.com/max-sixty/worktrunk/pull/3047))

- **`wt config state cache`**: The regenerable caches (CI status, branch summaries, git-command caches, hints, the `wt switch -` target) are consolidated under `wt config state cache`; `cache clear` drops them all without prompting, since everything regenerates. `wt config state clear`, which also wipes hand-authored markers and vars, now asks for confirmation; `--yes` skips, and non-interactive runs without `--yes` cancel. The `ci-status`, `hints`, and `previous-branch` subcommands are deprecated but still work. ([#3027](https://github.com/max-sixty/worktrunk/pull/3027))

- **Statusline rate-limit segment**: Above 90% of the binding window the segment shows the used percentage (`95%(8:30am–1:30pm)`) instead of the pace ratio; near the cap, what's left matters more than the rate. The pace form drops the word "pace" (`2.9×(Tue–Tue 5pm)`), and `-vv` logs each window's inputs and selection to `.git/wt/logs/trace.log` so the binding-window choice can be reconstructed. ([#3057](https://github.com/max-sixty/worktrunk/pull/3057), [#3053](https://github.com/max-sixty/worktrunk/pull/3053), [#3029](https://github.com/max-sixty/worktrunk/pull/3029))

- **`/wt-switch-create` branch name is optional**: The Claude Code plugin command picks a branch name from the task when none is given, and the skill's workflow is one route (create, then enter) with an error-driven fallback instead of three guarded paths. Worktrees created mid-session persist after the session ends. ([#3058](https://github.com/max-sixty/worktrunk/pull/3058))

### Fixed

- **Plugin worktree hooks fail before side effects**: The Claude Code plugin's `WorktreeCreate`/`WorktreeRemove` hooks validate the payload before running `wt`; a malformed payload previously created a branch named `null` or could remove the wrong worktree. `wt remove`'s help now documents that the positional argument accepts a worktree path as well as a branch name. ([#3058](https://github.com/max-sixty/worktrunk/pull/3058), [#3060](https://github.com/max-sixty/worktrunk/pull/3060))

- **Waiting-for-input marker covers questions, permission prompts, and turn end**: The Claude Code plugin sets the 💬 marker on `AskUserQuestion`, permission requests, and turn end. Previously only the `Notification` event set it, which never fires for the built-in question picker (and on some platforms not for permission prompts), so the marker stayed 🤖 while Claude waited. Part of [#2916](https://github.com/max-sixty/worktrunk/issues/2916). ([#3023](https://github.com/max-sixty/worktrunk/pull/3023), thanks @Ismael for reporting)

- **`wt list --help` no longer panics when piped**: With no detectable terminal width (output piped, `COLUMNS` unset), `wt list --help` panicked with a capacity overflow, and the post-commit diffstat truncated filenames to ~10 characters. Both now handle unknown width. ([#3040](https://github.com/max-sixty/worktrunk/pull/3040))

- **Deprecation warnings match `wt config update`**: A config deprecation warning now fires exactly when `wt config update` would change the file. The old detection and migration logic had drifted in several places: `ff` and `no-ff` together silently dropped `no-ff`, a scalar `forge` key was overwritten by the `[ci]` migration, an empty `[ci] platform` migrated without warning, and an empty `approved-commands = []` could be removed by an unrelated update. ([#3055](https://github.com/max-sixty/worktrunk/pull/3055))

- **Migrated `[forge]` keeps `[ci]`'s spot**: The `[ci]` → `[forge]` migration rendered the new section at the end of the file and could drop comments above `[ci]`; it now takes over `[ci]`'s position, comments included, so `wt config show` and `wt config update` diffs stay minimal. ([#3051](https://github.com/max-sixty/worktrunk/pull/3051))

- **`wt config state get` is read-only**: The aggregate dump resolved (and re-cached) the default branch, so running it right after `clear` silently repopulated the cache, and on a cold clone it could hit the network. It now reports the cached value or `(none)`. `wt config state default-branch get` still resolves and caches. ([#3024](https://github.com/max-sixty/worktrunk/pull/3024))

### Documentation

- **Reading vs resolving cached state**: `wt config state default-branch get` resolves and caches; the aggregate `wt config state get` only reports the cache. The help text and module docs now state the split. ([#3028](https://github.com/max-sixty/worktrunk/pull/3028))

### Internal

- `wt switch`/`wt remove` orchestration moved from `main.rs` to their command modules, and the hook execution call chain lost two delegation layers. ([#3049](https://github.com/max-sixty/worktrunk/pull/3049), [#3036](https://github.com/max-sixty/worktrunk/pull/3036))

- Config deprecations are driven by a single rule table; each rule is one function that migrates and reports what it changed. ([#3045](https://github.com/max-sixty/worktrunk/pull/3045), [#3055](https://github.com/max-sixty/worktrunk/pull/3055))

- `terminal_width()` returns `Option<usize>` instead of a `usize::MAX` sentinel, making the no-width case a compile-time concern. ([#3043](https://github.com/max-sixty/worktrunk/pull/3043))

- Snapshot tests regenerate identically across machines: host-specific paths are guarded, host-dependent env-block markers are normalized, and help snapshots share one settings builder. ([#3009](https://github.com/max-sixty/worktrunk/pull/3009), [#3026](https://github.com/max-sixty/worktrunk/pull/3026), [#3037](https://github.com/max-sixty/worktrunk/pull/3037), [#3061](https://github.com/max-sixty/worktrunk/pull/3061))

- Nightly CI runs lib tests across the full feature powerset. ([#3059](https://github.com/max-sixty/worktrunk/pull/3059))

- MSRV bumped from 1.94 to 1.95. ([#2948](https://github.com/max-sixty/worktrunk/pull/2948))

## Install worktrunk 0.58.0

### Install prebuilt binaries via shell script

```sh
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/max-sixty/worktrunk/releases/download/v0.58.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.58.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.58.0

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