mirror of
https://github.com/max-sixty/worktrunk.git
synced 2026-09-14 20:00:38 +08:00
60661a0d7e
SignPath Foundation's OSS program requires the attribution notice, and a route to the code signing policy, on a project's home page and download/release pages. Worktrunk had both only on the policy page itself — nothing on the README or the docs landing page. This puts the notice in the install section's Windows block, beside the artifacts it actually describes: > Free code signing provided by [SignPath.io](https://signpath.io/), certificate by [SignPath Foundation](https://signpath.org/) — [policy](https://worktrunk.dev/code-signing/). The edit is one line in `docs/content/worktrunk.md`; the README's Install→Further reading block is generated from it, so it propagates there and to both skill mirrors. The policy page leaves the docs navigation in the same change, so this is the single place it's linked from. `hide_from_nav = true` in a page's `[extra]` skips it in all three loops over `docs_section.pages`: the desktop TOC (`macros.html`), the mobile menu (`base.html`), and the prev/next flow nav (`page.html`). The page stays published and reachable at `/code-signing/` — unlisted, not removed. In the nav loops the skip wraps the whole per-page body, so a hidden page can't emit a stray group heading. In the prev/next loop it guards only the *candidate* assignments — the current-page test stays unguarded, because viewing a hidden page directly must still flip `found_current` or its own neighbours compute against the wrong page. Verified both directions: FAQ ends at `← Tips & Patterns` with no forward link, and the policy page keeps `← FAQ` back out into the docs. <details><summary>Why this came up, and the placement tradeoff</summary> Found while debugging why the `release-signing` signing policy shows INVALID in the SignPath console. That turned out to be unrelated and not fixable here — its certificate ("Release certificate 2026", subject `CN=SignPath Foundation`, on SignPath's HSM) is in `CSR PENDING` with no validity dates, awaiting CA issuance. The policy's own configuration is complete and correct. Worktrunk currently signs with the test certificate, which is VALID. The attribution gap was the one thing found on our side. Whether it bears on the pending review is unknown — the console exposes no application status. On placement: the notice sits inside the collapsed `<details>`, so it isn't visible until a reader expands "Windows & other". That's deliberate — the signing is Windows-specific and the notice reads better next to it than in the page chrome — but it is the least prominent placement that still counts as a link, and the terms ask for the notice *on* the home and download pages. Worth knowing if placement is ever queried during review. </details> > _This was written by Claude Code on behalf of max-sixty_ --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
223 lines
11 KiB
Markdown
223 lines
11 KiB
Markdown
+++
|
|
title = "Worktrunk"
|
|
description = "CLI for Git worktree management, designed for parallel AI agent workflows."
|
|
weight = 1
|
|
|
|
[extra]
|
|
canonical = "/"
|
|
+++
|
|
|
|
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:
|
|
|
|
<figure class="demo">
|
|
<picture>
|
|
<source srcset="/assets/docs/dark/wt-core.gif" media="(prefers-color-scheme: dark)">
|
|
<img src="/assets/docs/light/wt-core.gif" alt="Worktrunk demo showing wt list, wt switch, and hooks" width="1600" height="900">
|
|
</picture>
|
|
<figcaption>Listing worktrees, switching, cleaning up</figcaption>
|
|
</figure>
|
|
|
|
## 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:**
|
|
|
|
<table class="cmd-compare">
|
|
<thead>
|
|
<tr>
|
|
<th>Task</th>
|
|
<th>Worktrunk</th>
|
|
<th>Plain git</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>Switch worktrees</td>
|
|
<td>{% rawcode() %}wt switch feat{% end %}</td>
|
|
<td>{% rawcode() %}cd ../repo.feat{% end %}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Create + start Claude</td>
|
|
<td>{% rawcode() %}wt switch -c -x claude feat{% end %}</td>
|
|
<td>{% rawcode() %}git worktree add -b feat ../repo.feat && \
|
|
cd ../repo.feat && \
|
|
claude{% end %}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Clean up</td>
|
|
<td>{% rawcode() %}wt remove{% end %}</td>
|
|
<td>{% rawcode() %}cd ../repo && \
|
|
git worktree remove ../repo.feat && \
|
|
git branch -d feat{% end %}</td>
|
|
</tr>
|
|
<tr>
|
|
<td>List with status</td>
|
|
<td>{% rawcode() %}wt list{% end %}</td>
|
|
<td>{% rawcode() %}git worktree list{% end %} (paths only)</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
> Expand into the more advanced commands as needed
|
|
|
|
**Workflow automation:**
|
|
|
|
- **[Hooks](@/hook.md)** — run commands on create, pre-merge, post-merge, etc
|
|
- **[LLM commit messages](@/llm-commits.md)** — generate commit messages from diffs
|
|
- **[Merge workflow](@/merge.md)** — squash, rebase, merge, clean up in one command
|
|
- **[Interactive picker](@/switch.md#interactive-picker)** — browse worktrees with live diff and log previews
|
|
- **[Copy build caches](@/step.md#wt-step-copy-ignored)** — skip cold starts by sharing `target/`, `node_modules/`, etc between worktrees
|
|
- **[`wt list --full`](@/list.md#full-mode)** — [CI status](@/list.md#ci-status) and [AI-generated summaries](@/list.md#llm-summaries) per branch
|
|
- **[PR checkout](@/switch.md#pull-requests-and-merge-requests)** — `wt switch pr:123` to jump straight to a PR's branch
|
|
- **[Dev server per worktree](@/tips-patterns.md#dev-server-per-worktree)** — `hash_port` template filter gives each worktree a unique port
|
|
- **[Aliases](@/extending.md#aliases) & [per-branch variables](@/config.md#wt-config-state-vars)** — custom `wt <name>` commands and branch-scoped state for hook templates
|
|
- ...and **[lots more](#next-steps)**
|
|
|
|
Multiple parallel agents, same simple commands:
|
|
|
|
<figure class="demo">
|
|
<picture>
|
|
<source srcset="/assets/docs/dark/wt-zellij-omnibus.gif" media="(prefers-color-scheme: dark)">
|
|
<img src="/assets/docs/light/wt-zellij-omnibus.gif" alt="Worktrunk omnibus demo: multiple Claude agents in Zellij tabs with hooks, LLM commits, and merge workflow" width="1600" height="900">
|
|
</picture>
|
|
<figcaption>Multiple Claude agents in parallel with interactive picker, hooks, LLM commits, and merge</figcaption>
|
|
</figure>
|
|
|
|
## Install
|
|
|
|
**Homebrew (macOS & Linux):**
|
|
|
|
{{ terminal(cmd="brew install worktrunk && wt config shell install") }}
|
|
|
|
Shell integration allows commands to change directories.
|
|
|
|
**Cargo:**
|
|
|
|
{{ terminal(cmd="cargo install worktrunk && wt config shell install") }}
|
|
|
|
<details>
|
|
<summary><strong>Windows & other</strong></summary>
|
|
|
|
**Windows.** `wt` defaults to Windows Terminal's command, so Winget additionally installs Worktrunk as `git-wt` to avoid the conflict:
|
|
|
|
{{ terminal(cmd="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](https://signpath.io/), certificate by [SignPath Foundation](https://signpath.org/) — [policy](@/code-signing.md).
|
|
|
|
**Arch Linux:**
|
|
|
|
{{ terminal(cmd="sudo pacman -S worktrunk && wt config shell install") }}
|
|
|
|
**Conda / Pixi** (community-maintained [feedstock](https://github.com/conda-forge/worktrunk-feedstock)):
|
|
|
|
{{ terminal(cmd="conda install -c conda-forge worktrunk && wt config shell install") }}
|
|
|
|
Or with [Pixi](https://pixi.sh): `pixi global install worktrunk && wt config shell install`.
|
|
|
|
</details>
|
|
|
|
## Quick start
|
|
|
|
Create a worktree for a new feature:
|
|
|
|
<!-- ⚠️ AUTO-GENERATED from tests/snapshots/integration__integration_tests__list__quickstart_switch.snap — edit source to update -->
|
|
|
|
{% terminal(cmd="wt switch --create feature-auth") %}
|
|
<span class="cmd">wt switch --create feature-auth</span>
|
|
<span class=g>✓</span> <span class=g>Created branch <b>feature-auth</b> from <b>main</b> and worktree @ <b>~/repo.feature-auth</b></span>
|
|
{% end %}
|
|
|
|
<!-- END AUTO-GENERATED -->
|
|
|
|
This creates a new branch and worktree, then switches to it. Do your work, then check all worktrees with [`wt list`](@/list.md):
|
|
|
|
<!-- ⚠️ AUTO-GENERATED from tests/snapshots/integration__integration_tests__list__quickstart_list.snap — edit source to update -->
|
|
|
|
{% terminal(cmd="wt list") %}
|
|
<span class="cmd">wt list</span>
|
|
<b>Branch</b> <b>Status</b> <b>HEAD±</b> <b>main↕</b> <b>main…±</b> <b>Remote⇅</b> <b>Commit</b> <b>Age</b> <b>Message</b>
|
|
@ feature-auth <span class=c>+</span> <span class=d>↑</span> <span class=g>+27</span> <span class=r>-8</span> <span class=g>↑1</span> <span class=g>+31</span> <span class=d>4bc72dc</span> <span class=d>2h</span> <span class=d>Add authenticati…</span>
|
|
^ main <span class=d>^</span><span class=d>⇡</span> <span class=g>⇡1</span> <span class=d>0e631ad</span> <span class=d>1d</span> <span class=d>Initial commit</span>
|
|
|
|
<span class=d>○</span> <span class=d>Showing 2 worktrees, 1 with changes, 1 ahead, 1 column hidden</span>
|
|
{% end %}
|
|
|
|
<!-- END AUTO-GENERATED -->
|
|
|
|
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:
|
|
|
|
{{ terminal(cmd="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:
|
|
|
|
<!-- ⚠️ AUTO-GENERATED from tests/snapshots/integration__integration_tests__list__quickstart_merge.snap — edit source to update -->
|
|
|
|
{% terminal(cmd="wt merge main") %}
|
|
<span class="cmd">wt merge main</span>
|
|
<span class=c>◎</span> <span class=c>Generating commit message and committing changes... <span style='color:var(--bright-black,#555)'>(2 files, <span class=g>+53</span></span></span>, no squashing needed<span style='color:var(--bright-black,#555)'>)</span>
|
|
<span style='background:var(--bright-white,#fff)'> </span> <b>Add authentication module</b>
|
|
<span class=g>✓</span> <span class=g>Committed changes @ <span class=d>a1b2c3d</span></span>
|
|
<span class=c>◎</span> <span class=c>Merging 1 commit to <b>main</b> @ <span class=d>a1b2c3d</span> (no rebase needed)</span>
|
|
<span style='background:var(--bright-white,#fff)'> </span> * <span style='color:var(--yellow,#a60)'>a1b2c3d</span> Add authentication module
|
|
<span style='background:var(--bright-white,#fff)'> </span> auth.rs | 51 <span class=g>+++++++++++++++++++++++++++++++++++++++++++++++++++</span>
|
|
<span style='background:var(--bright-white,#fff)'> </span> lib.rs | 2 <span class=g>++</span>
|
|
<span style='background:var(--bright-white,#fff)'> </span> 2 files changed, 53 insertions(+)
|
|
<span class=g>✓</span> <span class=g>Merged to <b>main</b> <span style='color:var(--bright-black,#555)'>(1 commit, 2 files, <span class=g>+53</span></span></span><span style='color:var(--bright-black,#555)'>)</span>
|
|
<span class=c>◎</span> <span class=c>Removing <b>feature-auth</b> worktree & branch in background (same commit as <b>main</b>,</span> <span class=d>_</span><span class=c>)</span>
|
|
<span class=d>○</span> Switched to worktree for <b>main</b> @ <b>~/repo</b>
|
|
{% end %}
|
|
|
|
<!-- END AUTO-GENERATED -->
|
|
|
|
For parallel agents, create multiple worktrees and launch an agent in each:
|
|
|
|
{{ terminal(cmd="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](@/hook.md#hook-types) to automate setup (install deps, start dev servers).
|
|
|
|
## Next steps
|
|
|
|
- Learn the core commands: [`wt switch`](@/switch.md), [`wt list`](@/list.md), [`wt merge`](@/merge.md), [`wt remove`](@/remove.md)
|
|
- Set up [hooks](@/hook.md) for automated setup
|
|
- Explore [LLM commit messages](@/llm-commits.md), [interactive
|
|
picker](@/switch.md#interactive-picker), [Claude Code integration](@/claude-code.md), [CI
|
|
status & PR links](@/list.md#ci-status)
|
|
- Browse [tips & patterns](@/tips-patterns.md) for recipes: aliases, dev servers, databases, agent handoffs, and more
|
|
- [Extending Worktrunk](@/extending.md) — customize workflows with hooks & aliases
|
|
- Run `wt --help` or `wt <command> --help` for quick CLI reference
|
|
|
|
## Further reading
|
|
|
|
- [Claude Code: Best practices for agentic coding](https://www.anthropic.com/engineering/claude-code-best-practices) — Anthropic's official guide, including the worktree pattern
|
|
- [Shipping faster with Claude Code and Git Worktrees](https://incident.io/blog/shipping-faster-with-claude-code-and-git-worktrees) — incident.io's workflow for parallel agents
|
|
- [Git worktree pattern discussion](https://github.com/anthropics/claude-code/issues/1052) — Community discussion in the Claude Code repo
|
|
- [@DevOpsToolbox's video on Worktrunk](https://youtu.be/WBQiqr6LevQ?t=345)
|
|
- [git-worktree documentation](https://git-scm.com/docs/git-worktree) — Official git reference
|