- Add git_diff_stat template variable (always included in prompts)
- Implement progressive diff filtering when >400K chars:
- First filter out lock files (*.lock, *-lock.json, etc.)
- If still too large, truncate to 50 lines/file, max 50 files
- Update default templates to include <diffstat> section
- Use -c flags to ensure consistent git diff format regardless of user config
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Update help text for all state subcommands (default-branch, previous-branch,
ci-status, marker, logs) with detailed explanations of detection/behavior,
use cases, and examples. Remove horizontal rule separators between sections
in generated docs. Update help snapshots to reflect expanded output.
Running `wt config state default-branch` now defaults to `get`, making
the command shorter. For subcommands with options on `get` (like
`--refresh` or `--branch`), added help text explaining how to access
them via explicit `get` subcommand.
Changes:
- Make action optional for all state subcommands (default to Get)
- Add after_long_help for default-branch, ci-status, marker explaining
option access
- Update help text from "(git config)" to ".git/ (config entries and
log files)" for accuracy
- Update examples to use shorter syntax
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Extends the `wt config state` command with:
- `previous-branch` key: get/set/clear the previous branch used by `wt switch -`
- `state clear` (no args): clears all stored state at once
- `state get` (renamed from `show`): shows all stored state
Also improves consistency across state operations:
- All clear operations show info message when nothing to clear
- Renamed "cached state" to "stored state" (more accurate term)
- `clear_default_branch_cache()` returns bool for proper messaging
- JSON field uses `previous_branch` (not `switch_previous`)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Replace `wt config var` and `wt config cache` with a unified `wt config state`
subcommand that provides consistent get/set/clear semantics for all runtime
state.
New CLI structure uses key-first subcommands:
- `wt config state default-branch get [--refresh]`
- `wt config state default-branch set <branch>`
- `wt config state default-branch clear`
- `wt config state ci-status get [--refresh] [--branch=X]`
- `wt config state ci-status clear [--branch=X | --all]`
- `wt config state marker get [--branch=X]`
- `wt config state marker set <value> [--branch=X]`
- `wt config state marker clear [--branch=X | --all]`
- `wt config state logs get`
- `wt config state logs clear`
- `wt config state show`
Key changes:
- Added ability to manually set/clear default branch
- Each key is a subcommand with only its valid flags (type-safe at parse time)
- Removed runtime validation since clap handles invalid combinations
- Reuse format_relative_time_short for age formatting in logs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
The `approvals` subcommand logically belongs under `wt hook` since it manages approval of hook commands. This reorganizes the CLI structure to group related functionality together. Users should now use `wt hook approvals add/clear` instead of `wt config approvals add/clear`.
Refactor commit message prompts to be more concise and clearer. Replace verbose format/style explanations with structured XML-like tags and imperative mood guidance. Consolidate template examples and reduce redundant instructions.
Updates default templates in src/llm.rs and syncs changes to config example and documentation files along with related test snapshots.
* feat: Add user-level hooks that run for all repositories
Implement a new user hooks system that allows developers to define
personal hooks in `~/.config/worktrunk/config.toml` that execute for
all repositories. User hooks complement project hooks with these key
differences:
- **Scope**: Run for all repositories (vs. single repository)
- **Location**: User config file (vs. `.config/wt.toml`)
- **Approval**: Not required (user implicitly approves via config)
- **Execution order**: Run before project hooks
- **Skip behavior**: Skipped together with project hooks via `--no-verify`
### Implementation Details
**Configuration syntax** (same as project hooks):
```toml
[post-create]
setup = "echo 'Setting up worktree...'"
[pre-merge]
notify = "notify-send 'Merging {{ branch }}'"
```
**Hook types supported**: post-create, post-start, pre-commit, pre-merge,
post-merge, pre-remove
**Template variables**: Support all project hook variables plus `remote_url`
for repository-specific conditional logic
**New data structures**:
- `HookSource` enum: Distinguishes user vs. project hooks
- `prepare_user_commands()`: Expands user hook templates without approval
**Updated hook pipeline**:
- `HookPipeline::run_sequential()`: Accepts `HookSource` instead of
`phase` and `label_prefix`
- `HookPipeline::spawn_background()`: Renamed from `spawn_detached()` for
consistency
### Documentation Updates
- Updated help text and documentation to clarify `--no-verify` skips all
hooks (both user and project)
- Added "User hooks" section to config documentation with examples
- Added comparison table showing key differences from project hooks
- Added use cases and filtering examples
### Tests
Added comprehensive integration test suite (`tests/integration_tests/user_hooks.rs`)
covering:
- Basic execution of all hook types
- Execution order (user before project)
- No approval required for user hooks
- `--no-verify` skips all hooks
- Failure handling and behavior
- Template variable expansion
- Background hook execution
- Combined user and project hook scenarios
* Refine hooks: document remote_url, consolidate check
- Document remote_url template variable in cli.rs (syncs to docs)
- Move check_any_hook_configured into run_hook_with_filter
- Simplify standalone hook match arms
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update snapshots for symmetric project hook labeling
Project hooks now show "project" prefix (e.g., "Running project pre-merge")
for consistency with user hook labeling.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update docs to reflect user hooks in all hook references
- wt hook intro: Mention both user and project hooks
- --no-verify: Change "skip project hooks" to "skip all hooks"
- User config comment: Clarify verify skips all hooks
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add `wt hook show` command to display configured hooks with approval status
Adds a new `show` subcommand to `wt hook` that displays all configured hooks
from both user and project config files with their approval status. Project
hooks show a ❓ indicator when they require approval.
Features:
- Lists hooks organized by type (post-create, post-start, pre-commit, etc.)
- Shows both user-level hooks (run for all repos) and project-specific hooks
- Displays approval status for project hooks (❓ = needs approval)
- Optional `--expanded` flag to show template variables substituted with current context
- Optional hook type filter to show only specific hook types
- Output is displayed through a pager (like git help) when available
Also reorders hook subcommands to put `show` first, making hook inspection
the primary entry point before hook execution commands.
* feat: Add user-level hooks that run for all repositories
Personal hooks in ~/.config/worktrunk/config.toml now run automatically
before project hooks for all worktree operations. User hooks don't require
approval and use the same syntax and template variables as project hooks.
Changes:
- Add user hook support for all hook types (post-create, post-start,
pre-commit, pre-merge, post-merge, pre-remove)
- User hooks run before project hooks in execution order
- Skip all hooks with --no-verify (applies to both user and project)
- Add remote_url template variable for repository-aware filtering
- Update documentation and help text to reflect user hooks
- Refine hook labeling to distinguish "user" vs "project" hooks in output
- Add comprehensive integration tests for user hook functionality
* feat: Add user-level hooks and improve hook infrastructure
User hooks enable personal, repository-agnostic automations while maintaining
team standards via project hooks. Key improvements:
- User hooks defined in ~/.config/worktrunk/config.toml run before project hooks
- User hooks don't require approval (user implicitly approves by defining them)
- Post-start logs now include source prefix to avoid collisions (user/project)
- remote_url template variable added for conditional hook logic
- Hook output labels distinguish user vs project hooks for clarity
- All hooks skipped together via --no-verify flag
- --no-verify help text simplified from "Skip project hooks" to "Skip hooks"
Implementation:
- HookSource enum tracks whether hooks are user or project
- prepare_user_commands() handles user hooks (no approval needed)
- Hook pipeline shows source in output: "Running user pre-merge" vs "Running project pre-merge"
- Background operation names include source to prevent log file collisions
* feat: support SSH URLs and improve branch name escaping
Add support for ssh:// URL format in git remote parsing to handle
SSH URLs alongside existing git@ and https:// formats.
Improve branch name escaping for git config keys by using hex encoding
(-XX format) instead of percent-encoding, ensuring all non-alphanumeric
characters (except . and -) are properly escaped. This handles UTF-8
multi-byte sequences and enables reliable round-trip encoding/decoding
of branch names containing /, _, and other special characters.
* feat: Add user-level hooks and improve hook infrastructure
User hooks enable personal, repository-agnostic automations while maintaining
team standards via project hooks. Key improvements:
- User hooks defined in ~/.config/worktrunk/config.toml run before project hooks
- User hooks don't require approval (user implicitly approves by defining them)
- Post-start logs now include source prefix to avoid collisions (user/project)
- remote_url template variable added for conditional hook logic
- Hook output labels distinguish user vs project hooks for clarity
- All hooks skipped together via --no-verify flag
- --no-verify help text simplified from "Skip project hooks" to "Skip hooks"
Implementation:
- HookSource enum tracks whether hooks are user or project
- prepare_user_commands() handles user hooks (no approval needed)
- Hook pipeline shows source in output: "Running user pre-merge" vs "Running project pre-merge"
- Background operation names include source to prevent log file collisions
* Fix pre-remove hook approval with "Approve at the Gate" pattern
The pre-remove hook execution was incorrectly using auto_trust=true,
bypassing approval prompts. This commit introduces a design pattern
where approval happens exactly once at command entry points:
- Add collect_and_approve_hooks() helper for upfront approval
- wt remove now approves pre-remove hooks before any execution
- Add --force flag to skip approval prompts
- Thread auto_trust parameter through handle_remove_output
The pattern ensures approval happens at the "gate" (command entry),
eliminating error-prone threading of auto_trust through execution layers.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove pending snapshot file from statusline tests
The .statusline.rs.pending-snap file is no longer needed and should not be committed to version control.
* Implement "Approve at the Gate" pattern for all project hooks
Moves approval prompts to command entry points instead of hook execution.
Commands are now approved once in a batch before any hooks run, with template
expansion so users see actual values (branch names, paths) instead of
placeholders. This eliminates redundant prompts and simplifies the execution
layer by removing the `auto_trust` parameter threading.
Key changes:
- Rename `collect_and_approve_hooks()` to `collect_and_approve_hooks_with_context()`
and add `expand_commands_for_approval()` for showing expanded templates in prompts
- Remove `auto_trust` parameter from hook execution functions
- Simplify `HookSource::Project` enum variant (no longer carries approval state)
- Add gate approval at `wt switch --create`, `wt remove`, `wt step commit/squash`
- Update merge command collection to expand templates before approval batch
- Remove binary `rust_out` artifact and test snapshot file
* Clarify hook command runs on demand for testing and CI
Update documentation and help text to better explain that `wt hook`
runs hooks independently of normal worktree operations. Changes emphasize
the use cases (testing, CI, re-running after failure) rather than
describing it as "manually" running hooks.
Also simplify phrasing around user hooks and remove unnecessary markdown
formatting for consistency.
* Rename approval and hook functions to simpler names
Update function names to be more concise and consistent:
- `collect_and_approve_hooks_with_context()` → `approve_hooks()`
- `handle_standalone_run_hook()` → `run_hook()`
- `handle_standalone_commit()` → `step_commit()`
- `handle_standalone_add_approvals()` → `add_approvals()`
- `handle_standalone_clear_approvals()` → `clear_approvals()`
Also update documentation examples to reference the new names.
* Handle declined command approvals by skipping hooks while continuing operations
When users decline command approval, hooks are now skipped but the operation
proceeds. This applies consistently across all approval gates: merge, commit,
squash, remove, and hook execution.
Previously, declined approvals would still attempt hook execution. Now, the
verify flag is shadowed based on approval result - if declined, verify becomes
false to gate all subsequent hook execution. For explicit hook runs via
`wt hook`, a declined approval returns early since the entire purpose is hook
execution.
This ensures users have clear control: approving runs hooks, declining skips
them but continues the workflow.
* Fix wt hook approval: filter by name and use consistent target branch
Two fixes for `wt hook` command:
1. Pass name_filter to approval so `wt hook pre-merge --name foo` only
prompts for approval of the "foo" hook, not all hooks of that type.
Added `approve_hooks_filtered()` function that accepts optional name
filter parameter.
2. Use current branch as target for pre-merge/post-merge approval prompts
to match execution. Previously approval used default_branch while
execution used current branch, showing misleading command expansions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix wt hook show --expanded to expand {{ target }} for merge/commit hooks
The expand_command_template function now passes hook-specific extra vars:
- PreCommit: target = default branch (for comparison context)
- PreMerge/PostMerge: target = current branch (matches run_hook behavior)
Previously, --expanded would show raw {{ target }} placeholders for these
hook types because extra_vars was always empty.
Also added TODO for pre-remove approval context issue: when removing
another worktree, the approval preview uses current worktree context
instead of the target worktree context.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Clarify approvals docs
* Fix fish-style directory test on Windows
Unix-style absolute paths like `/tmp/test` are not recognized as absolute
on Windows, causing the test to fail. Guard these assertions with #[cfg(unix)].
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Add `wrap_help` feature to clap and `terminal_size` dependency to enable
automatic wrapping of help text based on terminal width. This improves
readability of long help descriptions by breaking them across multiple lines
instead of displaying as a single long line.
Changes:
- Enable `wrap_help` feature in clap configuration
- Add `terminal_size` crate as dependency for detecting terminal dimensions
- Update help template to support wrapping with proper formatting
- Help snapshots now show wrapped text at 150 character column width
Implements a system to include subcommand help as H2 sections within parent command docs pages using HTML comment placeholders.
In `cli.rs`, add `<!-- subdoc: subcommand-name -->` placeholders to a command's `after_long_help`. During `--help-page` generation, these expand to formatted sections with the subcommand's documentation and command reference.
The expansion process:
- Locates `<!-- subdoc: create -->` style placeholders
- Fetches the subcommand's help output via `get_help_reference()`
- Increases markdown heading levels (## → ###) so nested headings are children of the main H2
- Combines the subcommand's conceptual docs with a "Command reference" section
- Strips after_long_help from the help reference to avoid duplication
Also refactors help reference extraction into a reusable `get_help_reference()` function and adds `increase_heading_levels()` for proper nesting. Adds documentation in `CLAUDE.md` and expands `config.md` with full template content for `wt config create` and `wt config var` subcommands.
Command pages now preserve frontmatter in skeleton files (title, weight, group)
and replace only the AUTO-GENERATED marker region during sync. The END tag
mirrors the source ID to unambiguously match regions even with nested markers.
This allows manual editing of frontmatter and conceptual docs while keeping
auto-generated content synchronized. The main.rs generator outputs just the
content between START and END markers, and the sync test uses regex to find
and replace the exact region.
* Consolidate hook documentation into wt hook command
Move all lifecycle hook documentation from standalone hooks.md into the
wt hook --help output:
- Create `wt hook` command with subcommands for each hook type
(post-create, post-start, pre-commit, pre-merge, post-merge, pre-remove)
- Move hook execution from `wt step` to `wt hook`
- Add comprehensive template variable documentation to --help
- Consolidate all hook reference content into single canonical location
- Delete docs/content/hooks.md, replace with generated hook.md
- Update all links from /hooks/ to /hook/
The `wt step` command now focuses purely on git operations (commit,
squash, rebase, push) while `wt hook` handles user-defined lifecycle
commands.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update snapshot for clap's 'hook' suggestion on invalid command
* Fix hook command completion and test references
---------
Co-authored-by: Claude <noreply@anthropic.com>
Updates documentation and help text to wrap file paths (`.config/wt.toml`, `~/.config/worktrunk/config.toml`) in backticks, matching the existing style for inline code references throughout the docs and CLI help output.
* feat: pipe JSON context to hook stdin
Hooks now receive worktree context as JSON on stdin, enabling hooks
written in any language to access repo/branch/worktree information.
Changes:
- Foreground hooks (post-create, pre-merge, etc.) receive JSON via stdin
- Background hooks (post-start) receive JSON via printf pipe
- JSON includes hook_type and hook_name for self-aware hooks
- Optional fields are omitted when unavailable (not null)
- Windows uses PowerShell with proper escaping
Example hook:
```python
import json, sys
ctx = json.load(sys.stdin)
print(f"Setting up {ctx['repo']} on {ctx['branch']}")
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: add missing stdin_content parameter to Windows execute_streaming call
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Add `wt config create --project` to generate `.config/wt.toml` project
config files with documented examples. This makes it easier for users
to discover and create project configs.
Changes:
- Add --project flag to create project config instead of user config
- Show both user and project config templates in --help
- Update reference from dev/wt.example.toml to docs URL
- Add example to wt config --help
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Rename "Command defaults" section to "Command settings" and rephrase
descriptions to better explain that these are persistent flag values.
Update code examples to clarify default behavior and simplify comments
for better readability.
Move all configuration documentation from the separate configuration.md
file into the wt config command's help text. This ensures configuration
guidance is always accessible via `wt config --help` and eliminates
duplication between documentation and help output.
Includes detailed sections on user config (worktree paths, command
defaults, LLM settings, approvals), project config (lifecycle hooks),
shell integration, and environment variable overrides.
* Standardize doc headings to sentence case
Use sentence case for all documentation headings, matching modern
technical documentation conventions (GitHub, Stripe, Tailwind).
Exceptions preserved:
- Proper nouns: Claude Code, Worktrunk, Node.js, Python, Rust
- Acronyms: LLM, CI, JSON, API, CLI
- Code/commands: wt merge, post-create (stay lowercase)
- Questions: "Why Worktrunk?" (natural casing)
Changes span both manual docs and CLI help text (via cli.rs), with
auto-generated command pages regenerated to match.
* Update README and test snapshots for sentence case headings
Update auto-generated README sections and test snapshots to match
the sentence case heading changes in the previous commit.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Increase PTY drain wait to fix flaky Ubuntu CI test
The test_list_progressive_many_worktrees test was failing intermittently
on Ubuntu CI because 500ms wasn't enough time for the kernel to flush
all PTY buffer data under load. Increased MIN_DRAIN_WAIT_MS to 1000ms
to provide more margin for slow CI runners with many worktrees.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Update documentation to use Zola's native link handling instead of
standard markdown syntax for better site navigation and consistency.
This improves link resolution within the documentation system.
Reorder switch command documentation to place "Creating Worktrees" before
"Shortcuts" for better logical flow. Add auto-generated header comments to all
command docs (switch, list, merge, remove, select, config, step) to indicate
they're generated from CLI help. Adjust command weights in navigation to reflect
workflow order: switch, list, remove, merge, then utilities.
Command output blocks don't require language specification and render
correctly without it. Removing `bash` from the markdown fence makes
the markup cleaner and more semantically accurate.
Reorganize command documentation (switch, list, merge, remove, select, config, step)
for consistency and clarity. Restructure around user tasks: intro, examples, features,
then technical details. Update CLAUDE.md with documentation guidelines.
Add `test_command_pages_are_in_sync()` integration test to auto-update command pages
when `wt <cmd> --help-page` output changes, eliminating manual regeneration.
Update docs/CLAUDE.md to document the new sync test workflow instead of manual
regeneration steps.
Add dedicated documentation pages for each command (switch, list, merge,
remove, select, config, step) generated from CLI help text via new
--help-page flag. Pages include prose documentation from after_long_help
and command reference at bottom.
- Add --help-page flag to main.rs for generating doc pages
- Create individual command pages with Zola frontmatter
- Add sidebar grouping (Commands/Reference) via page.extra.group
- Update page.html template to render group labels
- Delete monolithic commands.md in favor of individual pages
- Tighten TOC spacing for child items
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>