# Changelog
## 0.18.2
### Improved
- **PR/MR context display**: `wt switch pr:N` and `mr:N` now show PR/MR details (title, author, state, URL) after fetching. ([#782](https://github.com/max-sixty/worktrunk/pull/782))
- **Fork PR branch conflicts**: When a fork PR's branch name conflicts with an existing local branch (e.g., contributor opens PR from their `main`), worktrunk now creates a prefixed branch like `contributor/main` instead of failing. Closes [#714](https://github.com/max-sixty/worktrunk/issues/714). (thanks @vimtor for reporting)
### Fixed
- **Help output formatting**: Fixed double blank lines appearing after demo comments in help output. ([#795](https://github.com/max-sixty/worktrunk/pull/795))
- **Error handling reliability**: Replaced fragile string-based error parsing with structured approaches for git stash, GitHub CLI, and GitLab CLI operations. ([#787](https://github.com/max-sixty/worktrunk/pull/787))
### Documentation
- **ci-status help text**: Improved clarity of the ci-status configuration documentation. ([#794](https://github.com/max-sixty/worktrunk/pull/794))
- **wt remove help text**: Simplified short description and added documentation for `pre-remove` and `post-remove` hooks. ([#792](https://github.com/max-sixty/worktrunk/pull/792))
- **Subcommand documentation**: Fixed generated website docs for subcommands (like `wt step copy-ignored`, `wt config state`) to include their short descriptions. ([#793](https://github.com/max-sixty/worktrunk/pull/793))
## 0.18.1
### Fixed
- **Submodule worktree paths**: Worktrees are now created in the correct location when running inside a git submodule. Previously, worktrees were created relative to the parent repo's `.git/modules/` directory instead of the submodule's working directory. ([#762](https://github.com/max-sixty/worktrunk/pull/762), thanks @lajarre; [#777](https://github.com/max-sixty/worktrunk/issues/777), thanks @mhonsel for reporting)
- **Shell integration warnings**: Warnings about shell integration now check if the *current* shell has integration configured, not whether *any* shell does. This fixes misleading "shell requires restart" messages when e.g. bash had integration but the user was running fish. ([#772](https://github.com/max-sixty/worktrunk/pull/772))
- **"Not found" error messages**: Improved error message phrasing — "No branch named X" instead of "Branch X not found", "Branch X has no worktree" instead of "No worktree found for branch X". Context-appropriate hints now appear (e.g., `wt remove` no longer suggests `--create`). ([#774](https://github.com/max-sixty/worktrunk/pull/774))
### Internal
- Unified PR/MR reference resolution, reducing code duplication. ([#778](https://github.com/max-sixty/worktrunk/pull/778))
## 0.18.0
### Improved
- **Post-remove hook**: New hook type runs after worktree removal. Template variables (`{{ branch }}`, `{{ worktree_path }}`, `{{ commit }}`) reference the removed worktree, enabling cleanup scripts for containers, servers, or other resources. ([#757](https://github.com/max-sixty/worktrunk/pull/757))
- **Graceful handling of missing worktree directories**: `wt remove` now prunes stale git metadata when the worktree directory was deleted externally (e.g., `rm -rf`), making the command more idempotent. Fixes [#724](https://github.com/max-sixty/worktrunk/issues/724). (thanks @strangemonad for reporting)
- **Config validation warnings at load time**: Unknown fields in config files (typos like `[commit-gen]` instead of `[commit-generation]`) now show warnings immediately instead of only in `wt config show`. ([#758](https://github.com/max-sixty/worktrunk/pull/758))
### Fixed
- **Age column shows "future" on NixOS/direnv**: `wt list` no longer uses `SOURCE_DATE_EPOCH` for time calculations, which NixOS and direnv commonly set to past timestamps for reproducible builds. Fixes [#763](https://github.com/max-sixty/worktrunk/issues/763). (thanks @ngotchac for reporting)
- **CI status with URL-based pushremote**: CI detection now works when `branch.<name>.pushremote` is set to a URL directly (as `gh pr checkout` does) instead of a remote name. ([#769](https://github.com/max-sixty/worktrunk/pull/769))
- **GitLab nested groups in URL parsing**: URLs like `gitlab.com/group/subgroup/repo` now correctly identify `repo` as the repository name instead of `subgroup`. This was a security fix — previously, approval bypass was possible across sibling repos in the same parent group. ([#768](https://github.com/max-sixty/worktrunk/pull/768))
- **GitLab CI status detection**: Fixed multiple issues with `glab` CLI compatibility — MR lookup now uses two-step resolution, "manual" pipelines show as running instead of failed, and rate limit errors are handled properly. Fixes [#764](https://github.com/max-sixty/worktrunk/issues/764). (thanks @ngotchac for reporting)
### Internal
- Refactored accessor functions to use bare nouns per Rust convention. ([#765](https://github.com/max-sixty/worktrunk/pull/765))
- Clarified target/integration naming across codebase. ([#755](https://github.com/max-sixty/worktrunk/pull/755))
## 0.17.0
### Improved
- **Per-project config overrides** (Experimental): Override settings per-project in user config. Supports `worktree-path`, `commit-generation`, `list`, `commit`, and `merge` sections. Config precedence: CLI arg > project config > global config > default. Closes [#596](https://github.com/max-sixty/worktrunk/issues/596). ([#749](https://github.com/max-sixty/worktrunk/pull/749))
- **Search all remotes for branch existence**: Branch existence checks and completions now search all remotes instead of just the primary remote, matching git's behavior. When a branch exists on multiple remotes, completions show all of them (e.g., `feature ⇣ 2d origin, upstream`). ([#744](https://github.com/max-sixty/worktrunk/pull/744))
- **CI detection for fork workflows**: CI status detection now searches all remotes and uses `gh config get git_protocol` / `glab config get git_protocol` for fork URL protocol preference instead of inferring from existing remotes. ([#753](https://github.com/max-sixty/worktrunk/pull/753))
### Fixed
- **Same-repo PR switching with stale refs**: `wt switch pr:N` for same-repo PRs now fetches the branch before validation, fixing "Branch not found" errors when local refs were stale. ([#742](https://github.com/max-sixty/worktrunk/pull/742))
- **Project identifier collision for repos without remotes**: Repos without remotes now use their full canonical path as the project identifier instead of just the directory name, preventing approval collisions between unrelated repos (e.g., `~/work/myproject` vs `~/personal/myproject`). Users with remoteless repos will need to re-approve commands. ([#747](https://github.com/max-sixty/worktrunk/pull/747))
### Internal
- Cross-platform path handling improvements using `path-slash` crate and `Path::file_name()`. ([#750](https://github.com/max-sixty/worktrunk/pull/750))
- Renamed `WorktrunkConfig` to `UserConfig` internally. ([#746](https://github.com/max-sixty/worktrunk/pull/746))
## 0.16.0
### Improved
- **Background hook verbosity**: Background hooks (post-start, post-switch) now show a single-line summary by default instead of per-hook output. Use `-v` to see detailed output with expanded commands. We're open to feedback on this change — let us know in [#690](https://github.com/max-sixty/worktrunk/issues/690). (thanks @clutchski for reporting)
### Internal
- Fixed dead Apple documentation link in copy-ignored rationale. ([#743](https://github.com/max-sixty/worktrunk/pull/743))
## 0.15.5
### Fixed
- **Hook execution order**: Hooks now run in the order defined in the config file. Previously, HashMap iteration randomized the order. Fixes [#737](https://github.com/max-sixty/worktrunk/issues/737). (thanks @ngotchac for reporting)
## 0.15.4
### Improved
- **Git progress for slow worktree creation**: When `git worktree add` takes more than 400ms (common on large repos), worktrunk now shows a progress message and streams git's output instead of going silent. ([#725](https://github.com/max-sixty/worktrunk/pull/725))
- **Verbose template expansion output**: `-v` now shows template expansion details: the template, expanded command, and any undefined variables with SemiStrict fallback behavior. ([#712](https://github.com/max-sixty/worktrunk/pull/712))
- **Shell integration hint for explicit path invocation**: When running wt via explicit path (e.g., `./target/debug/wt`) with shell integration configured, the warning now suggests running `wt switch <branch>` to use the shell-wrapped command. ([#721](https://github.com/max-sixty/worktrunk/pull/721))
### Fixed
- **Unsafe upstream when creating branch from remote base**: `wt switch --create feature --base=origin/main` no longer sets up tracking to origin/main, preventing accidental pushes to the base branch. Fixes [#713](https://github.com/max-sixty/worktrunk/issues/713). (thanks @kfirba)
- **Credential redaction in debug logs**: URLs with embedded credentials (e.g., `https://token@github.com/...`) are now redacted in `-vv` debug output. ([#718](https://github.com/max-sixty/worktrunk/pull/718))
- **Hook preview shows template on expansion failure**: `wt hook show --expanded` now displays both the error message and original template when expansion fails, instead of hiding the template. ([#722](https://github.com/max-sixty/worktrunk/pull/722))
### Documentation
- **Homebrew install uses core tap**: Install command updated from `max-sixty/worktrunk/wt` to `worktrunk`. ([#716](https://github.com/max-sixty/worktrunk/pull/716), thanks @chenrui333)
- **Hook docs reordered**: post-start (background) is now the recommended default, with post-create for blocking dependencies. ([#733](https://github.com/max-sixty/worktrunk/pull/733))
### Internal
- Simplified GitHub/GitLab CI status detection. ([#730](https://github.com/max-sixty/worktrunk/pull/730))
- Previous worktree gutter changed from `-` to `+` for visual consistency. ([#699](https://github.com/max-sixty/worktrunk/pull/699))
## 0.15.3
### Fixed
- **`--execute` command display**: Shows the expanded command in a gutter with path context instead of showing the raw template before expansion. ([#708](https://github.com/max-sixty/worktrunk/pull/708))
- **CRLF line endings in error display**: Multiline errors with Windows (`\r\n`) or old Mac (`\r`) line endings now display correctly instead of falling through to single-line handling. ([#707](https://github.com/max-sixty/worktrunk/pull/707))
### Documentation
- **Arch Linux install via AUR**: Added installation instructions and shell integration command. ([#709](https://github.com/max-sixty/worktrunk/pull/709), [#561](https://github.com/max-sixty/worktrunk/pull/561), thanks @razor-x)
## 0.15.2
### Improved
- **`wt config shell completions <shell>`**: Generate static shell completion scripts for package managers and custom installation. ([#701](https://github.com/max-sixty/worktrunk/pull/701), thanks @chenrui333)
- **Debug logging threshold**: Now requires `-vv` instead of `-v` for debug logging and diagnostic file generation, freeing `-v` for future use. ([#702](https://github.com/max-sixty/worktrunk/pull/702))
### Fixed
- **Fork PR fetching**: `wt switch pr:N` now works when `origin` points to a fork by fetching PR refs from the upstream remote. Shows actionable error with `git remote add` command if upstream remote is missing. ([#704](https://github.com/max-sixty/worktrunk/pull/704))
- **Fork PR branch naming**: Fork PR branches now use the original branch name (e.g., `feature-fix`) instead of `owner/feature-fix`, so `git push` works correctly. ([#706](https://github.com/max-sixty/worktrunk/pull/706))
- **Config race conditions**: File locking prevents corruption when multiple `wt` processes modify config simultaneously. ([#693](https://github.com/max-sixty/worktrunk/pull/693))
- **Nested worktree detection**: Current worktree indicator (`@`) now shows on the correct worktree when worktrees are nested (e.g., `.worktrees/` layout inside repo). ([#697](https://github.com/max-sixty/worktrunk/pull/697))
- **Symlink path resolution**: Worktree commands work correctly on systems with symlinks (e.g., macOS `/var` → `/private/var`). ([#696](https://github.com/max-sixty/worktrunk/pull/696))
- **Pre-remove hook failures**: Shell no longer cd's to main worktree when pre-remove hooks fail, leaving user in their current location. ([#692](https://github.com/max-sixty/worktrunk/pull/692))
- **PowerShell completion robustness**: Completion registration errors no longer break the shell wrapper function. ([#674](https://github.com/max-sixty/worktrunk/pull/674))
### Documentation
- Added missing `orphan` (`∅`) symbol and `no_worktree` state to JSON output documentation. ([#687](https://github.com/max-sixty/worktrunk/pull/687))
- Clarified Unicode handling in shell detection. ([#700](https://github.com/max-sixty/worktrunk/pull/700))
### Internal
- Refactored large files into focused modules. ([#688](https://github.com/max-sixty/worktrunk/pull/688))
- Consolidated integration reason computation into Repository method. ([#689](https://github.com/max-sixty/worktrunk/pull/689))
- Added verbose level tracking infrastructure for future `-v` output. ([#703](https://github.com/max-sixty/worktrunk/pull/703))
- PowerShell template uses `WORKTRUNK_BIN` for test isolation. ([#674](https://github.com/max-sixty/worktrunk/pull/674))
## 0.15.1
### Improved
- **`wt config show` diagnostics**: When shell integration is not active, now shows how the command was invoked, the binary path (if different), and `$SHELL` environment variable. Helps diagnose setup issues. ([#683](https://github.com/max-sixty/worktrunk/pull/683))
- **Help pager follows git convention**: `-h` never opens a pager, `--help` uses pager when available. Closes [#583](https://github.com/max-sixty/worktrunk/issues/583). ([#651](https://github.com/max-sixty/worktrunk/pull/651), thanks @razor-x)
- **Verbose mode logging**: `-v` now logs command stdout/stderr and all spawned processes including background hooks, `wt for-each` commands, and shell probes. ([#680](https://github.com/max-sixty/worktrunk/pull/680))
### Documentation
- **FAQ reordered**: Questions now ordered by frequency and importance.
### Internal
- **AUR package**: Worktrunk now published to Arch Linux AUR on each release. ([#585](https://github.com/max-sixty/worktrunk/pull/585), thanks @razor-x)
- **Codecov Test Analytics**: Integration tests now report to Codecov Test Analytics. ([#682](https://github.com/max-sixty/worktrunk/pull/682))
## 0.15.0
### Improved
- **`wt switch pr:<number>` syntax** (experimental): Switch directly to a GitHub PR by number. Same-repo PRs delegate to normal switch flow; fork PRs fetch from refs/pull/N/head and configure pushRemote. ([#673](https://github.com/max-sixty/worktrunk/pull/673), closes [#657](https://github.com/max-sixty/worktrunk/issues/657), thanks @wladpaiva for requesting)
- **`--force` hint for dirty worktrees**: When `wt remove` fails due to uncommitted changes, the hint now shows the full command: `wt remove <branch> --force`. ([#671](https://github.com/max-sixty/worktrunk/pull/671))
### Documentation
- **Windows install guidance**: Winget as recommended install (ships `git-wt` by default), plus the App Execution Aliases workaround to use `wt` directly. Closes [#133](https://github.com/max-sixty/worktrunk/issues/133). (thanks @ctolkien for reporting, @shanselman for the aliases tip, @Farley-Chen for [#648](https://github.com/max-sixty/worktrunk/pull/648))
- **Caddy subdomain routing pattern**: Clean URLs like `feature-auth.myproject.lvh.me` via Caddy reverse proxy with dynamic route registration.
- **tmux session per worktree pattern**: Dedicated tmux session with multi-pane layout per worktree.
## 0.14.2
### Fixed
- **`wt remove --force` works with dirty worktrees**: The `--force` flag was documented to allow removal with uncommitted changes, but worktrunk's own cleanliness check blocked it before git could apply the flag. Fixes [#658](https://github.com/max-sixty/worktrunk/issues/658). (thanks @pedro93)
- **Correct output when switching to existing local branch**: When switching to a local branch that tracks a remote, worktrunk incorrectly reported "Created branch X" instead of "Created worktree for X". Now only reports branch creation when git's DWIM actually creates a new tracking branch from a remote. Fixes [#656](https://github.com/max-sixty/worktrunk/issues/656). (thanks @guidupuy-ws)
- **PowerShell handles multiple `wt.exe` binaries**: On Windows, when both Windows Terminal's `wt.exe` and worktrunk's `wt.exe` exist in PATH, shell integration errored with "Cannot convert 'System.Object[]' to the type 'System.String'". Now correctly uses the first match. Relates to [#648](https://github.com/max-sixty/worktrunk/issues/648). (thanks @Farley-Chen)
## 0.14.1
### Improved
- **`--base` accepts commit-ish refs**: `wt switch --create --base` now accepts HEAD, tags, commit SHAs, and relative refs (e.g., `HEAD~2`), not just branch names. Fixes [#630](https://github.com/max-sixty/worktrunk/issues/630). (thanks @myhau)
- **Upfront validation for target refs**: `wt merge` and `wt step` commands now validate target refs before approval prompts, giving clearer "Branch X not found" errors immediately.
- **Visual hierarchy in help**: Section dividers, improved heading structure, and sentence case in `--help` output.
### Fixed
- **macOS shell freeze during `copy-ignored`**: Atomic `clonefile()` on directories saturated disk I/O, blocking shell startup. Now uses per-file reflink which is slower but keeps the system responsive.
- **`copy-ignored` no longer copies nested worktrees**: When `worktree-path` places worktrees inside the main worktree, `copy-ignored` now skips them. Also now copies symlinks (fixes `node_modules/.bin/` etc.). Fixes [#641](https://github.com/max-sixty/worktrunk/issues/641). (thanks @razor-x)
- **Context-aware hints for `wt config create`**: Hints now suggest relevant next steps based on which configs exist.
## 0.14.0
### Improved
- **`worktree_path_of_branch(branch)` template function**: Look up the filesystem path of any branch's worktree in hooks. Enables copying files between worktrees: `setup = "cp {{ worktree_path_of_branch('main') }}/config.local {{ worktree_path }}"`. Returns empty string if no worktree exists for the branch.
- **Per-task timeout for `wt list`**: Configure timeout for git operations via `[list] timeout-ms` in user config. Shows timeout count in footer. Use `--full` to disable timeout for complete data collection.
- **Atomic COW directory cloning on macOS**: `wt step copy-ignored` uses `clonefile()` syscall on APFS for O(1) directory cloning instead of file-by-file copying. ~12-15x faster for large directories like `target/`.
- **Template variable renamed**: `main_worktree_path` → `primary_worktree_path` for clarity. Old name still works with deprecation warning.
### Fixed
- **`wt step copy-ignored` in bare repositories**: Fixed "this operation must be run in a work tree" error when using bare repo setups. Closes [#598](https://github.com/max-sixty/worktrunk/issues/598). (thanks @sbennett33 for reporting)
### Internal
- **Help system extraction**: Moved help and invocation utilities from main.rs to dedicated modules.
- **`wt list` model refactor**: Split monolithic model.rs into modular directory structure.
## 0.13.4
### Fixed
- **LESS flag concatenation with long options**: Fixed "invalid option" error when users have long options in LESS (e.g., `LESS=--mouse`). The pager auto-quit feature from v0.13.1 now correctly separates flags. Fixes [#594](https://github.com/max-sixty/worktrunk/issues/594). (thanks @tnlanh for reporting)
### Internal
- **Homebrew formula generation**: Release workflow now uses cargo-dist for Homebrew formula generation, simplifying the release process.
## 0.13.2
### Improved
- **Validate before approval prompts**: `wt switch` and `wt remove` now validate operations before prompting for hook approval, so users don't approve hooks for operations that will fail.
### Fixed
- **Homebrew formula SHA256 hashes**: Fixed release workflow that was setting incorrect checksums for Intel and Linux binaries, causing `brew install` to fail. Fixes [#589](https://github.com/max-sixty/worktrunk/issues/589). (thanks @kobrigo for reporting)
## 0.13.1
### Fixed
- **Pager auto-quit**: Help text now auto-quits when it fits on screen, even when `LESS` is set without the `F` flag (common with oh-my-zsh's `LESS=-R` default). Fixes [#583](https://github.com/max-sixty/worktrunk/issues/583). (thanks @razor-x for reporting)
- **`--create` hint for remote branch shadowing**: Improved recovery hint when `--create` shadows a remote branch — now shows the full recovery command.
## 0.13.0
### Improved
- **`wt list` parallelization improvements**: Better parallelization of worktree operations reduce latency in some conditions. Respects `RAYON_NUM_THREADS` environment variable for controlling parallelism.
- **Template variables in `--execute`**: Hook template variables (`{{ branch }}`, `{{ worktree_path }}`, etc.) are now expanded in `--execute` commands and trailing args. With `--create`, `{{ base }}` and `{{ base_worktree_path }}` are also available.
- **Fish shell Homebrew compatibility**: Fish shell integration now installs to `~/.config/fish/functions/wt.fish` instead of `conf.d/`, ensuring PATH is fully configured before the wt function loads. `wt config show` detects legacy installations and `wt config shell install` handles migration automatically. ([#586](https://github.com/max-sixty/worktrunk/issues/586) — thanks @ekans & @itzlambda)
- **Chrome Trace Format export**: Performance traces can be exported for analysis with Chrome's trace viewer or Perfetto.
- **`--dry-run` flag for shell commands**: `wt config shell install` and `wt config shell uninstall` now support `--dry-run` to preview changes without prompting.
- **Nested subcommand suggestions**: When typing `wt squash` instead of `wt step squash`, the error now suggests the correct command path.
- **Orphan branch indicator**: `wt list` shows `∅` (empty set) for orphan branches with no common ancestor to the default branch.
- **Improved `-vv` diagnostic workflow**: Bug reporting hint now uses a gist workflow to avoid URL length limits.
### Fixed
- **`wt switch --create --base` error message**: Now correctly identifies the invalid base branch instead of the target branch. Fixes [#562](https://github.com/max-sixty/worktrunk/issues/562). (thanks @fablefactor)
- **AheadBehind column loading indicator**: Shows `⋯` when not yet loaded instead of appearing empty, distinguishing loading state from "in sync".
- **Post-merge hook failure output**: Simplified error messages and removed confusing `--no-verify` hint.
- **`wt select` log preview**: Graph structure is now preserved when displaying commit history, and columns dynamically align.
### Documentation
- **FAQ entry for shell setup issues**: Added troubleshooting guidance for common shell integration problems.
- **Template variables reference**: Consolidated template variables documentation into hook.md.
- **Clarified `--force` vs `-D` flags**: Updated `wt remove` documentation. (thanks @hlee-cb)
- **Performance benchmarks**: Added documentation for `copy-ignored` performance.
## 0.12.0
### Improved
- **`wt select --branches` and `--remotes` flags**: Control which items appear in the selection UI. Shares the `[list]` config section with `wt list` for consistent defaults.
- **Graceful degradation when default branch unavailable**: When the default branch cannot be determined (e.g., misconfigured), `wt list` shows warnings and empty cells rather than failing. `wt switch --create` without `--base` gives a clear error message.
- **Remove `--refresh` flag from state commands**: `wt config state default-branch get` and `wt config state ci-status get` now purely read cached state. To force re-detection, use the explicit workflow: `clear` then `get`. (Breaking: `--refresh` flag removed)
- **Windows: Require Git for Windows**: Removed PowerShell fallback. Worktrunk now requires Git for Windows (Git Bash) and shows a clear error message pointing to the download page if not found. (Breaking: PowerShell no longer supported)
### Fixed
- **Flag styling in messages**: Flags like `--clobber` and `--no-verify` in parentheses now inherit message color instead of using bright-black styling.
- **Nix flake**: Remove apple_sdk framework dependency. ([#525](https://github.com/max-sixty/worktrunk/pull/525), thanks @MattiasMTS)
- **`gh issue create` hint**: Now includes `--web` flag to open the issue form in browser.
### Internal
- **Binary size reduced ~1MB**: Trimmed unused config/minijinja features (13MB → 12MB).
- **Repository module split**: Split 2200-line module into 8 focused submodules for maintainability.
## 0.11.0
### Improved
- **Nix flake for packaging**: New `flake.nix` for Nix users with crane for efficient Rust builds. ([#502](https://github.com/max-sixty/worktrunk/pull/502), thanks @marktoda; thanks @Kabilan108 for requesting)
- **`sanitize_db` template filter**: New filter that transforms strings into database-safe identifiers with a 3-character hash suffix for collision/keyword safety. ([#498](https://github.com/max-sixty/worktrunk/pull/498), thanks @hugobarauna for requesting)
- **`wt select` performance**: 500ms timeout for git commands improves TUI responsiveness on large repos with many branches. (thanks @KidkArolis for reporting [#461](https://github.com/max-sixty/worktrunk/issues/461))
- **`wt select` stale branch handling**: Branches 50+ commits behind the default branch now skip expensive operations, showing `...` in the diff column. Improves performance on repos with many stale branches.
- **Global merge-base cache**: Cached merge-base results improve `wt list` performance by avoiding redundant git calls.
- **`wt config show` git version**: Now displays the git version alongside the worktrunk version.
- **`wt step copy-ignored` default**: Now copies all gitignored files by default. Use `.worktreeinclude` to limit what gets copied (previously required `.worktreeinclude` to specify what to copy).
- **Trace log analysis**: New `analyze-trace` binary for analyzing `[wt-trace]` performance logs.
### Fixed
- **Statusline truncation**: No longer truncates when terminal width is unknown, fixing Claude Code statusline display.
- **Shell completions**: Deprecated args like `--no-background` no longer appear in tab completions.
- **`wt remove` progress ordering**: Progress message now appears after pre-remove hooks, not before.
- **`wt list` index lock**: Uses `--no-optional-locks` for git status to avoid lock contention with parallel tasks.
## 0.10.0
### Improved
- **`wt step copy-ignored`**: Copy gitignored files listed in `.worktreeinclude` between worktrees. Useful for syncing `.env` files, IDE settings, and build caches to new worktrees via post-create hooks. Uses COW (reflink) copying for efficient handling of large directories. Matches Claude Code Desktop's worktree file syncing behavior.
- **`--foreground` flag**: Debug background hooks by running them in the foreground. Available on `wt hook post-start`, `wt hook post-switch`, and `wt remove`. Replaces the deprecated `--no-background` flag.
- **`--var` flag for hooks**: Override template variables when running hooks manually, e.g., `wt hook post-create --var target=main`.
- **`[ci] platform` config**: Explicitly set CI platform (`github` or `gitlab`) for GitHub Enterprise or self-hosted GitLab where URL-based detection fails.
- **Upstream diff in `wt select`**: Tab 4 shows ahead/behind diff vs upstream tracking branch (remote⇅), matching the column in `wt list`.
- **`{{ base }}` and `{{ base_worktree_path }}` variables**: New template variables for creation hooks (post-create, post-start, post-switch) to access the base branch name and worktree path.
- **`-vv` diagnostic reports**: Double-verbose flag writes a diagnostic report to `.git/wt-logs/diagnostic.md` with environment info, configs, and logs for easy bug reporting.
### Fixed
- **Warning ordering**: Warnings about state discovered during evaluation now appear before the action message, making them feel like considered observations rather than afterthoughts.
- **Config validation in `wt config show`**: Now validates TOML syntax and schema, displaying parse errors with details.
### Documentation
- **Undocumented features**: Added documentation for `--show-prompt` and `--stage` flags on `wt step commit/squash`, `skip-shell-integration-prompt` config, and `[select] pager` config.
## 0.9.5
### Improved
- **Pager config for `wt select`**: New `[select] pager` config option to customize the diff pager in `wt select` previews. Auto-detects delta/bat when not configured.
- **Infinity symbol for extreme diffs**: `wt list` shows `∞` instead of `9K` for diffs >= 10,000 commits, avoiding misleading values.
### Fixed
- **Windows shell integration message**: Warning now shows just the command name instead of the full absolute path, and gives targeted advice when only the `.exe` suffix differs.
- **URL column width**: Column width in `wt list` now accounts for hyperlink display showing just `:PORT` instead of full URLs.
### Internal
- **Deprecated `template-file` and `squash-template-file`**: Legacy LLM template config options now show deprecation warnings.
- **Path handling improvements**: Replaced string manipulation with proper Path/PathBuf stdlib methods throughout the codebase.
## 0.9.4
### Improved
- **Diagnostic report generation**: `wt list --verbose` generates diagnostic reports (`.git/wt-logs/diagnostic.md`) when warnings or errors occur, with a `gh issue create` command hint when GitHub CLI is available.
- **Alias bypass detection**: `wt config show` detects shell aliases that point to binary paths (e.g., `alias gwt="/usr/bin/wt"`) and warns that they bypass shell integration with suggested fixes.
- **Switch message clarity**: Messages now explicitly state what was created — "Created branch X and worktree" vs "Created worktree for X" vs "Switched to worktree for X".
- **Worktree-path hint**: One-time hint after first `wt switch --create` suggesting `wt config create` to customize worktree locations.
- **Path mismatch warnings**: `wt remove` and `wt merge` show warnings when worktree paths don't match the config template.
- **CLI command ordering**: Commands reordered by usage frequency in `--help` (switch, list, remove, merge...).
### Fixed
- **Progress counter overflow**: Fixed `wt list` progressive rendering when URL sends caused completed count to exceed expected count.
- **Windows shell integration**: Shell function now correctly strips `.exe` suffix, relying on MSYS2/Git Bash automatic resolution (fixes [#348](https://github.com/max-sixty/worktrunk/issues/348)).
- **Prunable worktrees**: Gracefully handle worktrees where the directory was deleted but git still tracks metadata.
- **Help text tables**: Disabled clap text wrapping to preserve markdown tables in `--help` output.
### Documentation
- **FAQ entries**: Added entries for "What files does Worktrunk create?" and "What can Worktrunk delete?".
### Internal
- **Hint state management**: New `wt config state hints` subcommand for viewing and clearing shown hints.
- **Deprecated config deduplication**: Migration files (`.new`) only written once per repo, tracked via git config hints.
## 0.9.3
### Improved
- **Terminal hyperlinks for URLs**: The URL column in `wt list` now shows clickable links (OSC 8) in supported terminals, displaying a compact `:port` that links to the full URL.
- **Statusline truncation**: Statusline output now intelligently truncates by dropping low-priority segments (URL, CI) before high-priority ones (branch, model) when exceeding terminal width.
- **Statusline URL**: When a project has a `[list] url` template configured, the URL now appears in statusline output for shell prompts.
- **Bare repo default branch detection**: Uses `symbolic-ref HEAD` as a heuristic for detecting the default branch in bare repos and empty repos before the first commit.
- **Terminology**: Renamed "path mismatch" to "branch-worktree mismatch" for clarity. In JSON output (`wt list --format=json`), the field `path_mismatch` is now `branch_worktree_mismatch`.
### Fixed
- **Empty bare repo bootstrap**: `wt switch --create main` now works in empty bare repos by handling unborn branches correctly.
### Documentation
- **CLI help text**: Improved descriptions across multiple commands including `wt`, `wt list`, `wt select`, `wt step`, `wt merge`, `wt remove`, and `wt hook`.
- **Web docs copy button**: Fixed copy button position so it stays at top-right when scrolling horizontally through code blocks.
### Internal
- **Claude Code plugin detection**: `wt config show` now displays whether the worktrunk Claude Code plugin is installed, with install hints if needed.
- **Hyperlink diagnostics**: `wt config show` shows hyperlink support status (active/inactive).
## 0.9.2
### Fixed
- **Locked worktree detection**: `wt remove` now detects locked worktrees upfront and shows a clear error with unlock instructions, instead of reporting success but silently failing. ([#408](https://github.com/max-sixty/worktrunk/pull/408), [#412](https://github.com/max-sixty/worktrunk/pull/412))
- **Windows Git Bash shell integration**: Shell detection now handles Windows-style paths in `$SHELL` (e.g., `C:\Program Files\Git\usr\bin\bash.exe`). Fixes [#348](https://github.com/max-sixty/worktrunk/issues/348). ([#398](https://github.com/max-sixty/worktrunk/pull/398))
### Documentation
- **CLI help text clarity**: Improved descriptions for `wt`, `wt list`, `wt step push`, `wt step squash`, `wt remove`, and `wt config state`. ([#410](https://github.com/max-sixty/worktrunk/pull/410))
- **Installation commands**: Removed `$` prefixes from install commands for easier copy-paste. ([#405](https://github.com/max-sixty/worktrunk/pull/405), thanks @muzzlol)
### Internal
- **Home worktree lookup**: Centralized with `find_home()` and `home_path()` methods for more consistent behavior with bare repos.
- **Windows CI**: Added cross-platform mock infrastructure for testing Windows-specific behavior.
## 0.9.1
### Improved
- **Shell integration debug info**: `wt config show` now displays invocation details (path, git subcommand mode, explicit path usage) to help diagnose shell integration issues. "Shell integration not active" is now a warning instead of a hint.
## 0.9.0
### Improved
- **Shell integration prompt**: When shell integration isn't active after `wt switch`, an interactive prompt offers to install it. The prompt remembers your choice and falls back to a hint for non-TTY environments.
- **Template variable names**: Renamed for clarity: `repo_root` → `repo_path`, `worktree` → `worktree_path`, `main_worktree` → `repo`. Added `main_worktree_path` for accessing the main worktree's absolute path. Deprecated names work with migration warnings and auto-generated `.new` config files.
- **Shell integration warnings**: Specific diagnostic messages when shell cd won't work: "shell integration not installed", "shell requires restart", "ran ./wt; shell integration wraps wt", or "ran git wt; running through git prevents cd".
- **RUNTIME section in `wt config show`**: Displays binary name, version, and shell integration status to help debug invocation issues.
- **Clickable CI indicator**: The CI status indicator (●) in `wt list` output is now a clickable link to the PR in terminals that support OSC 8 hyperlinks.
- **`wt switch` help text**: Clarifies the difference from `git switch` and documents common failure conditions.
### Fixed
- **Hook path display**: Hook announcements show the execution path when shell integration isn't active.
- **Approval matching with deprecated vars**: Approvals now match regardless of whether they were saved with deprecated or current variable names.
- **Documentation filter syntax**: Fixed incorrect Jinja filter examples that showed `~` concatenation with `|` filter without parentheses. ([#373](https://github.com/max-sixty/worktrunk/pull/373), thanks @coriocactus)
### Documentation
- **Pre-remove hook example**: Added pattern for cleaning up background processes (e.g., killing dev servers) when worktrees are removed.
## 0.8.5
### Improved
- **Windows `git-wt` command**: Winget now ships with `git-wt` as a workaround to the Windows Terminal `wt` naming conflict. We're still considering better options — see [#133](https://github.com/max-sixty/worktrunk/issues/133).
## 0.8.4
### Improved
- **Shell integration detection**: More robust detection of `git wt` (space) vs `git-wt` patterns. `wt config show` now displays line numbers for detected shell integration.
- **Windows `wt select` error**: Shows a helpful error message with alternatives instead of "unrecognized subcommand".
### Fixed
- **Markdown table rendering**: Escaped pipe characters (`\|`) in help output now render correctly.
- **Dim styling on wrapped lines**: Dim text attribute now preserved on continuation lines when text wraps.
- **Path occupied hint**: Fixed tilde expansion issue where `~/...` paths didn't work in shell commands.
### Documentation
- **Hook design guide**: Added comprehensive guide for designing hooks.
- **Command docs**: Added `wt config show` to command documentation.
- **Windows paths**: Documented MSYS2 auto path conversion for Windows shell integration.
### Internal
- **Output system**: Consolidated output functions, removed redundant aliases.
- **Zsh compinit**: Improved handling of "insecure directories" warning in tests.
## 0.8.3
### Improved
- **Hook execution path**: Shows the execution path when post-merge hooks run in a different directory than where the user invoked the command (e.g., with `--no-remove`).
- **TTY check for `wt select`**: Now fails gracefully when run in a non-interactive terminal instead of hanging.
- **Background hooks**: `post-start` and `post-switch` hooks spawn in background via stdin piping, matching their normal behavior during `wt switch`.
- **Occupied path error message**: When a worktree path is occupied by a different branch, the error now explains the situation clearly and suggests `git switch`.
- **Shell integration hint**: Shows a hint to restart the shell when shell integration is configured but not active.
- **Message style**: Removed 2nd person pronouns ("you/your") from user-facing messages following CLI guidelines.
### Fixed
- **`wt hook post-start` blocking**: Fixed bug where `wt hook post-start` ran in foreground blocking the command, instead of spawning in background like during normal `wt switch --create`.
- **Approval bypass with `project:` prefix**: Fixed security issue where using `project:` filter prefix (e.g., `wt hook pre-merge project:`) bypassed the approval check, allowing unapproved project commands to run.
### Documentation
- **License file**: Added combined MIT and Apache-2.0 license file.
- **Demo GIFs**: Added demo GIFs to command pages on the documentation site.
- **Install instructions**: Simplified to single-line commands.
### Internal
- **Pre-commit hooks**: Updated to immutable tags.
- **Lychee exclusions**: Cleaned up link checker configuration.
## 0.8.2
### Improved
- **Concurrent hook execution**: `wt hook post-start` and `wt hook post-switch` now run all commands concurrently (matching their normal background behavior) instead of sequentially with fail-fast. Multiple failures are collected and reported together.
### Documentation
- **Nested bare repo layout**: Added worktree-path template example for nested bare repo layout (`project/.git` pattern). Uses relative paths like `../{{ branch | sanitize }}` to create worktrees as siblings to the .git directory.
## 0.8.1
### Improved
- **Shell and PowerShell installers**: Added one-line install commands for Linux/macOS and Windows.
- **Consistent terminology**: CLI now uses "branch name" consistently instead of mixing "worktree" and "branch". The `wt remove` argument is renamed from `worktrees` to `branches` to reflect that worktrees are addressed by branch name.
### Fixed
- **Switch hints**: Removed incorrect `wt switch @` hint and improved error output spacing.
### Documentation
- **Dev server and database patterns**: Added practical examples for running per-worktree dev servers with subdomain routing and databases with unique ports.
## 0.8.0
### Improved
- **Separate `--yes` and `--force` flags**: `--force/-f` renamed to `--yes/-y` for skipping prompts (all commands). New `--force/-f` on `wt remove` forces removal of worktrees with untracked files (build artifacts, node_modules, etc.). (Breaking: `--force` no longer skips prompts; use `--yes`)
- **Clearer branch deletion output**: `wt remove` output now shows "worktree & branch" when the branch is deleted, or plain "worktree" with a hint when kept. Makes scanning output for branch fate easier.
- **`post-switch` hook on remove**: When `wt remove` switches to the main worktree, post-switch hooks now run in the destination.
- **Allow merge commits by default**: `wt step push` no longer rejects history with merge commits. Removed `--allow-merge-commits` flag. (Breaking: flag removed)
### Fixed
- **Orphan branches in `wt list`**: Branches with no common ancestor with the default branch no longer cause errors.
- **Remote branch filtering**: `wt list --remotes` now filters out branches that are tracked as upstreams, not just branches with worktrees.
- **Error message spacing**: Reduced double-newline spacing in error messages.
## 0.7.0
### Improved
- **Working tree conflict detection**: `wt list --full` now detects conflicts using uncommitted working tree changes, not just committed content. This catches conflicts earlier—before committing changes that would conflict with the target branch.
- **Dev server URL column**: New optional URL column in `wt list` configured via `[list] url` template in project config (`.config/wt.toml`). URLs show with health-check styling: normal if the port is listening, dimmed otherwise.
- **Shell integration simplification**: The shell wrapper is now self-contained with all directive handling inlined. Removes the separate helper function that could become unavailable if shell initialization order changed.
- **Performance**: Repository caching reduces git subprocess spawns; parallelized pre-skeleton operations for faster initial display.
- **Improved error hints**: When a worktree path already exists during creation, the error hint now correctly suggests `--create --clobber`.
### Fixed
- **Docs syntax highlighting**: Fixed syntax highlighting colors being stripped by 1Password browser extension on the documentation site.
## 0.6.1
### Improved
- **`post-switch` hook**: New hook that runs in the background after every `wt switch` operation. Unlike `post-start` (which only runs on creation), `post-switch` runs on all switch results. Use cases include renaming terminal tabs, updating tmux window names, and IDE notifications.
- **Signal forwarding for hooks**: Hooks now receive SIGINT/SIGTERM when the parent process is interrupted, allowing proper cleanup. Previously, non-interactive shells continued executing after signals.
- **Faster `wt list` skeleton**: Time-to-skeleton reduced by caching default branch lookup, batching timestamp fetching, and deferring non-essential git operations. Skeleton shows `·` placeholder for gutter symbols until data loads.
- **Clearer `--clobber` hint**: Error message now says "to overwrite (with backup)" instead of "to retry with backup".
### Documentation
- **State side-effects**: Added section explaining how Worktrunk state operations may trigger git commands.
- **`wt merge` location**: Clarified that `wt merge` runs from the feature worktree.
## 0.6.0
### Improved
- **Single-width Unicode symbols**: Replaced emojis (🔄, ✅, ❌) with single-width Unicode symbols (◎, ✓, ✗, ▲, ↳, ○, ❯) for better terminal compatibility and consistent alignment.
- **Output system overhaul**: Clean separation of output channels (data→stdout, status→stderr, directives→file) means piping works with shell integration active. `wt list --format=json | jq` and `wt switch feature | tee log.txt` both work correctly. Background processes use `process_group(0)` instead of `nohup` for more reliable detachment.
- **Trailing arguments for `--execute`**: `wt switch --execute` now accepts arguments after `--`, enabling shell aliases like `alias wsc='wt switch --create -x claude'` then `wsc feature -- 'implement login'`.
- **`hash_port` template filter**: `{{ branch | hash_port }}` hashes the branch name to a deterministic port number (10000-19999), useful for running dev servers without port conflicts.
- **`sanitize` template filter**: `{{ branch | sanitize }}` explicitly replaces `/` and `\` with `-` for filesystem-safe paths. (Breaking: `{{ branch }}` now provides raw branch names. Update templates that use `{{ branch }}` in filesystem paths to use `{{ branch | sanitize }}` instead)
- **Log directory in state output**: `wt config state logs` and `wt config state get` now show the log directory path under a LOG FILES heading.
- **Actionable error hints**: Error messages now include hints about what command to run next.
- **Unified directory change output**: `wt remove` now shows "Switched to worktree for {branch} @ {path}" matching `wt switch` format.
- **Consistent "already up to date" formatting**: Standardized message wording and styling across commands.
### Fixed
- **`wt step rebase` with merge commits**: Fixed incorrect "Already up-to-date" when a branch has merge commits from merging target into itself.
### Documentation
- **Local CI workflow**: Added "Local CI" section to `wt merge --help` explaining how pre-merge hooks enable faster iteration.
- **Colored command reference**: Web docs now preserve ANSI colors in command reference output.
- **Clarified terminology**: Help text uses "default branch" instead of hardcoded "main".
## 0.5.2
### Improved
- **`--clobber` flag for `wt switch`**: When encountering a stale directory or file at the target worktree path, `--clobber` moves it to a timestamped `.bak` file instead of failing.
- **Relative paths in `wt list`**: Paths are now shown relative to the main worktree (`.`, `./subdir`, `../repo.feature`) instead of a computed common prefix that could degenerate to `/`.
- **Multiline error formatting**: Errors with context now show a header describing what worktrunk was trying to do, with the full error chain in a gutter block.
- **Semantic switch messaging**: Switching to an existing worktree now shows ⚪ (info) instead of ✅ (success), reflecting that nothing was created.
### Fixed
- **Symbol styling in removal messages**: Integration symbols (`_`, `⊂`) now render in their canonical dim appearance instead of inheriting the message's cyan color.
- **ConflictingChanges error formatting**: Fixed double newlines in the error message output.
## 0.5.1
### Improved
- **Integration status in removal messages**: Shows integration symbols (`_` for same commit, `⊂` for integrated) when removing worktrees, matching `wt list` display.
- **Concurrent command limiting**: Limits concurrent git processes to 32 (configurable via `WORKTRUNK_MAX_CONCURRENT_COMMANDS`), preventing resource exhaustion on repos with many branches.
- **Better error display for `wt list`**: Task errors are now collected and displayed as warnings after the table renders, instead of being silently swallowed.
- **Remove continues on partial failures**: `wt remove` continues removing other worktrees when some fail, reporting all errors at the end.
- **Bash syntax highlighting**: Shell commands in error gutters now have syntax highlighting.
- **Shell integration is command-aware**: Detection and removal works correctly when installed as `git-wt` or other names.
- **CI fetch error documentation**: Yellow warning symbol (⚠) in CI column is now documented in help text.
### Fixed
- **CI status with multiple workflows**: Fixed incorrect status when multiple workflows exist (e.g., `ci` and `publish-docs`). Now uses GitHub's check-runs API to aggregate all workflow statuses.
- **State storage unification**: Unified branch-keyed state under `worktrunk.state.<branch>.*`. Numeric branch names now work. (Existing CI cache and markers regenerate on first access)
### Internal
- **Environment variable prefix**: Standardized to `WORKTRUNK_` prefix (e.g., `WORKTRUNK_MAX_CONCURRENT_COMMANDS`).
- Automatic winget package publishing on releases.
## 0.5.0
### Improved
- **Path column hidden when redundant**: Path column is deprioritized when all paths match the naming template, showing only at wider terminal widths (~125+ columns).
- **Better error formatting**: Errors with context now show a header with the root cause in a gutter block, improving readability for git errors.
- **Clearer integration target**: Separated `default_branch` (for stats like ahead/behind) from `target` (for integration checks), catching branches merged remotely before pulling.
### Fixed
- **Untracked files block integration**: Untracked files now prevent a worktree from being flagged as integrated, avoiding accidental data loss on removal.
- **Dirty worktree count includes untracked**: Summary now correctly counts worktrees with untracked files as dirty.
- **Branch name disambiguation**: Fixed `refname:short` issues when a branch and remote have the same name.
- **JSON output uses kebab-case**: Enum values changed from snake_case to kebab-case (e.g., `same_commit` → `same-commit`). (Breaking: scripts parsing JSON output may need updates)
- **Legacy marker format removed**: Plain-text markers no longer parsed. (Breaking: re-set markers with `wt config state marker set`)
### Internal
- **Unified command execution**: All external commands now go through `shell_exec::run()` for consistent logging and tracing.
## 0.4.0
### Added
- **`--no-rebase` flag for `wt merge`**: Fails early with a clear error if the branch is not already rebased onto target, rather than auto-rebasing. Useful for workflows that handle rebasing separately. ([#194](https://github.com/max-sixty/worktrunk/pull/194))
### Changed
- **Branch-first argument resolution**: `wt switch` and `wt remove` now check if the branch has a worktree anywhere before checking the expected path. If you type `wt switch foo`, you get branch foo's worktree, not whatever happens to be at the expected path. ([#197](https://github.com/max-sixty/worktrunk/pull/197))
### Fixed
- **`--no-commit` incorrectly skipped rebasing**: `wt merge --no-commit` now correctly rebases before stopping (if needed), rather than skipping the rebase entirely. ([#194](https://github.com/max-sixty/worktrunk/pull/194))
- **Pager for `wt config show --full`**: The pager now works correctly with the `--full` flag, showing diagnostics properly. ([#198](https://github.com/max-sixty/worktrunk/pull/198))
- **Statusline stdin handling**: Fixed flaky behavior on Windows CI by using standard is_terminal() check instead of timeout-based approach. ([#210](https://github.com/max-sixty/worktrunk/pull/210))
### Improved
- **Path-occupied error messages**: When `wt switch` can't create a worktree because the path exists, error messages now show which branch occupies the path and provide actionable commands to fix the situation. ([#195](https://github.com/max-sixty/worktrunk/pull/195), [#206](https://github.com/max-sixty/worktrunk/pull/206), [#207](https://github.com/max-sixty/worktrunk/pull/207))
- **Switch mismatch detection**: Better error messages when path/branch mismatches occur, with hints showing the expected path. ([#195](https://github.com/max-sixty/worktrunk/pull/195))
## 0.3.1
### Fixed
- **Branch names with slashes**: Branch names like `fix/feature-name` no longer break git config markers. Slashes are now escaped for git config compatibility. ([#189](https://github.com/max-sixty/worktrunk/pull/189), thanks @kyleacmooney)
- **stdin inheritance for `--execute`**: Interactive programs (vim, python -i, claude) now work correctly with `--execute` on non-Unix platforms. ([#191](https://github.com/max-sixty/worktrunk/pull/191))
- **Filenames with spaces/newlines**: Git status parsing now handles filenames containing spaces and newlines correctly using NUL-separated output.
- **Concurrent approval race condition**: Multiple concurrent approval/revocation operations no longer overwrite each other. Approvals now reload from disk before saving.
- **Dirty worktrees incorrectly marked integrated**: Priority 5 integration check now requires clean working tree state, preventing worktrees with uncommitted changes from being flagged as safe to remove.
- **Type changes not detected as staged**: Index status check now recognizes file type changes (`T` status) as staged changes.
- **User hook failure strategy**: Hook failure strategy now correctly applies to user hooks instead of always using fail-fast.
- **Branch variable in detached HEAD**: `{{ branch }}` now correctly expands to "HEAD" in detached HEAD worktrees instead of "(detached)".
### Improved
- **Self-hosted GitLab support**: CI auth checks now detect the GitLab host from the remote URL, supporting self-hosted GitLab instances instead of always checking gitlab.com.
- **Platform-specific CI status**: `wt list --full` and `wt config show` now show only the relevant CI tool (GitHub Actions or GitLab CI) based on the repository's remote URL.
- **LLM error reproduction**: When LLM commands fail, error messages now show the full reproduction command (e.g., `wt step commit --show-prompt | llm`) for easier debugging.
- **Location format**: Messages now use `@` instead of `at` for location phrases (e.g., "Switched to feature @ /path").
- **Switch help text**: Clarified that `wt switch` creates worktrees automatically for existing branches, not just for new branches with `--create`.
## 0.3.0
### Added
- **`--show-prompt` flag for LLM commands**: `wt step commit --show-prompt` and `wt step squash --show-prompt` output the rendered LLM prompt without executing the command. Useful for debugging templates or manually piping to LLM tools. ([#187](https://github.com/max-sixty/worktrunk/pull/187))
- **Diff size limits and diffstat for LLM prompts**: Large diffs (>400K chars) are progressively filtered—first removing lock files, then truncating to 50 lines/file, max 50 files. New `git_diff_stat` template variable shows line change statistics. ([#186](https://github.com/max-sixty/worktrunk/pull/186))
- **`MainState::Empty` status**: New `_` symbol for clean same-commit branches (safe to delete), distinguished from `–` (en-dash) for same-commit branches with uncommitted changes. Previously, both showed `_`. Only Empty branches are dimmed and considered "potentially removable". ([#185](https://github.com/max-sixty/worktrunk/pull/185))
### Changed
- **State subcommands default to `get`**: Running `wt config state default-branch` now defaults to `get`, making the command shorter. Use explicit `get` subcommand to access options like `--refresh` or `--branch`. ([#184](https://github.com/max-sixty/worktrunk/pull/184))
- **Clearer integration reason messages**: Updated descriptions to be more precise—"same commit as" instead of "already in" for SameCommit, "ancestor of" for Ancestor, "no added changes" for NoAddedChanges, "tree matches" for TreesMatch.
## 0.2.1
### Changed
- **Unified state management**: `wt config var` and `wt config cache` replaced by `wt config state` with consistent get/set/clear semantics for all runtime state. New subcommands: `default-branch`, `ci-status`, `marker`, `logs`, `show`. ([#178](https://github.com/max-sixty/worktrunk/pull/178))
- **Comprehensive state overview**: `wt config state show` displays all state (default branch, switch history, markers, CI cache, logs) with `--format=json` support. ([#180](https://github.com/max-sixty/worktrunk/pull/180))
### Added
- **`git-wt` binary for Windows**: New `git-wt` binary avoids conflict with Windows Terminal's `wt` command. Build with `--features git-wt`. Shell init/install now accept `--cmd` to specify which binary name to use. ([#177](https://github.com/max-sixty/worktrunk/pull/177))
- **Diffstat in select preview**: The log preview (Tab 2) in `wt select` now shows line change statistics (+N -M) matching `wt list`'s HEAD± column format. ([#179](https://github.com/max-sixty/worktrunk/pull/179))
### Fixed
- **Windows compatibility**: Multiple test and runtime fixes for Windows including stdin timeout handling, path canonicalization, and cross-platform test behavior. ([#167](https://github.com/max-sixty/worktrunk/pull/167), [#168](https://github.com/max-sixty/worktrunk/pull/168), [#169](https://github.com/max-sixty/worktrunk/pull/169), [#170](https://github.com/max-sixty/worktrunk/pull/170), [#171](https://github.com/max-sixty/worktrunk/pull/171), [#174](https://github.com/max-sixty/worktrunk/pull/174), [#176](https://github.com/max-sixty/worktrunk/pull/176))
## 0.1.21
### Fixed
- **Windows path handling in shell templates**: Fixed path quoting in hook templates on Windows by using `cygpath` to convert native Windows paths to POSIX format for Git Bash compatibility. Template variables like `{{ worktree }}` and `{{ repo_root }}` now work correctly. ([#161](https://github.com/max-sixty/worktrunk/pull/161))
- **Hook errors show `--no-verify` hint**: When hooks fail during `wt merge`, `wt commit`, or `wt squash`, the error message now includes a hint about using `--no-verify` to skip hooks. ([4a89748](https://github.com/max-sixty/worktrunk/commit/4a89748f))
## 0.1.20
### Changed
- **`--doctor` renamed to `--full`**: The `wt list --doctor` flag is now `wt list --full`. The new name better reflects that it shows extended information (binaries status, full diff stats). ([171952e](https://github.com/max-sixty/worktrunk/commit/171952ec))
- **CLI binaries status in `wt config show --full`**: Shows installation and authentication status of `gh` and `glab` CLI tools in a new BINARIES section. ([171952e](https://github.com/max-sixty/worktrunk/commit/171952ec))
- **CI tool hints**: `wt list --full` shows a hint when CI status is unavailable, with specific guidance on which CLI tool to install or authenticate. ([171952e](https://github.com/max-sixty/worktrunk/commit/171952ec))
### Fixed
- **GitHub StatusContext checks**: CI status now includes StatusContext checks (used by some CI systems like Jenkins, CircleCI, and external status checks) in addition to CheckRuns. ([690da88](https://github.com/max-sixty/worktrunk/commit/690da889))
- **Windows Git Bash detection with WSL**: Fixed detection of Git Bash when WSL is installed. Previously, the WSL bash shim in PATH could be found instead of Git Bash, causing hook execution failures. ([b48b0ba](https://github.com/max-sixty/worktrunk/commit/b48b0ba7))
## 0.1.19
### Added
- **`wt step for-each` command**: Run commands across all worktrees sequentially. Supports template variables (`{{ branch }}`, `{{ worktree }}`, etc.) and JSON context on stdin. Example: `wt step for-each -- git pull --autostash`. ([#138](https://github.com/max-sixty/worktrunk/pull/138))
### Changed
- **Content integration detection always enabled**: The `⊂` (content integrated) symbol now appears without requiring `--full`. Squash-merged branches are detected automatically. ([f39c442](https://github.com/max-sixty/worktrunk/commit/f39c4428))
- **SIGINT forwarding**: Ctrl+C now properly terminates child processes in hooks, preventing orphaned background commands. ([#136](https://github.com/max-sixty/worktrunk/pull/136))
### Fixed
- **Windows path handling**: Fixed path canonicalization issues on Windows that caused worktree detection failures. Uses `dunce` to handle Windows verbatim paths (`\\?\`) that git cannot process. ([#125](https://github.com/max-sixty/worktrunk/pull/125))
## 0.1.18
### Added
- **Windows support**: Git Bash with PowerShell fallback enables worktrunk on Windows. Git Bash is preferred (same bash hook syntax across platforms); PowerShell works for basic commands with limitations. ([#122](https://github.com/max-sixty/worktrunk/pull/122))
- **Winget publishing**: Release workflow now publishes to Windows Package Manager. ([079c9df](https://github.com/max-sixty/worktrunk/commit/079c9df3))
### Changed
- **Approvals command moved**: `wt config approvals` is now `wt hook approvals` since approvals manage hook commands. ([b7b1b9e](https://github.com/max-sixty/worktrunk/commit/b7b1b9e3))
- **Approval prompts show templates**: Approval prompts now display command templates (what gets saved) rather than expanded values. ([2315d26](https://github.com/max-sixty/worktrunk/commit/2315d268))
- **Preview mode renamed**: The `history` preview mode is now `log` for clarity. ([0461152](https://github.com/max-sixty/worktrunk/commit/04611524))
### Fixed
- **PR/MR source filtering**: Filter PRs by source repository instead of author, fixing false matches when multiple users have PRs with the same branch name. ([e9ccdf7](https://github.com/max-sixty/worktrunk/commit/e9ccdf77))
## 0.1.17
### Added
- **User-level hooks**: Define hooks in `~/.config/wt.toml` that run for all repositories. New `wt hook show` command displays configured hooks and their sources. ([#118](https://github.com/max-sixty/worktrunk/pull/118))
- **SSH URL support**: Git SSH URLs (e.g., `git@github.com:user/repo.git`) now work correctly for remote operations and branch name escaping. ([92c2cef](https://github.com/max-sixty/worktrunk/commit/92c2cef8))
- **Help text wrapping**: CLI help text now wraps to terminal width for better readability. ([fe981c2](https://github.com/max-sixty/worktrunk/commit/fe981c2e))
### Changed
- **JSON output redesign**: `wt list --format=json` now outputs a query-friendly format. This is a breaking change for existing JSON consumers. ([236eae8](https://github.com/max-sixty/worktrunk/commit/236eae81))
- **Status symbols**: Reorganized status column symbols for better scannability. Same-commit now distinguished from ancestor in integration detection. ([5053af8](https://github.com/max-sixty/worktrunk/commit/5053af88), [a087962](https://github.com/max-sixty/worktrunk/commit/a0879623))
### Fixed
- **ANSI state reset**: Reset terminal ANSI state before returning to shell, preventing color bleeding into subsequent commands. ([334f6d9](https://github.com/max-sixty/worktrunk/commit/334f6d99))
- **Empty staging error**: Fail early with a clear error when trying to generate a commit message with nothing staged. ([b9522bc](https://github.com/max-sixty/worktrunk/commit/b9522bc6))
## 0.1.16
### Added
- **Squash-merge integration detection**: Improved branch cleanup detection with four ordered checks to identify when branch content is already in the target branch. This enables accurate removal of squash-merged branches even after target advances. New status symbols: `·` for same commit, `⊂` for content integrated via different history. ([6325be2](https://github.com/max-sixty/worktrunk/commit/6325be28))
- **CI absence caching**: Cache "no CI found" results to avoid repeated API calls for branches without CI configured. Reduces unnecessary rate limit consumption. ([8db3928](https://github.com/max-sixty/worktrunk/commit/8db39285))
- **Shell completion tests**: Black-box snapshot tests for zsh, bash, and fish completions that verify actual completion output. ([#117](https://github.com/max-sixty/worktrunk/pull/117))
### Changed
- **Merge conflict indicator**: Changed from `⊘` to `⚔` (crossed swords) for better visual distinction from the rebase symbol. ([f3b96a8](https://github.com/max-sixty/worktrunk/commit/f3b96a83))
### Documentation
- **Hook JSON context**: Document all JSON fields available to hooks on stdin with examples for Python and other languages. ([af80589](https://github.com/max-sixty/worktrunk/commit/af805898))
- **CI caching**: Document that CI results are cached for 30-60 seconds and how to use `wt config cache` to manage the cache. ([4804913](https://github.com/max-sixty/worktrunk/commit/48049132))
- **Status column clarifications**: Clarify that the Status column contains multiple subcolumns with priority ordering. ([1f9bb38](https://github.com/max-sixty/worktrunk/commit/1f9bb38f))
## 0.1.15
### Added
- **`wt hook` command**: New command for running lifecycle hooks directly. Moved hook execution from `wt step` to `wt hook` for cleaner semantic separation. ([#113](https://github.com/max-sixty/worktrunk/pull/113))
- **Named hook execution**: Run specific named commands with `wt hook <type> <name>` (e.g., `wt hook pre-merge test`). Includes shell completion for hook names from project config. ([#114](https://github.com/max-sixty/worktrunk/pull/114))
### Fixed
- **Zsh completion syntax**: Fixed `_describe` syntax in zsh shell completions. ([6ae9d0f](https://github.com/max-sixty/worktrunk/commit/6ae9d0f9))
- **Fish shell wrapper**: Fixed stderr redirection in fish shell wrapper. ([0301d4b](https://github.com/max-sixty/worktrunk/commit/0301d4bf))
- **CI status for local branches**: Only check CI for branches with upstream tracking configured. ([6273ccd](https://github.com/max-sixty/worktrunk/commit/6273ccdb))
- **Git error messages**: Include executed git command in error messages for easier debugging. ([200eea4](https://github.com/max-sixty/worktrunk/commit/200eea43))
## 0.1.14
### Added
- **Pre-remove hook**: New `pre-remove` hook runs before worktree removal, enabling cleanup tasks like stopping devcontainers. Thanks to [@pwntester](https://github.com/pwntester) in [#101](https://github.com/max-sixty/worktrunk/issues/101). ([#107](https://github.com/max-sixty/worktrunk/pull/107))
- **JSON context on stdin**: Hooks now receive worktree context as JSON on stdin, enabling hooks in any language (Python, Node, Ruby, etc.) to access repo information. ([#109](https://github.com/max-sixty/worktrunk/pull/109))
- **`wt config create --project`**: New flag to generate `.config/wt.toml` project config files directly. ([#110](https://github.com/max-sixty/worktrunk/pull/110))
### Fixed
- **Shell completion bypass**: Fixed lazy shell completion to use `command` builtin, bypassing the shell function that was causing `_clap_dynamic_completer_wt` errors. Thanks to [@cquiroz](https://github.com/cquiroz) in [#102](https://github.com/max-sixty/worktrunk/issues/102). ([#105](https://github.com/max-sixty/worktrunk/pull/105))
- **Remote-only branch completions**: `wt remove` completions now exclude remote-only branches (which can't be removed) and show a helpful error with hint to use `wt switch`. ([#108](https://github.com/max-sixty/worktrunk/pull/108))
- **Detached HEAD hooks**: Pre-remove hooks now work correctly on detached HEAD worktrees. ([#111](https://github.com/max-sixty/worktrunk/pull/111))
- **Hook `{{ target }}` variable**: Fixed template variable expansion in standalone hook execution. ([#106](https://github.com/max-sixty/worktrunk/pull/106))