wt hook
Run hooks independently of normal worktree operations.
Hooks normally run automatically during wt switch --create, wt merge, and wt remove. This command runs them on demand — useful for testing hooks during development, running in CI pipelines, or re-running after a failure.
Both user hooks (from ~/.config/worktrunk/config.toml) and project hooks (from .config/wt.toml) are supported.
Hook types
| Hook | When | Blocking | Fail-fast |
|---|---|---|---|
post-create | After worktree created | Yes | No |
post-start | After worktree created | No (background) | No |
pre-commit | Before commit during merge | Yes | Yes |
pre-merge | Before merging to target | Yes | Yes |
post-merge | After successful merge | Yes | No |
pre-remove | Before worktree removed | Yes | Yes |
Blocking: Command waits for hook to complete before continuing. Fail-fast: First failure aborts the operation.
post-create
Runs after worktree creation, blocks until complete. The worktree switch doesn't finish until these commands succeed.
Use cases: Installing dependencies, database migrations, copying environment files.
[]
= "npm ci"
= "npm run db:migrate"
= "cp .env.example .env"
post-start
Runs after worktree creation, in background. The worktree switch completes immediately; these run in parallel.
Use cases: Long builds, dev servers, file watchers, downloading large assets.
[]
= "npm run build"
= "npm run dev"
Output logged to .git/wt-logs/{branch}-{source}-post-start-{name}.log (source is user or project).
pre-commit
Runs before committing during wt merge, fail-fast. All commands must exit 0 for the commit to proceed.
Use cases: Formatters, linters, type checking.
[]
= "cargo fmt -- --check"
= "cargo clippy -- -D warnings"
pre-merge
Runs before merging to target branch, fail-fast. All commands must exit 0 for the merge to proceed.
Use cases: Tests, security scans, build verification.
[]
= "cargo test"
= "cargo build --release"
post-merge
Runs after successful merge in the main worktree, best-effort. Failures are logged but don't abort.
Use cases: Deployment, notifications, installing updated binaries.
= "cargo install --path ."
pre-remove
Runs before worktree removal during wt remove, fail-fast. All commands must exit 0 for removal to proceed.
Use cases: Cleanup tasks, saving state, notifying external systems.
[]
= "rm -rf /tmp/cache/{{ branch }}"
Timing during merge
- pre-commit — After staging, before squash commit
- pre-merge — After rebase, before merge to target
- pre-remove — Before removing worktree during cleanup
- post-merge — After cleanup completes
See wt merge for the complete pipeline.
Configuration
Hooks are defined in .config/wt.toml. They can be a single command or multiple named commands:
# Single command (string)
= "npm install"
# Multiple commands (table) — run sequentially in declaration order
[]
= "cargo test"
= "cargo build --release"
Template variables
Hooks can use template variables that expand at runtime:
| Variable | Example | Description |
|---|---|---|
{{ repo }} | my-project | Repository name |
{{ branch }} | feature-foo | Branch name |
{{ worktree }} | /path/to/worktree | Absolute worktree path |
{{ worktree_name }} | my-project.feature-foo | Worktree directory name |
{{ repo_root }} | /path/to/main | Repository root path |
{{ default_branch }} | main | Default branch name |
{{ commit }} | a1b2c3d4e5f6... | Full HEAD commit SHA |
{{ short_commit }} | a1b2c3d | Short HEAD commit SHA |
{{ remote }} | origin | Primary remote name |
{{ remote_url }} | git@github.com:user/repo.git | Remote URL |
{{ upstream }} | origin/feature | Upstream tracking branch |
{{ target }} | main | Target branch (merge hooks only) |
JSON context
Hooks also receive context as JSON on stdin, enabling hooks in any language:
=
The JSON includes all template variables plus hook_type and hook_name.
Security
Project commands require approval on first run:
🟡 repo needs approval to execute 3 commands:
⚪ post-create install:
echo 'Installing dependencies...'
❓ Allow and remember? [y/N]
- Approvals are saved to user config (
~/.config/worktrunk/config.toml) - If a command changes, new approval is required
- Use
--forceto bypass prompts (useful for CI/automation) - Use
--no-verifyto skip hooks
Manage approvals with wt hook approvals add and wt hook approvals clear.
User hooks
Define hooks in ~/.config/worktrunk/config.toml to run for all repositories. User hooks run before project hooks and don't require approval.
# ~/.config/worktrunk/config.toml
[]
= "echo 'Setting up worktree...'"
[]
= "notify-send 'Merging {{ branch }}'"
User hooks support the same hook types and template variables as project hooks.
Key differences from project hooks:
| Aspect | Project hooks | User hooks |
|---|---|---|
| Location | .config/wt.toml | ~/.config/worktrunk/config.toml |
| Scope | Single repository | All repositories |
| Approval | Required | Not required |
| Execution order | After user hooks | Before project hooks |
Skip hooks with --no-verify.
Use cases:
- Personal notifications or logging
- Editor/IDE integration
- Repository-agnostic setup tasks
- Filtering by repository using JSON context
Filtering by repository:
User hooks receive JSON context on stdin, enabling repository-specific behavior:
# ~/.config/worktrunk/config.toml
[]
= """
python3 -c '
import json, sys, subprocess
ctx = json.load(sys.stdin)
if "gitlab" in ctx.get("remote", ""):
subprocess.run(["glab", "mr", "create", "--fill"])
'
"""
Examples
Node.js / TypeScript
[]
= "npm ci"
[]
= "npm run dev"
[]
= "npm run lint"
= "npm run typecheck"
[]
= "npm test"
= "npm run build"
Rust
[]
= "cargo build"
[]
= "cargo fmt -- --check"
= "cargo clippy -- -D warnings"
[]
= "cargo test"
= "cargo build --release"
[]
= "cargo install --path ."
Python (uv)
[]
= "uv sync"
[]
= "uv run ruff format --check ."
= "uv run ruff check ."
[]
= "uv run pytest"
= "uv run mypy ."
Monorepo
[]
= "cd frontend && npm ci"
= "cd backend && cargo build"
[]
= "docker-compose up -d postgres"
[]
= "cd frontend && npm test"
= "cd backend && cargo test"
Common patterns
Fast dependencies + slow build — Install blocking, build in background:
= "npm install"
= "npm run build"
Progressive validation — Quick checks before commit, thorough validation before merge:
[]
= "npm run lint"
= "npm run typecheck"
[]
= "npm test"
= "npm run build"
Target-specific behavior:
= """
if [ "{{ target }}" = "main" ]; then
npm run deploy:production
elif [ "{{ target }}" = "staging" ]; then
npm run deploy:staging
fi
"""
Symlinks and caches — The {{ repo_root }} variable points to the main worktree:
[]
= "ln -sf {{ repo_root }}/node_modules node_modules"
= "cp {{ repo_root }}/.env.local .env"
See also
- wt merge — Runs hooks automatically during merge
- wt switch — Runs post-create/post-start hooks on
--create - wt config — Manage hook approvals
Command reference
wt hook - Run hooks independently
Usage: wt hook [OPTIONS] <COMMAND>
Commands:
show Show configured hooks
post-create Run post-create hooks
post-start Run post-start hooks
pre-commit Run pre-commit hooks
pre-merge Run pre-merge hooks
post-merge Run post-merge hooks
pre-remove Run pre-remove hooks
approvals Manage command approvals
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
Show commands and debug info
wt hook approvals
How Approvals Work
Commands from project hooks (.config/wt.toml) and LLM configuration require
approval on first run. This prevents untrusted projects from running arbitrary
commands.
Approval flow:
- Command is shown with expanded template variables
- User approves or denies
- Approved commands are saved to user config under
[projects."project-id"]
When re-approval is required:
- Command template changes (not just variable values)
- Project ID changes (repository moves)
Bypassing prompts:
--forceflag on individual commands (e.g.,wt merge --force)- Useful for CI/automation where prompts aren't possible
Examples
Pre-approve all commands for current project:
Clear approvals for current project:
Clear global approvals:
Command reference
wt hook approvals - Manage command approvals
Usage: wt hook approvals [OPTIONS] <COMMAND>
Commands:
add Store approvals in config
clear Clear approved commands from config
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
Show commands and debug info