1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# # User Configuration
#
# Create with `wt config create`. Values shown are defaults unless noted otherwise.
#
# Location:
#
# - macOS/Linux: `~/.config/worktrunk/config.toml` (or `$XDG_CONFIG_HOME` if set)
# - Windows: `%APPDATA%\worktrunk\config.toml`
#
# ## Worktree path template
#
# Controls where new worktrees are created.
#
# **Available template variables:**
#
# - `{{ repo_path }}` — absolute path to the repository root (e.g., `/Users/me/code/myproject`. Or for bare repos, the bare directory itself)
# - `{{ repo }}` — repository directory name (e.g., `myproject`)
# - `{{ owner }}` — primary remote owner path (may include subgroups like `group/subgroup`)
# - `{{ branch }}` — raw branch name (e.g., `feature/auth`)
# - `{{ branch | sanitize }}` — filesystem-safe: `/` and `\` become `-` (e.g., `feature-auth`)
# - `{{ branch | sanitize_db }}` — database-safe: lowercase, underscores, hash suffix (e.g., `feature_auth_x7k`)
# - `{{ branch | codename(2) }}` — deterministic friendly name from a ~1.26M-combo pool (e.g., `malleable-opah`)
#
# **Examples** for repo at `~/code/myproject`, branch `feature/auth`:
#
# Default — sibling directory (`~/code/myproject.feature-auth`):
#
# worktree-path = "{{ repo_path }}/../{{ repo }}.{{ branch | sanitize }}"
#
# Inside the repository (`~/code/myproject/.worktrees/feature-auth`):
#
# worktree-path = "{{ repo_path }}/.worktrees/{{ branch | sanitize }}"
#
# Friendly branch-derived names (`~/code/myproject.malleable-opah`):
#
# worktree-path = "{{ repo_path }}/../{{ repo }}.{{ branch | codename(2) }}"
#
# Friendly names with branch identity in a parent directory (`~/code/worktrees/feature-auth/malleable-opah`):
#
# worktree-path = "{{ repo_path }}/../worktrees/{{ branch | sanitize }}/{{ branch | codename(2) }}"
#
# Centralized worktrees directory (`~/worktrees/myproject/feature-auth`):
#
# worktree-path = "~/worktrees/{{ repo }}/{{ branch | sanitize }}"
#
# By remote owner path (`~/development/max-sixty/myproject/feature/auth`):
#
# worktree-path = "~/development/{{ owner }}/{{ repo }}/{{ branch }}"
#
# Bare repository (`~/code/myproject/feature-auth`):
#
# worktree-path = "{{ repo_path }}/../{{ branch | sanitize }}"
#
# `~` expands to the home directory. Relative paths resolve from `repo_path`.
#
# ## LLM commit messages
#
# Generate commit messages automatically during merge. Requires an external CLI tool.
#
# ### Claude Code
#
# [commit.generation]
# command = "CLAUDECODE= MAX_THINKING_TOKENS=0 claude -p --no-session-persistence --model=haiku --tools='' --disable-slash-commands --setting-sources='' --system-prompt=''"
#
# ### Codex
#
# [commit.generation]
# command = "codex exec -m gpt-5.1-codex-mini -c model_reasoning_effort='low' -c system_prompt='' --sandbox=read-only --json - | jq -sr '[.[] | select(.item.type? == \"agent_message\")] | last.item.text'"
#
# ### OpenCode
#
# [commit.generation]
# command = "opencode run -m anthropic/claude-haiku-4.5 --variant fast"
#
# ### llm
#
# [commit.generation]
# command = "llm -m claude-haiku-4.5"
#
# ### aichat
#
# [commit.generation]
# command = "aichat -m claude:claude-haiku-4.5"
#
# See LLM commits docs (https://worktrunk.dev/llm-commits/) for setup and Custom prompt templates (#custom-prompt-templates) for template customization.
#
# ## Command config
#
# ### List
#
# Persistent flag values for `wt list`. Override on command line as needed.
#
# [list]
# summary = false # Enable LLM branch summaries (requires [commit.generation])
#
# full = false # Show CI, main…± diffstat, and LLM summaries (--full)
# branches = false # Include branches without worktrees (--branches)
# remotes = false # Include remote-only branches (--remotes)
#
# task-timeout-ms = 0 # Kill individual git commands after N ms; 0 disables
# timeout-ms = 0 # Wall-clock budget for the entire collect phase; 0 disables
#
# ### Commit
#
# Shared by `wt step commit`, `wt step squash`, and `wt merge`.
#
# [commit]
# stage = "all" # What to stage before commit: "all", "tracked", or "none"
#
# ### Merge
#
# Most flags are on by default. Set to false to change default behavior.
#
# [merge]
# squash = true # Squash commits into one (--no-squash to preserve history)
# commit = true # Commit uncommitted changes first (--no-commit to skip)
# rebase = true # Rebase onto target before merge (--no-rebase to skip)
# remove = true # Remove worktree after merge (--no-remove to keep)
# verify = true # Run project hooks (--no-hooks to skip)
# ff = true # Fast-forward merge (--no-ff to create a merge commit instead)
#
# ### Remove
#
# Persistent flag values for `wt remove`. Override on command line as needed.
#
# [remove]
# delete-branch = true # Delete branch after removal (--no-delete-branch to keep)
#
# ### Switch
#
# [switch]
# cd = true # Change directory after switching (--no-cd to skip)
#
# [switch.picker]
# pager = "delta --paging=never" # Example: override git's core.pager for diff preview
#
# ### Step
#
# [step.copy-ignored]
# exclude = [] # Additional excludes (e.g., [".cache/", ".turbo/"])
#
# Built-in excludes always apply: VCS metadata directories (`.bzr/`, `.hg/`, `.jj/`, `.pijul/`, `.sl/`, `.svn/`) and tool-state directories (`.conductor/`, `.entire/`, `.worktrees/`). User config and project config exclusions are combined.
#
# ### Aliases
#
# Command templates that run as `wt <name>`. See the Extending Worktrunk guide (https://worktrunk.dev/extending/#aliases) for usage and flags.
#
# [aliases]
# greet = "echo Hello from {{ branch }}"
# url = "echo http://localhost:{{ branch | hash_port }}"
#
# Aliases defined here apply to all projects. For project-specific aliases, use the project config (https://worktrunk.dev/config/#project-configuration) `[aliases]` section instead.
#
# ### User project-specific settings
#
# User config can include a `[projects]` table for project-specific settings — worktree layout, setting overrides, anything else — separate from the project config (https://worktrunk.dev/config/#project-configuration) shared with teammates.
#
# Entries are keyed by project identifier — `<host>/<owner>/<repo>` derived from the primary remote URL (no `.git` suffix), or the canonical repo path when there is no remote. Run `wt config show` inside the repo to see the identifier for the current project; it appears in the `PROJECT CONFIG` section as `Identifier: …`.
#
# Scalar values (like `worktree-path`) replace the global value; everything else (hooks, aliases, etc.) appends, global first.
#
# [projects."github.com/user/repo"]
# worktree-path = ".worktrees/{{ branch | sanitize }}"
# list.full = true
# merge.squash = false
# remove.delete-branch = false
# pre-start.env = "cp .env.example .env"
# step.copy-ignored.exclude = [".repo-local-cache/"]
# aliases.deploy = "make deploy BRANCH={{ branch }}"
#
# Hooks support all three hook forms (https://worktrunk.dev/hook/#hook-forms). A table runs multiple commands concurrently; an array-of-tables pipeline runs steps in sequence. The dotted-key examples below are equivalent to the table forms — TOML treats `projects."github.com/user/repo".post-start.server = "..."` and a `[projects."github.com/user/repo".post-start]` table the same way:
#
# # Single command
# [projects."github.com/user/repo"]
# post-start = "mise trust"
#
# # Multiple commands, running concurrently
# [projects."github.com/user/repo".post-start]
# mise = "mise trust"
# server = "npm run dev"
#
# # Pipeline: steps run in sequence
# [[projects."github.com/user/repo".post-start]]
# install = "npm ci"
#
# [[projects."github.com/user/repo".post-start]]
# build = "npm run build"
# server = "npm run dev"
#
# ### Custom prompt templates
#
# Templates use minijinja (https://docs.rs/minijinja/) syntax.
#
# #### Commit template
#
# Available variables:
#
# - `{{ git_diff }}`, `{{ git_diff_stat }}` — diff content
# - `{{ branch }}`, `{{ repo }}` — context
# - `{{ recent_commits }}` — recent commit messages
# - `{{ user_guidance }}`, `{{ project_guidance }}` — rendered append fragments (see Appending to the prompt (https://worktrunk.dev/config/#appending-to-the-prompt))
#
# Default template:
#
# <!-- DEFAULT_TEMPLATE_START -->
# [commit.generation]
# template = """
# <task>Write a commit message for the staged changes below.</task>
#
# <format>
# - Subject line under 50 chars
# - For material changes, add a blank line then a body paragraph explaining the change
# - Output only the commit message, no quotes or code blocks
# </format>
#
# <style>
# - Imperative mood: "Add feature" not "Added feature"
# - Match recent commit style (conventional commits if used)
# - Describe the change, not the intent or benefit
# </style>
# {% if user_guidance %}
# <user-guidance>
# {{ user_guidance }}
# </user-guidance>
# {% endif %}{% if project_guidance %}
# <project-guidance>
# {{ project_guidance }}
# </project-guidance>
# {% endif %}
# <diffstat>
# {{ git_diff_stat }}
# </diffstat>
#
# <diff>
# {{ git_diff }}
# </diff>
#
# <context>
# Branch: {{ branch }}
# {% if recent_commits %}<recent_commits>
# {% for commit in recent_commits %}- {{ commit }}
# {% endfor %}</recent_commits>{% endif %}
# </context>
#
# """
# <!-- DEFAULT_TEMPLATE_END -->
#
# #### Squash template
#
# Available variables (in addition to commit template variables):
#
# - `{{ commits }}` — list of commits being squashed
# - `{{ target_branch }}` — merge target branch
#
# Default template:
#
# <!-- DEFAULT_SQUASH_TEMPLATE_START -->
# [commit.generation]
# squash-template = """
# <task>Write a commit message for the combined effect of these commits.</task>
#
# <format>
# - Subject line under 50 chars
# - For material changes, add a blank line then a body paragraph explaining the change
# - Output only the commit message, no quotes or code blocks
# </format>
#
# <style>
# - Imperative mood: "Add feature" not "Added feature"
# - Match the style of commits being squashed (conventional commits if used)
# - Describe the change, not the intent or benefit
# </style>
# {% if user_guidance %}
# <user-guidance>
# {{ user_guidance }}
# </user-guidance>
# {% endif %}{% if project_guidance %}
# <project-guidance>
# {{ project_guidance }}
# </project-guidance>
# {% endif %}
# <commits branch="{{ branch }}" target="{{ target_branch }}">
# {% for commit in commits %}- {{ commit }}
# {% endfor %}</commits>
#
# <diffstat>
# {{ git_diff_stat }}
# </diffstat>
#
# <diff>
# {{ git_diff }}
# </diff>
#
# """
# <!-- DEFAULT_SQUASH_TEMPLATE_END -->
#
# #### Appending to the prompt [experimental]
#
# `template-append` adds to the prompt instead of replacing it. The value is rendered as its own minijinja template (same variables) and injected into the default templates' `{{ user_guidance }}` slot — a `<user-guidance>` block right after `<style>`. It applies to both commit and squash. Use it for personal preferences without restating the whole template:
#
# [commit.generation]
# template-append = """
# - Explain the rationale in the body, not just the change
# """
#
# The project config (https://worktrunk.dev/config/#project-configuration) has a `template-append` of its own; it renders into a separate `<project-guidance>` block right after `<user-guidance>`.
#
# ## Hooks
#
# See `wt hook` (https://worktrunk.dev/hook/) for hook types, execution order, template variables, and examples. User hooks apply to all projects; project hooks (https://worktrunk.dev/config/#project-configuration) apply only to that repository.