---
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[0m
Includes shell integration, hooks, and saved state.[0m
Usage: [1m[36mwt config[0m [36m[OPTIONS][0m [36m<COMMAND>[0m
[1m[32mCommands:[0m
[1m[36mshell[0m Shell integration setup
[1m[36mcreate[0m Create configuration file
[1m[36mshow[0m Show configuration files & locations
[1m[36mupdate[0m Update deprecated config settings
[1m[36mapprovals[0m Manage command approvals
[1m[36malias[0m Inspect and preview aliases
[1m[36mplugins[0m Plugin management
[1m[36mstate[0m Manage internal data and cache
[1m[32mOptions:[0m
[1m[36m-h[0m, [1m[36m--help[0m
Print help (see a summary with '-h')
[1m[32mGlobal Options:[0m
[1m[36m-C[0m[36m [0m[36m<path>[0m
Working directory for this command
[1m[36m--config[0m[36m [0m[36m<path>[0m
User config file path
[1m[36m-v[0m, [1m[36m--verbose[0m[36m...[0m
Verbose output (-v: info logs + hook/alias template variable & output; -vv: debug logs + diagnostic report + trace.log/output.log under .git/wt/logs/)
[1m[36m-y[0m, [1m[36m--yes[0m
Skip approval prompts
[1m[32mExamples[0m
Install shell integration (required for directory switching):
[107m [0m [2m[0m[2m[34mwt[0m[2m config shell install[0m
Create user config file with documented examples:
[107m [0m [2m[0m[2m[34mwt[0m[2m config create[0m
Create project config file ([2m.config/wt.toml[0m) for hooks:
[107m [0m [2m[0m[2m[34mwt[0m[2m config create [0m[2m[36m--project[0m[2m[0m
Show current configuration and file locations:
[107m [0m [2m[0m[2m[34mwt[0m[2m config show[0m
[1m[32mConfiguration files[0m
File Location Contains Committed & shared
────────────── ─────────────────────────────── ─────────────────────────────────────────────── ──────────────────
User config [2m~/.config/worktrunk/config.toml[0m Worktree path template, LLM commit configs, etc ✗
Project config [2m.config/wt.toml[0m Project hooks, dev server URL ✓
Organizations can also deploy a system-wide config file for shared defaults — run [2mwt config show[0m for the platform-specific location.
[1mUser config[0m — personal preferences:
[107m [0m [2m# ~/.config/worktrunk/config.toml[0m
[107m [0m [2mworktree-path = [0m[2m[32m".worktrees/{{ branch | sanitize }}"[0m
[107m [0m
[107m [0m [2m[36m[commit.generation][0m
[107m [0m [2mcommand = [0m[2m[32m"CLAUDECODE= MAX_THINKING_TOKENS=0 claude -p --no-session-persistence --model=haiku --tools='' --disable-slash-commands --setting-sources='' --system-prompt=''"[0m
[1mProject config[0m — shared team settings:
[107m [0m [2m# .config/wt.toml[0m
[107m [0m [2m[36m[pre-start][0m
[107m [0m [2mdeps = [0m[2m[32m"npm ci"[0m
[107m [0m
[107m [0m [2m[36m[pre-merge][0m
[107m [0m [2mtest = [0m[2m[32m"npm test"[0m
[32mUSER CONFIGURATION[0m
Create with [2mwt config create[0m. Values shown are defaults unless noted otherwise.
Location:
- macOS/Linux: [2m~/.config/worktrunk/config.toml[0m (or [2m$XDG_CONFIG_HOME[0m if set)
- Windows: [2m%APPDATA%\worktrunk\config.toml[0m
[1m[32mWorktree path template[0m
Controls where new worktrees are created.
[1mAvailable template variables:[0m
- [2m{{ repo_path }}[0m — absolute path to the repository root (e.g., [2m/Users/me/code/myproject[0m. Or for bare repos, the bare directory itself)
- [2m{{ repo }}[0m — repository directory name (e.g., [2mmyproject[0m)
- [2m{{ owner }}[0m — primary remote owner path (may include subgroups like [2mgroup/subgroup[0m)
- [2m{{ branch }}[0m — raw branch name (e.g., [2mfeature/auth[0m)
- [2m{{ branch | sanitize }}[0m — filesystem-safe: [2m/[0m and [2m\[0m become [2m-[0m (e.g., [2mfeature-auth[0m)
- [2m{{ branch | sanitize_db }}[0m — database-safe: lowercase, underscores, hash suffix (e.g., [2mfeature_auth_x7k[0m)
[1mExamples[0m for repo at [2m~/code/myproject[0m, branch [2mfeature/auth[0m:
Default — sibling directory ([2m~/code/myproject.feature-auth[0m):
[107m [0m [2mworktree-path = [0m[2m[32m"{{ repo_path }}/../{{ repo }}.{{ branch | sanitize }}"[0m
Inside the repository ([2m~/code/myproject/.worktrees/feature-auth[0m):
[107m [0m [2mworktree-path = [0m[2m[32m"{{ repo_path }}/.worktrees/{{ branch | sanitize }}"[0m
Centralized worktrees directory ([2m~/worktrees/myproject/feature-auth[0m):
[107m [0m [2mworktree-path = [0m[2m[32m"~/worktrees/{{ repo }}/{{ branch | sanitize }}"[0m
By remote owner path ([2m~/development/max-sixty/myproject/feature/auth[0m):
[107m [0m [2mworktree-path = [0m[2m[32m"~/development/{{ owner }}/{{ repo }}/{{ branch }}"[0m
Bare repository ([2m~/code/myproject/feature-auth[0m):
[107m [0m [2mworktree-path = [0m[2m[32m"{{ repo_path }}/../{{ branch | sanitize }}"[0m
[2m~[0m expands to the home directory. Relative paths resolve from [2mrepo_path[0m.
[1m[32mLLM commit messages[0m
Generate commit messages automatically during merge. Requires an external CLI tool.
[32mClaude Code[0m
[107m [0m [2m[36m[commit.generation][0m
[107m [0m [2mcommand = [0m[2m[32m"CLAUDECODE= MAX_THINKING_TOKENS=0 claude -p --no-session-persistence --model=haiku --tools='' --disable-slash-commands --setting-sources='' --system-prompt=''"[0m
[32mCodex[0m
[107m [0m [2m[36m[commit.generation][0m
[107m [0m [2mcommand = [0m[2m[32m"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'"[0m
[32mOpenCode[0m
[107m [0m [2m[36m[commit.generation][0m
[107m [0m [2mcommand = [0m[2m[32m"opencode run -m anthropic/claude-haiku-4.5 --variant fast"[0m
[32mllm[0m
[107m [0m [2m[36m[commit.generation][0m
[107m [0m [2mcommand = [0m[2m[32m"llm -m claude-haiku-4.5"[0m
[32maichat[0m
[107m [0m [2m[36m[commit.generation][0m
[107m [0m [2mcommand = [0m[2m[32m"aichat -m claude:claude-haiku-4.5"[0m
See LLM commits docs for setup and Custom prompt templates for template customization.
[1m[32mCommand config[0m
[32mList[0m
Persistent flag values for [2mwt list[0m. Override on command line as needed.
[107m [0m [2m[36m[list][0m
[107m [0m [2msummary = [0m[2m[33mfalse[0m[2m [0m[2m# Enable LLM branch summaries (requires [commit.generation])[0m
[107m [0m
[107m [0m [2mfull = [0m[2m[33mfalse[0m[2m [0m[2m# Show CI, main…± diffstat, and LLM summaries (--full)[0m
[107m [0m [2mbranches = [0m[2m[33mfalse[0m[2m [0m[2m# Include branches without worktrees (--branches)[0m
[107m [0m [2mremotes = [0m[2m[33mfalse[0m[2m [0m[2m# Include remote-only branches (--remotes)[0m
[107m [0m
[107m [0m [2mtask-timeout-ms = [0m[2m[33m0[0m[2m [0m[2m# Kill individual git commands after N ms; 0 disables[0m
[107m [0m [2mtimeout-ms = [0m[2m[33m0[0m[2m [0m[2m# Wall-clock budget for the entire collect phase; 0 disables[0m
[32mCommit[0m
Shared by [2mwt step commit[0m, [2mwt step squash[0m, and [2mwt merge[0m.
[107m [0m [2m[36m[commit][0m
[107m [0m [2mstage = [0m[2m[32m"all"[0m[2m [0m[2m# What to stage before commit: "all", "tracked", or "none"[0m
[32mMerge[0m
Most flags are on by default. Set to false to change default behavior.
[107m [0m [2m[36m[merge][0m
[107m [0m [2msquash = [0m[2m[33mtrue[0m[2m [0m[2m# Squash commits into one (--no-squash to preserve history)[0m
[107m [0m [2mcommit = [0m[2m[33mtrue[0m[2m [0m[2m# Commit uncommitted changes first (--no-commit to skip)[0m
[107m [0m [2mrebase = [0m[2m[33mtrue[0m[2m [0m[2m# Rebase onto target before merge (--no-rebase to skip)[0m
[107m [0m [2mremove = [0m[2m[33mtrue[0m[2m [0m[2m# Remove worktree after merge (--no-remove to keep)[0m
[107m [0m [2mverify = [0m[2m[33mtrue[0m[2m [0m[2m# Run project hooks (--no-hooks to skip)[0m
[107m [0m [2mff = [0m[2m[33mtrue[0m[2m [0m[2m# Fast-forward merge (--no-ff to create a merge commit instead)[0m
[32mSwitch[0m
[107m [0m [2m[36m[switch][0m
[107m [0m [2mcd = [0m[2m[33mtrue[0m[2m [0m[2m# Change directory after switching (--no-cd to skip)[0m
[107m [0m
[107m [0m [2m[36m[switch.picker][0m
[107m [0m [2mpager = [0m[2m[32m"delta --paging=never"[0m[2m [0m[2m# Example: override git's core.pager for diff preview[0m
[32mStep[0m
[107m [0m [2m[36m[step.copy-ignored][0m
[107m [0m [2mexclude = [] [0m[2m# Additional excludes (e.g., [".cache/", ".turbo/"])[0m
Built-in excludes always apply: VCS metadata directories ([2m.bzr/[0m, [2m.hg/[0m, [2m.jj/[0m, [2m.pijul/[0m, [2m.sl/[0m, [2m.svn/[0m) and tool-state directories ([2m.conductor/[0m, [2m.entire/[0m, [2m.pi/[0m, [2m.worktrees/[0m). User config and project config exclusions are combined.
[32mAliases[0m
Command templates that run as [2mwt <name>[0m. See the Extending Worktrunk guide for usage and flags.
[107m [0m [2m[36m[aliases][0m
[107m [0m [2mgreet = [0m[2m[32m"echo Hello from {{ branch }}"[0m
[107m [0m [2murl = [0m[2m[32m"echo http://localhost:{{ branch | hash_port }}"[0m
Aliases defined here apply to all projects. For project-specific aliases, use the project config [2m[aliases][0m section instead.
[32mUser project-specific settings[0m
For context:
- Project config settings are shared with teammates.
- User configs generally apply to all projects.
- User configs _also_ has a [2m[projects][0m 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., [2mgithub.com/user/repo[0m). Scalar values (like [2mworktree-path[0m) replace the global value; everything else (hooks, aliases, etc.) appends, global first.
[107m [0m [2m[36m[projects."github.com/user/repo"][0m
[107m [0m [2mworktree-path = [0m[2m[32m".worktrees/{{ branch | sanitize }}"[0m
[107m [0m [2mlist.full = [0m[2m[33mtrue[0m
[107m [0m [2mmerge.squash = [0m[2m[33mfalse[0m
[107m [0m [2mpre-start.env = [0m[2m[32m"cp .env.example .env"[0m
[107m [0m [2mstep.copy-ignored.exclude = [[0m[2m[32m".repo-local-cache/"[0m[2m][0m
[107m [0m [2maliases.deploy = [0m[2m[32m"make deploy BRANCH={{ branch }}"[0m
[32mCustom prompt templates[0m
Templates use minijinja syntax.
[1mCommit template[0m
Available variables:
- [2m{{ git_diff }}[0m, [2m{{ git_diff_stat }}[0m — diff content
- [2m{{ branch }}[0m, [2m{{ repo }}[0m — context
- [2m{{ recent_commits }}[0m — recent commit messages
Default template:
[107m [0m [2m[36m[commit.generation][0m
[107m [0m [2mtemplate = [0m[2m[32m""[0m[2m[32m"[0m
[107m [0m [2m[32m<task>Write a commit message for the staged changes below.</task>[0m
[107m [0m
[107m [0m [2m[32m<format>[0m
[107m [0m [2m[32m- Subject line under 50 chars[0m
[107m [0m [2m[32m- For material changes, add a blank line then a body paragraph explaining the change[0m
[107m [0m [2m[32m- Output only the commit message, no quotes or code blocks[0m
[107m [0m [2m[32m</format>[0m
[107m [0m
[107m [0m [2m[32m<style>[0m
[107m [0m [2m[32m- Imperative mood: "[0m[2mAdd feature[0m[2m[32m" not "[0m[2mAdded feature[0m[2m[32m"[0m
[107m [0m [2m[32m- Match recent commit style (conventional commits if used)[0m
[107m [0m [2m[32m- Describe the change, not the intent or benefit[0m
[107m [0m [2m[32m</style>[0m
[107m [0m
[107m [0m [2m[32m<diffstat>[0m
[107m [0m [2m[32m{{ git_diff_stat }}[0m
[107m [0m [2m[32m</diffstat>[0m
[107m [0m
[107m [0m [2m[32m<diff>[0m
[107m [0m [2m[32m{{ git_diff }}[0m
[107m [0m [2m[32m</diff>[0m
[107m [0m
[107m [0m [2m[32m<context>[0m
[107m [0m [2m[32mBranch: {{ branch }}[0m
[107m [0m [2m[32m{% if recent_commits %}<recent_commits>[0m
[107m [0m [2m[32m{% for commit in recent_commits %}- {{ commit }}[0m
[107m [0m [2m[32m{% endfor %}</recent_commits>{% endif %}[0m
[107m [0m [2m[32m</context>[0m
[107m [0m
[107m [0m [2m[32m"[0m[2m[32m""[0m
[1mSquash template[0m
Available variables (in addition to commit template variables):
- [2m{{ commits }}[0m — list of commits being squashed
- [2m{{ target_branch }}[0m — merge target branch
Default template:
[107m [0m [2m[36m[commit.generation][0m
[107m [0m [2msquash-template = [0m[2m[32m""[0m[2m[32m"[0m
[107m [0m [2m[32m<task>Write a commit message for the combined effect of these commits.</task>[0m
[107m [0m
[107m [0m [2m[32m<format>[0m
[107m [0m [2m[32m- Subject line under 50 chars[0m
[107m [0m [2m[32m- For material changes, add a blank line then a body paragraph explaining the change[0m
[107m [0m [2m[32m- Output only the commit message, no quotes or code blocks[0m
[107m [0m [2m[32m</format>[0m
[107m [0m
[107m [0m [2m[32m<style>[0m
[107m [0m [2m[32m- Imperative mood: "[0m[2mAdd feature[0m[2m[32m" not "[0m[2mAdded feature[0m[2m[32m"[0m
[107m [0m [2m[32m- Match the style of commits being squashed (conventional commits if used)[0m
[107m [0m [2m[32m- Describe the change, not the intent or benefit[0m
[107m [0m [2m[32m</style>[0m
[107m [0m
[107m [0m [2m[32m<commits branch="[0m[2m{{ branch }}[0m[2m[32m" target="[0m[2m{{ target_branch }}[0m[2m[32m">[0m
[107m [0m [2m[32m{% for commit in commits %}- {{ commit }}[0m
[107m [0m [2m[32m{% endfor %}</commits>[0m
[107m [0m
[107m [0m [2m[32m<diffstat>[0m
[107m [0m [2m[32m{{ git_diff_stat }}[0m
[107m [0m [2m[32m</diffstat>[0m
[107m [0m
[107m [0m [2m[32m<diff>[0m
[107m [0m [2m[32m{{ git_diff }}[0m
[107m [0m [2m[32m</diff>[0m
[107m [0m
[107m [0m [2m[32m"[0m[2m[32m""[0m
[1m[32mHooks[0m
See [2mwt hook[0m for hook types, execution order, template variables, and examples. User hooks apply to all projects; project hooks apply only to that repository.
[32mPROJECT CONFIGURATION[0m
Project configuration lets teams share repository-specific settings — hooks, dev server URLs, and other defaults. The file lives in [2m.config/wt.toml[0m and is typically checked into version control.
To create a starter file with commented-out examples, run [2mwt config create --project[0m.
[1m[32mHooks[0m
Project hooks apply to this repository only. See [2mwt hook[0m for hook types, execution order, and examples.
[107m [0m [2mpre-start = [0m[2m[32m"npm ci"[0m
[107m [0m [2mpost-start = [0m[2m[32m"npm run dev"[0m
[107m [0m [2mpre-merge = [0m[2m[32m"npm test"[0m
[1m[32mDev server URL[0m
URL column in [2mwt list[0m (dimmed when port not listening):
[107m [0m [2m[36m[list][0m
[107m [0m [2murl = [0m[2m[32m"http://localhost:{{ branch | hash_port }}"[0m
[1m[32mForge platform override[0m
Override platform detection for SSH aliases or self-hosted instances:
[107m [0m [2m[36m[forge][0m
[107m [0m [2mplatform = [0m[2m[32m"github"[0m[2m [0m[2m# or "gitlab"[0m
[107m [0m [2mhostname = [0m[2m[32m"github.example.com"[0m[2m [0m[2m# Example: API host (GHE / self-hosted GitLab)[0m
[1m[32mCopy-ignored excludes[0m
Additional excludes for [2mwt step copy-ignored[0m:
[107m [0m [2m[36m[step.copy-ignored][0m
[107m [0m [2mexclude = [[0m[2m[32m".cache/"[0m[2m, [0m[2m[32m".turbo/"[0m[2m][0m
Built-in excludes always apply: VCS metadata directories ([2m.bzr/[0m, [2m.hg/[0m, [2m.jj/[0m, [2m.pijul/[0m, [2m.sl/[0m, [2m.svn/[0m) and tool-state directories ([2m.conductor/[0m, [2m.entire/[0m, [2m.pi/[0m, [2m.worktrees/[0m). User config and project config exclusions are combined.
[1m[32mAliases[0m
Command templates that run as [2mwt <name>[0m. See the Extending Worktrunk guide for usage and flags.
[107m [0m [2m[36m[aliases][0m
[107m [0m [2mdeploy = [0m[2m[32m"make deploy BRANCH={{ branch }}"[0m
[107m [0m [2murl = [0m[2m[32m"echo http://localhost:{{ branch | hash_port }}"[0m
Aliases defined here are shared with teammates. For personal aliases, use the user config [2m[aliases][0m section instead.
[32mSHELL INTEGRATION[0m
Worktrunk needs shell integration to change directories when switching worktrees. Install with:
[107m [0m [2m[0m[2m[34mwt[0m[2m config shell install[0m
For manual setup, see [2mwt config shell init --help[0m.
Without shell integration, [2mwt switch[0m prints the target directory but cannot [2mcd[0m into it.
[32mFirst-run prompts[0m
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 ([2mclaude[0m, [2mcodex[0m). Declining sets [2mskip-shell-integration-prompt[0m or [2mskip-commit-generation-prompt[0m automatically.
[32mOTHER[0m
[1m[32mEnvironment variables[0m
All user config options can be overridden with environment variables using the [2mWORKTRUNK_[0m prefix.
[32mNaming convention[0m
Config keys use kebab-case ([2mworktree-path[0m), while env vars use SCREAMING_SNAKE_CASE ([2mWORKTRUNK_WORKTREE_PATH[0m). The conversion happens automatically.
For nested config sections, use double underscores to separate levels:
Config Environment Variable
───────────────────────── ─────────────────────────────────────
[2mworktree-path[0m [2mWORKTRUNK_WORKTREE_PATH[0m
[2mcommit.generation.command[0m [2mWORKTRUNK_COMMIT__GENERATION__COMMAND[0m
[2mcommit.stage[0m [2mWORKTRUNK_COMMIT__STAGE[0m
Note the single underscore after [2mWORKTRUNK[0m and double underscores between nested keys.
[32mExample: CI/testing override[0m
Override the LLM command in CI to use a mock:
[107m [0m [2mWORKTRUNK_COMMIT__GENERATION__COMMAND=[0m[2m[32m"echo 'test: automated commit'"[0m[2m [0m[2m[34mwt[0m[2m merge[0m
[32mOther environment variables[0m
Variable Purpose
───────────────────────────────── ───────────────────────────────────────────────────────────────────────────────────────
[2mWORKTRUNK_BIN[0m Override binary path for shell wrappers; useful for testing dev builds
[2mWORKTRUNK_CONFIG_PATH[0m Override user config file location
[2mWORKTRUNK_SYSTEM_CONFIG_PATH[0m Override system config file location
[2mWORKTRUNK_PROJECT_CONFIG_PATH[0m Override project config file location (defaults to [2m.config/wt.toml[0m)
[2mXDG_CONFIG_DIRS[0m Colon-separated system config directories (default: [2m/etc/xdg[0m)
[2mWORKTRUNK_DIRECTIVE_CD_FILE[0m Internal: set by shell wrappers. wt writes a raw path; the wrapper [2mcd[0ms to it
[2mWORKTRUNK_DIRECTIVE_EXEC_FILE[0m Internal: set by shell wrappers. wt writes shell commands; the wrapper sources the file
[2mWORKTRUNK_SHELL[0m Internal: set by shell wrappers to indicate shell type (e.g., [2mpowershell[0m)
[2mWORKTRUNK_MAX_CONCURRENT_COMMANDS[0m Max parallel git commands (default: 32). Lower if hitting file descriptor limits.
[2mNO_COLOR[0m Disable colored output (standard)
[2mCLICOLOR_FORCE[0m Force colored output even when not a TTY
----- stderr -----