worktrunk 0.42.0

A CLI for Git worktree management, designed for parallel AI agent workflows
Documentation
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
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
---
source: tests/integration_tests/help.rs
info:
  program: wt
  args:
    - config
    - "--help"
  env:
    CLICOLOR_FORCE: "1"
    COLUMNS: "500"
    GIT_EDITOR: ""
    LANG: C
    LC_ALL: C
    NO_COLOR: ""
    PSModulePath: ""
    RUST_LOG: warn
    SHELL: ""
    TERM: alacritty
    WORKTRUNK_APPROVALS_PATH: /nonexistent/test/approvals.toml
    WORKTRUNK_CONFIG_PATH: /nonexistent/test/config.toml
    WORKTRUNK_SYSTEM_CONFIG_PATH: /etc/xdg/worktrunk/config.toml
    WORKTRUNK_TEST_CLAUDE_INSTALLED: "0"
    WORKTRUNK_TEST_DELAYED_STREAM_MS: "-1"
    WORKTRUNK_TEST_EPOCH: "1735776000"
    WORKTRUNK_TEST_NUSHELL_ENV: "0"
    WORKTRUNK_TEST_OPENCODE_INSTALLED: "0"
    WORKTRUNK_TEST_POWERSHELL_ENV: "0"
    WORKTRUNK_TEST_SKIP_URL_HEALTH_CHECK: "1"
---
success: true
exit_code: 0
----- stdout -----
wt config - Manage user & project configs

Includes shell integration, hooks, and saved state.

Usage: wt config [OPTIONS] <COMMAND>

Commands:
  shell      Shell integration setup
  create     Create configuration file
  show       Show configuration files & locations
  update     Update deprecated config settings
  approvals  Manage command approvals
  alias      Inspect and preview aliases
  plugins    Plugin management
  state      Manage internal data and cache

Options:
  -h, --help
          Print help (see a summary with '-h')

Global Options:
  -C <path>
          Working directory for this command

      --config <path>
          User config file path

  -v, --verbose...
          Verbose output (-v: info logs + hook/alias template variable & output; -vv: debug logs + diagnostic report + trace.log/output.log under .git/wt/logs/)

  -y, --yes
          Skip approval prompts

Examples

Install shell integration (required for directory switching):

  wt config shell install

Create user config file with documented examples:

  wt config create

Create project config file (.config/wt.toml) for hooks:

  wt config create --project

Show current configuration and file locations:

  wt config show

Configuration files

      File                 Location                                Contains                     Committed & shared 
 ────────────── ─────────────────────────────── ─────────────────────────────────────────────── ────────────────── 
 User config    ~/.config/worktrunk/config.toml Worktree path template, LLM commit configs, etc ✗                  
 Project config .config/wt.toml                 Project hooks, dev server URL                   ✓                  

Organizations can also deploy a system-wide config file for shared defaults — run wt config show for the platform-specific location.

User config — personal preferences:

  # ~/.config/worktrunk/config.toml
  worktree-path = ".worktrees/{{ branch | sanitize }}"
  
  [commit.generation]
  command = "CLAUDECODE= MAX_THINKING_TOKENS=0 claude -p --no-session-persistence --model=haiku --tools='' --disable-slash-commands --setting-sources='' --system-prompt=''"

Project config — shared team settings:

  # .config/wt.toml
  [pre-start]
  deps = "npm ci"
  
  [pre-merge]
  test = "npm test"

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)

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 }}"

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 for setup and 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)

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/, .pi/, .worktrees/). User config and project config exclusions are combined.

Aliases

Command templates that run as wt <name>. See the Extending Worktrunk guide 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 [aliases] section instead.

User project-specific settings

For context:

- Project config settings are shared with teammates.
- User configs generally apply to all projects.
- User configs _also_ has a [projects] table which holds project-specific settings for the user, such as worktree layout and setting overrides. That's what this section covers.

Entries are keyed by project identifier (e.g., github.com/user/repo). 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
  pre-start.env = "cp .env.example .env"
  step.copy-ignored.exclude = [".repo-local-cache/"]
  aliases.deploy = "make deploy BRANCH={{ branch }}"

Custom prompt templates

Templates use minijinja syntax.

Commit template

Available variables:

- {{ git_diff }}, {{ git_diff_stat }} — diff content
- {{ branch }}, {{ repo }} — context
- {{ recent_commits }} — recent commit messages

Default template:

  [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>
  
  <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>
  
  """

Squash template

Available variables (in addition to commit template variables):

- {{ commits }} — list of commits being squashed
- {{ target_branch }} — merge target branch

Default template:

  [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>
  
  <commits branch="{{ branch }}" target="{{ target_branch }}">
  {% for commit in commits %}- {{ commit }}
  {% endfor %}</commits>
  
  <diffstat>
  {{ git_diff_stat }}
  </diffstat>
  
  <diff>
  {{ git_diff }}
  </diff>
  
  """

Hooks

See wt hook for hook types, execution order, template variables, and examples. User hooks apply to all projects; project hooks apply only to that repository.
PROJECT CONFIGURATION

Project configuration lets teams share repository-specific settings — hooks, dev server URLs, and other defaults. The file lives in .config/wt.toml and is typically checked into version control.

To create a starter file with commented-out examples, run wt config create --project.

Hooks

Project hooks apply to this repository only. See wt hook for hook types, execution order, and examples.

  pre-start = "npm ci"
  post-start = "npm run dev"
  pre-merge = "npm test"

Dev server URL

URL column in wt list (dimmed when port not listening):

  [list]
  url = "http://localhost:{{ branch | hash_port }}"

Forge platform override

Override platform detection for SSH aliases or self-hosted instances:

  [forge]
  platform = "github"  # or "gitlab"
  hostname = "github.example.com"  # Example: API host (GHE / self-hosted GitLab)

Copy-ignored excludes

Additional excludes for wt step copy-ignored:

  [step.copy-ignored]
  exclude = [".cache/", ".turbo/"]

Built-in excludes always apply: VCS metadata directories (.bzr/, .hg/, .jj/, .pijul/, .sl/, .svn/) and tool-state directories (.conductor/, .entire/, .pi/, .worktrees/). User config and project config exclusions are combined.

Aliases

Command templates that run as wt <name>. See the Extending Worktrunk guide for usage and flags.

  [aliases]
  deploy = "make deploy BRANCH={{ branch }}"
  url = "echo http://localhost:{{ branch | hash_port }}"

Aliases defined here are shared with teammates. For personal aliases, use the user config [aliases] section instead.

SHELL INTEGRATION

Worktrunk needs shell integration to change directories when switching worktrees. Install with:

  wt config shell install

For manual setup, see wt config shell init --help.

Without shell integration, wt switch prints the target directory but cannot cd into it.

First-run prompts

On first run without shell integration, Worktrunk offers to install it. Similarly, on first commit without LLM configuration, it offers to configure a detected tool (claude, codex). Declining sets skip-shell-integration-prompt or skip-commit-generation-prompt automatically.

OTHER

Environment variables

All user config options can be overridden with environment variables using the WORKTRUNK_ prefix.

Naming convention

Config keys use kebab-case (worktree-path), while env vars use SCREAMING_SNAKE_CASE (WORKTRUNK_WORKTREE_PATH). The conversion happens automatically.

For nested config sections, use double underscores to separate levels:

          Config                   Environment Variable          
 ───────────────────────── ───────────────────────────────────── 
 worktree-path             WORKTRUNK_WORKTREE_PATH               
 commit.generation.command WORKTRUNK_COMMIT__GENERATION__COMMAND 
 commit.stage              WORKTRUNK_COMMIT__STAGE               

Note the single underscore after WORKTRUNK and double underscores between nested keys.

Example: CI/testing override

Override the LLM command in CI to use a mock:

  WORKTRUNK_COMMIT__GENERATION__COMMAND="echo 'test: automated commit'" wt merge

Other environment variables

             Variable                                                      Purpose                                         
 ───────────────────────────────── ─────────────────────────────────────────────────────────────────────────────────────── 
 WORKTRUNK_BIN                     Override binary path for shell wrappers; useful for testing dev builds                  
 WORKTRUNK_CONFIG_PATH             Override user config file location                                                      
 WORKTRUNK_SYSTEM_CONFIG_PATH      Override system config file location                                                    
 WORKTRUNK_PROJECT_CONFIG_PATH     Override project config file location (defaults to .config/wt.toml)                     
 XDG_CONFIG_DIRS                   Colon-separated system config directories (default: /etc/xdg)                           
 WORKTRUNK_DIRECTIVE_CD_FILE       Internal: set by shell wrappers. wt writes a raw path; the wrapper cds to it            
 WORKTRUNK_DIRECTIVE_EXEC_FILE     Internal: set by shell wrappers. wt writes shell commands; the wrapper sources the file 
 WORKTRUNK_SHELL                   Internal: set by shell wrappers to indicate shell type (e.g., powershell)               
 WORKTRUNK_MAX_CONCURRENT_COMMANDS Max parallel git commands (default: 32). Lower if hitting file descriptor limits.       
 NO_COLOR                          Disable colored output (standard)                                                       
 CLICOLOR_FORCE                    Force colored output even when not a TTY                                                

----- stderr -----