Loading theme preference
Ilia Bukin
← Back to blog

Worktrunk: the Rust CLI that makes parallel AI agents play nice with git

Sep 15, 2026
git
worktrees
AI agents
developer tools
rust
claude-code

If you have let an AI coding agent run unattended for more than a few minutes, you have probably hit the wall worktrunk exists to remove. Agents like Claude Code and Codex can handle long tasks without supervision, so the obvious move is to run several at once. The docs put the number at 5-10+ in parallel. Each agent needs somewhere to work that will not collide with the others. Git's native worktree feature gives every agent its own working directory, but the surrounding UX is clunky. Starting a worktree means typing the branch name three times: git worktree add -b feat ../repo.feat, then cd ../repo.feat. 1

Worktrunk is a Rust CLI for worktree management, designed for parallel AI agent workflows. 1 Worktrees are addressed by branch name, and paths are computed from a configurable template instead of being typed by hand. Commands that take a branch also accept the path of the worktree it checks out. 1 It is MIT OR Apache-2.0 licensed, installs via Homebrew, Cargo, Winget, pacman, and conda-forge, and sits at about 7.7k GitHub stars, enough to hold a spot on the weekly trending list. 12 Released at the start of this year, it is already at v0.77.0, out September 8, on a roughly weekly release cadence. 3

Three commands instead of the ceremony

The core is three commands. wt switch moves between worktrees and creates one if needed; wt list shows every worktree with live status; wt remove cleans up. The README compares them directly against plain git: 1

# worktrunk
wt switch -c -x claude feat

# plain git
git worktree add -b feat ../repo.feat && \
cd ../repo.feat && \
claude

The -x flag is the one that matters for agent work: it runs a program after switching, and everything after -- is passed to that program as literal arguments. The parallel-agent recipe is three lines: 1

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'

Each line creates a branch and a worktree, switches into it, and launches a Claude Code session pointed at that task. Later, wt list acts as a dashboard: @ marks the current worktree, + means staged changes, ↑1 means one commit ahead of main, ⇡ means unpushed commits. 1

The agent integrations are the interesting part

Worktrunk ships a plugin for each supported agent CLI: Claude Code, Codex, OpenCode, Pi, and Gemini CLI. 4 What a plugin provides depends on what hooks that CLI exposes. Activity tracking works everywhere: while an agent runs, its branch shows a 🤖 marker in wt list; when it finishes a turn and waits, the marker becomes 💬. Markers clear when a session ends, and wt config state marker clear removes any that go stale when a process is killed first. 4

Only Claude Code gets the full treatment. It is the one agent with worktree-lifecycle hooks, so worktrunk routes Claude's isolation mode through wt switch --create and wt remove. Worktrees that an agent creates itself still follow your naming template and run your hooks. 4 Claude Code also gets /wt-switch-create, a skill that starts a task in a fresh worktree without leaving the session. 4 The other four plugins stick to activity tracking, and their users invoke wt switch --create and wt remove directly. 4

The 0.77.0 release added Pi to that roster and tightened wt list for bigger setups: columns now size to the terminal width, long branch names are capped at 32 characters and elided, and detached worktrees get their own marker. 3 Earlier releases this cycle set Git 2.43 as the minimum supported version (0.75.0) and reworked -x to name a program rather than a shell string, so shell syntax now needs an explicit -x sh -- -c '...' (0.76.0). 3

Hooks turn worktree management into workflow automation

The second layer is hooks. Worktrunk runs shell commands at fixed points in the lifecycle: pre-switch, pre-start, post-start, pre-commit, post-commit, pre-merge, post-merge, pre-remove, post-remove. 5 The pre-* hooks block, so a failure aborts the operation. The post-* hooks run in the background with output logged. 5

Two details stand out. Project hooks live in .config/wt.toml, are shared with the team, and require approval the first time they run, with answers saved to ~/.config/worktrunk/approvals.toml. 5 That gate matters because a repo you clone can otherwise run arbitrary shell on your machine the moment you run wt switch. And hooks are templates with per-branch variables and a few genuinely useful filters. {{ branch | hash_port }} maps a branch to a stable port in the 10000-19999 range, the standard recipe for a dev server per worktree: 5

[post-start]
dev = "npm run dev -- --host {{ branch }}.localhost --port {{ branch | hash_port }}"

For dependency-heavy repos, wt step copy-ignored shares ignored files like target/ and node_modules/ between worktrees, reflinked where the filesystem allows it (APFS, btrfs, XFS), so ten worktrees do not mean ten cold builds. 15

wt merge: the whole landing sequence in one command

Landing changes is where agent work usually makes a mess. Unlike git merge, which merges the target into your current branch, wt merge merges the current branch into the target, like clicking "Merge pull request" locally. 6 The default pipeline: commit uncommitted changes, squash everything since the target into one commit, rebase, run pre-merge hooks, fast-forward the target, then remove the worktree and branch. 6 Flags adjust each step: --no-squash preserves history, --no-ff makes a merge commit, --no-remove keeps the worktree. 6

The pre-merge hook step is the part I like most. A pre-merge hook running cargo test and cargo clippy turns wt merge into a validation gate that runs before anything reaches the default branch, with no remote pipeline required. 6 With that configured, the agent loop is: review the diff, run wt merge, move on.

LLM commits, if you want them

Worktrunk can write your commit messages too. Point it at any command that reads a prompt from stdin and writes a message to stdout (the docs show claude -p, codex exec, opencode run, and llm), and it takes over message generation for wt step commit, wt step squash, and the commit inside wt merge. 7 Prompts are minijinja templates with variables like {{ git_diff }}, {{ branch }}, and {{ recent_commits }}. Users and projects can each append their own style guidance without replacing the default template. 7 No LLM configured? It falls back to deterministic messages built from the changed filenames. 7 The same pipeline feeds the branch summaries shown in wt switch's interactive picker and wt list --full. 7

Opinionated on purpose

Squashing each branch into one commit by default is the right call for agent work. A few hundred small commits per task is noise; one well-written change is what a reviewer wants. If you disagree, --no-squash is a flag away.

The scope is harder to ignore. This started as a worktree manager and has grown hooks, an approval system, forge integration (wt switch pr:123 jumps straight to a PR's branch), and LLM features. 18 That is a lot of surface for one CLI, but the through-line is coherent: one repository with many parallel change sets, plus everything needed to keep them isolated, validated, and landed. If you supervise more than one agent at a time, it is worth an afternoon.


  1. README: https://github.com/max-sixty/worktrunk
  2. GitHub trending this week: https://github.com/trending?since=weekly
  3. Releases: https://github.com/max-sixty/worktrunk/releases
  4. Agent integration docs: https://worktrunk.dev/claude-code/
  5. Hooks docs: https://worktrunk.dev/hook/
  6. wt merge docs: https://worktrunk.dev/merge/
  7. LLM commit messages docs: https://worktrunk.dev/llm-commits/
  8. wt switch docs: https://worktrunk.dev/switch/