## Summary Weekly CI renovation. Rust stable moved to 1.98.0 on 2026-08-20, so MSRV and the development toolchain go to 1.97 (latest stable − 1); one cargo-install pin had drifted. Everything else is already current. - **MSRV + toolchain: 1.96 → 1.97** — `Cargo.toml`, `tests/helpers/wt-perf/Cargo.toml`, `rust-toolchain.toml` (`1.97.0`), plus the `flake.lock` refresh the channel bump requires. - **`cargo-llvm-cov`: 0.8.7 → 0.9.0** — `coverage.yaml`. MSRV 1.87, well under the pinned toolchain. Toolchain compatibility for every other pinned crate against 1.97.0: `cargo-affected` 0.4.0 (1.94), `cargo-insta` 1.48.0 (1.66.0), `cargo-nextest` 0.9.143 (1.91), `cargo-llvm-cov` 0.9.0 (1.87), `cargo-msrv` 0.19.3 (1.91.1), `lychee` 0.24.2 (1.88.0), `worktrunk` 0.74.0 (1.96), `cargo-udeps` 0.1.61 (unspecified). All build under 1.97.0. - **Pinned nightly: `nightly-2026-03-01` → `nightly-2026-08-01`** — `nightly.yaml` ×2. Not drift: the MSRV bump *broke* these two jobs, see below. - **The skill's `flake.lock` recipe** — the in-session Nix install it pointed at can never run. The setup step that fixes that lives in #3891, not here; see below. The remaining commits are fallout from the same sweep: `cargo-llvm-cov` 0.9.0 changes the shape of the `--show-missing-lines` column `tests/CLAUDE.md` sends you to during a codecov investigation, and the weekly statusline cache-check has been reporting two duplicates that are artifacts of its own `-vv` flag. ## The MSRV bump broke two nightly jobs; that is fixed here `check-unused-dependencies` and `minimal-versions` each pin their own toolchain, and `nightly-2026-03-01` is `1.96.0-nightly` — so raising `rust-version` to 1.97 made cargo refuse the workspace outright, before either job ran its actual check: ``` error: rustc 1.96.0-nightly is not supported by the following packages: worktrunk@0.74.0 requires rustc 1.97 ``` Both are now on `nightly-2026-08-01` (`1.99.0-nightly`), which clears the new MSRV with headroom rather than landing on it. Reproduced locally in both directions: `cargo +nightly-2026-03-01 check` fails with the error above, `cargo +nightly-2026-08-01 check` passes. The coupling is easy to miss because neither failure mentions udeps or minimal versions, so both lines now say so, and the weekly MSRV file table gained a row for the pins. The rule on that row is a date, not a version: bump only when the pinned date is more than three months old. Nightly runs two channels ahead of stable and MSRV tracks stable − 1, so a pin that recent is still a release above the new MSRV — which makes staleness checkable from the pinned date alone, where reading it off the rustc version means fetching that day's `channel-rust-nightly.toml`. `nightly-2026-03-01` was five and a half months old, which is exactly what the rule catches. ## The `flake.lock` bump was computed by hand — and the recipe that forced that is fixed here `rust-toolchain.toml` moving to `1.97.0` forces a lock refresh: the locked `rust-overlay` (`4a408e1f`, 2026-06-02) carries stable manifests only up to `1.96.0`, so `nix flake check` cannot resolve the new channel. `rust-overlay` is bumped to `f60c1b57` (2026-08-23), which has `1.97.0.nix`. `nixpkgs` and `crane` are left alone — only `rust-overlay` has to know about the new channel, and a full `nix flake update` is a wider change than this PR needs. This session could not run `nix flake update`: the weekly runner has no Nix, and the agent runs as a sandbox user with no sudo, so the installer the skill pointed at stops at `sudo: a password is required`. The lock entry was therefore computed directly from the NAR serialisation, and the method was validated first by recomputing the **existing** `rust-overlay` entry from its own revision and getting `sha256-7mDa7OBAaf7MU6ZovT9ENfD62kH911SsSazBb4KTDF0=` back byte-for-byte — the value already in `flake.lock`. The same script then produced the new entry. That should not have been the answer, and it no longer is. #3891 has merged (`2960bfb`), so `tend-setup` installs Nix and next week's refresh runs `nix flake update rust-overlay` for real. This branch briefly carried its own `cachix/install-nix-action@v31` step in the same file; `adbeb76` dropped it in favour of #3891's, which asserts the multi-user install branch directly and doesn't couple to `github.workflow == 'tend-weekly'`, a gate that stops firing if the generated workflow is renamed. `.github/actions/tend-setup/action.yaml` on this branch is byte-identical to `main`. What stays here is the skill side: the in-session install recipe and the NAR-serialisation fallback are both deleted, because the Determinate installer they rest on cannot run in the sandbox. Both PRs rewrote that section and converged on nearly the same wording, so they merged clean while both were open — but #3891's squash collapsed its five commits into one, and its last two had moved the "if `nix` isn't on the PATH" line and folded the flake-input rationale into the code block. That turned the section into the merge's one conflict, resolved by taking `main`'s wording wholesale; the section is now byte-identical to `main`'s, and this branch's own additions to that file are untouched by it. That is a strong check but not the real one. `nightly`'s `nix-flake` job runs `nix flake check` and fires on this PR (the paths filter matches `rust-toolchain.toml`, `Cargo.toml`, and `flake.lock`), so it is the gate that actually proves the lock evaluates. **It has now run on this head and passed**, so the computed lock resolves the 1.97.0 channel and the flake's checks build under it. Flagging the provenance anyway, since a hand-written lock entry deserves a second look on review. <details><summary>How the hash was computed</summary> Nix serialises the unpacked flake input as a NAR and reports SHA-256 of that stream in SRI form. The format is length-prefixed strings padded to 8 bytes, with directory entries in bytewise-sorted order; a ~90-line Python script reproduces it from the GitHub tarball with the top-level `<repo>-<rev>` directory stripped, which is the same tree Nix hashes. ``` rust-overlay 4a408e1fc99ad517b4cb402fd0de7464f40c05e1 (currently locked) computed sha256-7mDa7OBAaf7MU6ZovT9ENfD62kH911SsSazBb4KTDF0= in lock sha256-7mDa7OBAaf7MU6ZovT9ENfD62kH911SsSazBb4KTDF0= ✓ rust-overlay f60c1b57ff805a46b5175c76fc981fb4f81efbcc (new) computed sha256-r4LDUF+zmJnkftvCVkCrUhSJazsf6EVJF+V2l4/MYbI= lastModified 1787454509 (committer date 2026-08-23T03:08:29Z) ``` </details> ## Already up to date - `cargo-affected` 0.4.0, `cargo-insta` 1.48.0, `cargo-nextest` 0.9.143, `cargo-msrv` 0.19.3, `cargo-udeps` 0.1.61, `lychee` 0.24.2, `worktrunk` 0.74.0 (matches the newest crates.io release) - Nushell 0.115.0 — all four call sites, and `dev/codex.sh` - Codex Cloud pins in `dev/codex.sh`: pre-commit 4.6.2, cargo-insta 1.48.0, cargo-nextest 0.9.143, PowerShell 7.6.5; `setup-web`'s own Nushell and PowerShell pins agree - Runner images `ubuntu-24.04` and `windows-2022` (the latter deliberately pinned — actions/runner-images#12677) ## Found, not bumped: `macos-15` is no longer what `macos-latest` resolves to `ci.yaml`'s header comment says `ubuntu-24.04, macos-15` are "pinned to current -latest equivalents". That is still true of Ubuntu but no longer of macOS: `macos-latest` now resolves to **macOS 26 arm64**, and `macos-15` has become the older of the two GA images — which, under the runner-images deprecation policy ("deprecation of the oldest image label begins once the newest OS image label has been released to GA"), is the one that starts aging out next. `macos-14` already carries the deprecated badge. Not bumped here, because it is an OS upgrade rather than a version pin, and this repo drives PTY and shell-integration snapshots on macOS that a new image and Xcode can move. There is also nothing this session can do to check it — the only macOS available to it is the `test (macos)` job on a PR, and a red macOS matrix would have blocked the MSRV bump alongside it. Flagging rather than guessing at the timing: whether to take macOS 26 now or wait for the deprecation announcement is a call about this repo's snapshot surface. Happy to open it as its own PR if you want the signal. ## CI Fully green on `7940a97`, the first merge of `main`: all 33 non-skipped checks, including `msrv`, all three `test` legs, `full-tests` on every platform, `nix-flake`, `minimal-versions`, `check-unused-dependencies`, `check-docs`, `link-check`, `feature-powerset`, and `codecov/patch`. That head is where the hand-written lock entry and the nightly pins were proven against the current `main`. `main` has since moved four commits (#3886, #3893, #3895, #3897) and is merged in again at `d8d1553`, alongside the nightly-pin rule above. #3895 touches `nightly.yaml`, so the pins were re-checked after that merge: still exactly two sites, `minimal-versions` and `check-unused-dependencies`, both on `nightly-2026-08-01`. Locally `pre-commit run --all-files` and `test_docs_are_in_sync` pass on this head. ## Weekly checks that produced no change - **LLM model pins** — no drift. `gpt-5.6-luna` is still how OpenAI's models page positions the "fast and affordable … lowest cost in the family" 5.6 variant; `gpt-5.3-codex-spark` is a Pro-only research preview, not a default. `haiku` / `claude-haiku-4.5` is still the smallest current Anthropic model. - **Statusline cache-check** — clean. `command_count` was 27, which includes the three calls the `-vv` diagnostic collector makes after the render, so the render itself is ~24 against a ~29 baseline measured before the recipe used `-vv`. The two duplicates the report flagged (`gh --version`, `git worktree list --porcelain`) are that same collector, not the render. Both the baseline arithmetic and the trap are now written down in the skill. - **Agent app integration surfaces** — nothing that changes what Worktrunk consumes. Claude Code 2.1.239 fixed `metadata.pluginRoot` resolution, but `.claude-plugin/marketplace.json` names an explicit `./plugins/worktrunk` source rather than a bare name, so it is unaffected; the `WorktreeCreate`/`WorktreeRemove` hooks and the statusline stdin schema are unchanged (`workspace.git_worktree` and `workspace.repo` exist but predate this window by several hundred releases). Codex, Gemini CLI, and OpenCode shipped only routine releases. - **README month** — already "August 2026". - **Dependency PRs** — none open. <details><summary>Verification</summary> - `rustup` resolves the new channel: `cargo 1.97.0 (c980f4866 2026-06-30)`, `rustc 1.97.0 (2d8144b78 2026-07-07)`, `clippy 0.1.97`. - `cargo clippy --all-targets --all-features -- -D warnings` passes on 1.97.0 — the check that matters most for a toolchain bump, since it compiles every target and feature under the new rustc and holds the new clippy to zero warnings. Doctests passed too. - Unit tests pass on 1.97.0: 979 + 11 + 1, zero failures. - Integration tests: 2000 passed, 1 failed — `test_copy_ignored_preserves_file_executable_permissions`, which expects `0644` and got `0664`. That is this sandbox's `umask 0002`, not the toolchain; the `test (linux|macos|windows)` matrix is the real gate. - `cargo run -- hook pre-merge --yes` is not a clean local signal on this runner: it ends on `pre-commit: exit status: 127` because pre-commit isn't installed in the tend sandbox, unrelated to the bump. - `cargo msrv verify` was not run locally (it rebuilds the graph per candidate); `ci.yaml`'s `msrv` job covers it. - Every version above was read from its upstream source of truth: `cargo info` / crates.io for the cargo tools, `static.rust-lang.org/dist/channel-rust-stable.toml` for Rust stable (1.98.0, 2026-08-20), the `nushell/nushell` and `PowerShell/PowerShell` release APIs, PyPI for pre-commit, `actions/runner-images` README for the image labels, and the vendors' own model pages for the LLM pins. - `rust-overlay` at the currently-locked revision was confirmed to stop at `1.96.0.nix`, and at the new revision to contain `1.97.0.nix` — this is why the lock has to move at all. </details> > _This was written by Claude Code on behalf of max-sixty_ --------- Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com> Co-authored-by: Maximilian Roos <m@maxroos.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Worktrunk
August 2026: Worktrunk was released at the start of the year, and has quickly become the most popular git worktree manager. It's built with love (there's no slop!). Please let me know any frictions at all; I'm intensely focused on continuing to make Worktrunk excellent, and the biggest help is folks posting problems they perceive.
Worktrunk is a CLI for git worktree management, designed for running AI agents in parallel.
Worktrunk's three core commands make worktrees as easy as branches. Plus, Worktrunk has a bunch of quality-of-life features to simplify working with many parallel changes, including hooks to automate local workflows.
A quick demo:
📚 Full documentation at worktrunk.dev 📚
Context: git worktrees
AI agents like Claude Code and Codex can handle longer tasks without supervision, such that it's possible to manage 5-10+ in parallel. Git's native worktree feature give each agent its own working directory, so they don't step on each other's changes.
But the git worktree UX is clunky. Even a task as small as starting a new
worktree requires typing the branch name three times: git worktree add -b feat ../repo.feat, then cd ../repo.feat.
Worktrunk makes git worktrees as easy as branches
Worktrees are addressed by branch name; paths are computed from a configurable template. Commands that take a branch also accept the path of the worktree it is checked out in.
Start with the core commands
Core commands:
| Task | Worktrunk | Plain git |
|---|---|---|
| Switch worktrees | wt switch feat |
cd ../repo.feat |
| Create + start Claude | wt switch -c -x claude feat |
|
| Clean up | wt remove |
|
| List with status | wt list |
git worktree list (paths only) |
Expand into the more advanced commands as needed
Workflow automation:
- Hooks — run commands on create, pre-merge, post-merge, etc
- LLM commit messages — generate commit messages from diffs
- Merge workflow — squash, rebase, merge, clean up in one command
- Interactive picker — browse worktrees with live diff and log previews
- Copy build caches — skip cold starts by sharing
target/,node_modules/, etc between worktrees wt list --full— CI status and AI-generated summaries per branch- PR checkout —
wt switch pr:123to jump straight to a PR's branch - Dev server per worktree —
hash_porttemplate filter gives each worktree a unique port - Aliases & per-branch variables — custom
wt <name>commands and branch-scoped state for hook templates - ...and lots more
Multiple parallel agents, same simple commands:
Install
Homebrew (macOS & Linux):
brew install worktrunk && wt config shell install
Shell integration allows commands to change directories.
Cargo:
cargo install worktrunk && wt config shell install
Windows & other
Windows. wt defaults to Windows Terminal's command, so Winget additionally installs Worktrunk as git-wt to avoid the conflict:
winget install max-sixty.worktrunk
git-wt config shell install
Alternatively, disable Windows Terminal's alias (Settings → Apps → Advanced app settings → App execution aliases → "Terminal"/"Terminal Preview") to use wt directly.
Free code signing provided by SignPath.io, certificate by SignPath Foundation — policy.
Arch Linux:
sudo pacman -S worktrunk && wt config shell install
Conda / Pixi (community-maintained feedstock):
conda install -c conda-forge worktrunk && wt config shell install
Or with Pixi: pixi global install worktrunk && wt config shell install.
Quick start
Create a worktree for a new feature:
$ wt switch --create feature-auth
✓ Created branch feature-auth from main and worktree @ ~/repo.feature-auth
This creates a new branch and worktree, then switches to it. Do your work, then check all worktrees with wt list:
$ wt list
Branch Status HEAD± main↕ main…± Remote⇅ Commit Age Message
@ feature-auth + ↑ +27 -8 ↑1 +31 4bc72dc 2h Add authenticati…
^ main ^⇡ ⇡1 0e631ad 1d Initial commit
○ Showing 2 worktrees, 1 with changes, 1 ahead, 1 column hidden
The @ marks the current worktree. + means staged changes, ↑1 means 1 commit ahead of main, ⇡ means unpushed commits.
When done, either:
PR workflow — commit, push, open a PR, merge via GitHub/GitLab, then clean up:
wt step commit # commit staged changes
gh pr create # or glab mr create
wt remove # after PR is merged
Local merge — squash, rebase onto main, fast-forward merge, clean up:
$ wt merge main
◎ Generating commit message and committing changes... (2 files, +53, no squashing needed)
Add authentication module
✓ Committed changes @ a1b2c3d
◎ Merging 1 commit to main @ a1b2c3d (no rebase needed)
* a1b2c3d Add authentication module
auth.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
lib.rs | 2 ++
2 files changed, 53 insertions(+)
✓ Merged to main (1 commit, 2 files, +53)
◎ Removing feature-auth worktree & branch in background (same commit as main, _)
○ Switched to worktree for main @ ~/repo
For parallel agents, create multiple worktrees and launch an agent in each:
wt switch -x claude -c feature-a -- 'Add user authentication'
wt switch -x claude -c feature-b -- 'Fix the pagination bug'
wt switch -x claude -c feature-c -- 'Write tests for the API'
The -x flag runs a command after switching; arguments after -- are passed to it. Configure post-start hooks to automate setup (install deps, start dev servers).
Next steps
- Learn the core commands:
wt switch,wt list,wt merge,wt remove - Set up hooks for automated setup
- Explore LLM commit messages, interactive picker, Claude Code integration, CI status & PR links
- Browse tips & patterns for recipes: aliases, dev servers, databases, agent handoffs, and more
- Extending Worktrunk — customize workflows with hooks & aliases
- Run
wt --helporwt <command> --helpfor quick CLI reference
Further reading
- Claude Code: Best practices for agentic coding — Anthropic's official guide, including the worktree pattern
- Shipping faster with Claude Code and Git Worktrees — incident.io's workflow for parallel agents
- Git worktree pattern discussion — Community discussion in the Claude Code repo
- @DevOpsToolbox's video on Worktrunk
- git-worktree documentation — Official git reference
Contributing
- ⭐ Star the repo
- Tell a friend about Worktrunk
- Open an issue — feedback, feature requests, even a small friction or imperfect user message, or a worktree pain not yet solved
- Share: X · Reddit · LinkedIn
📚 Full documentation at worktrunk.dev 📚

