* docs: add Quick Start section to front page
Shows the basic workflow with clear directory paths at each stage:
- Create worktree with wt switch --create
- Check status with wt list
- Two merge paths: PR workflow (push + gh pr create + wt remove)
and local merge (wt merge)
- Parallel agents example with -x flag
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: improve Quick Start with realistic examples and snapshot sync
- Add snapshot-based output sync for quickstart examples (switch, list, merge)
- Make examples more realistic: 53 lines of auth module changes instead of 9
- Show uncommitted changes in wt list demo (WIP state, not already committed)
- Add wt step commit to PR workflow since changes are now uncommitted
- Remove redundant git push from PR workflow (gh pr create auto-pushes)
- Suppress worktree-path hint in quickstart tests for cleaner output
- Add transform_zola_to_github() for converting HTML terminal markers to plain code blocks
Co-Authored-By: Claude <noreply@anthropic.com>
* Simplify code block formatting in README and tests
Convert bash code blocks to console format with command prompts and output
in a single block. Update regex pattern to optionally strip redundant bash
preamble when converting AUTO-GENERATED-HTML terminal markers.
* docs: remove redundant bash blocks before terminal examples
The terminal shortcodes already include the command with $ prefix,
so separate bash blocks showing just the command were redundant.
Also fix broken anchor link in config.md.
Co-Authored-By: Claude <noreply@anthropic.com>
* feat(docs): make terminal prompt non-copyable via CSS
Use CSS ::before pseudo-element to generate the $ prompt, making it
structurally non-copyable. This works with both manual text selection
and copy buttons.
Changes:
- Add .cmd::before { content: "$ "; } to generate prompt via CSS
- Remove explicit <span class="prompt">$</span> from HTML output
- Extract command from snapshot YAML header instead of parsing HTML
- Update expand_command_placeholders for command pages (list.md, etc.)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(docs): show commit step in quick start merge example
The merge example now shows staged changes being committed as part of
the wt merge workflow, reflecting a realistic user experience where
code is staged but not yet committed before merging.
Co-Authored-By: Claude <noreply@anthropic.com>
* style: fix cargo fmt formatting
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(tests): use cross-platform mock LLM for quickstart_merge test
The quickstart_merge test was using a shell script for the mock LLM
which doesn't work on Windows. Now uses the mock-stub system which
creates a cross-platform mock binary.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(test): use to_slash_lossy for Windows path compatibility
Windows paths with backslashes trigger shell metacharacter handling,
which wraps the command in `sh -c`. Bash can't parse Windows paths
like `C:\Users\...`. Converting to forward slashes with
to_slash_lossy() makes the path bash-compatible.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
The previous docs incorrectly presented this as a CI configuration option,
but in CI without TTY the prompt is already suppressed. The config is
actually set automatically when declining the prompt.
Co-authored-by: Claude <noreply@anthropic.com>
* docs(config): add H1 major sections with TOC support (#857)
* docs(config): add H1 major sections with TOC support
Add H1 headings for major sections (User Configuration, Project
Configuration, Shell Integration, Environment Variables) to improve
navigation and visual hierarchy.
Theme changes:
- Include H1s in sidebar TOC with divider lines
- Fix H1 link color (was orange due to missing zola-anchor rule)
- Style H1 headings consistently with H2 (underline, size)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs(config): improve TOC structure and auto-generate Subcommands header
- Auto-insert "# Subcommands" in help.rs before subdoc expansions
- Add "# Other" section containing Environment Variables and Command reference
- Rename "Commands" to "Command config" for clarity
- Fix TOC styling: align H1/H2 text, reduce vertical spacing, use sentence case
- Template: show H2s nested under H1s at same indent as standalone H2s
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: address codex review feedback
- Add default guard for h.children in TOC template
- Remove ineffective :first-of-type selector
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: use sentence case for Environment variables
Co-Authored-By: Claude <noreply@anthropic.com>
* test: update snapshots for config section header changes
Co-Authored-By: Claude <noreply@anthropic.com>
* test: update help_config_create snapshot
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix(docs): prevent h1 styling from breaking hero layout
The H1 major sections commit added `width: fit-content` and underline
styling to all h1 elements. This broke the hero because:
- fit-content shrinks the element, breaking text-align: center
- The underline appeared on the hero title
Fix by overriding these in .heading-text (used for page titles/hero):
- width: auto to restore centering
- > a::after { display: none } to hide underline
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(docs): align H1 TOC entries with H2s
Remove left border and custom padding from H1 entries in the sidebar
TOC. H1s are now distinguished only by bolder weight and extra top
margin, creating a cleaner visual hierarchy.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
The `expand_demo_placeholders` function now adds a trailing newline
after `</figure>` elements, ensuring proper paragraph separation in
web docs. Terminal `--help` output is unaffected since HTML comments
are stripped.
Also removes the inconsistent extra blank line from `wt select`'s
demo placeholder in cli.rs.
Co-authored-by: Claude <noreply@anthropic.com>
* docs(config): add H1 major sections with TOC support
Add H1 headings for major sections (User Configuration, Project
Configuration, Shell Integration, Environment Variables) to improve
navigation and visual hierarchy.
Theme changes:
- Include H1s in sidebar TOC with divider lines
- Fix H1 link color (was orange due to missing zola-anchor rule)
- Style H1 headings consistently with H2 (underline, size)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs(config): improve TOC structure and auto-generate Subcommands header
- Auto-insert "# Subcommands" in help.rs before subdoc expansions
- Add "# Other" section containing Environment Variables and Command reference
- Rename "Commands" to "Command config" for clarity
- Fix TOC styling: align H1/H2 text, reduce vertical spacing, use sentence case
- Template: show H2s nested under H1s at same indent as standalone H2s
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: address codex review feedback
- Add default guard for h.children in TOC template
- Remove ineffective :first-of-type selector
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: use sentence case for Environment variables
Co-Authored-By: Claude <noreply@anthropic.com>
* test: update snapshots for config section header changes
Co-Authored-By: Claude <noreply@anthropic.com>
* test: update help_config_create snapshot
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add step relocate command
Adds `wt step relocate` to move worktrees to their expected paths based on
the `worktree-path` template. Supports dry-run preview, filtering by branch
name, and auto-committing dirty worktrees. Handles special case of main
worktree by switching to default branch and creating a new worktree.
* Add `--clobber` flag and cycle resolution to `step relocate`
Implement full swap/cycle handling and non-worktree blocker management for
relocate command. Adds `--clobber` flag to automatically backup blocking
paths, dependency graph processing to handle worktree cycles via temporary
locations, and comprehensive spec documentation.
Key changes:
- Add `--clobber` flag to back up non-worktree paths at target locations
- Implement cycle detection and resolution using temp directory
- Build dependency graph to coordinate multi-worktree moves
- Handle main worktree relocation by creating new worktree + switching
- Add test cases for swap, clobber, and cycle scenarios
- Canonicalize temp home paths on macOS for snapshot consistency
* fix: address Codex review issues in step relocate
- Refuse to clobber existing worktrees (would corrupt git metadata)
- Prefer non-main worktree when breaking cycles (git can't move main)
- Sanitize branch names for temp paths (feature/foo -> feature-foo)
- Track original path for shell cd in temp-relocated worktrees
- Show template errors as warnings instead of silently dropping
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add coverage for clobber refusing to overwrite worktrees
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add relocate --commit coverage test
Tests the commit_worktree_changes function by configuring a mock LLM
and verifying that dirty worktrees are auto-committed before relocating.
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: simplify step relocate and improve coverage
- Change unreachable defensive code to expect() with explanation
- Simplify multi-line cformat! calls to single-line (improves LLVM coverage)
- Add test_relocate_mixed_success_and_skip to cover "relocated X, skipped Y" path
- Add test_relocate_dirty_with_commit to cover commit_worktree_changes function
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: remove shell cd for temp-to-final moves, simplify summary
- Remove shell directory update for temp-to-final worktree moves
(rare case where user is inside a worktree during cycle resolution)
- Simplify summary pluralization with inline closure
- Remove unused original_path tracking from temp_relocated
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: simplify remaining cformat! calls in step_relocate
Extract multi-line cformat! macro calls to single-line variables
to improve LLVM coverage instrumentation.
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: remove defensive early return in commit_worktree_changes
The early return when no staged changes was unreachable - if is_dirty()
returned true, git add -A must stage something. Removing improves coverage
and follows fail-fast principles.
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: simplify step_relocate for better coverage
- Remove redundant exists() check before create_dir_all
- Extract cformat! to single-line variable in commit_worktree_changes
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: revert configure_shell cosmetic changes to reduce diff
Reverts format_path_for_display changes that were unrelated to step relocate
and were reducing coverage percentage since they're in error paths.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: harden step relocate against edge cases
Fixes identified by adversarial testing:
1. Empty default branch validation - fails early with actionable error
instead of confusing "git checkout ''" errors
2. Same-target conflict handling - `is_target_empty` now returns
`Option<bool>` to gracefully skip when target is unexpectedly
blocked (TOCTOU race or same-target conflict)
3. Main worktree rollback - if `git worktree add` fails after
checkout, restore the original branch
Adds test for same-target scenario that previously panicked.
Co-Authored-By: Claude <noreply@anthropic.com>
* Move step relocate plan to Rust module spec
Moved the comprehensive plan from .claude/plans/step-relocate-spec.md
to a Rust doc comment on the step_relocate function. This makes the
specification more discoverable and keeps it synchronized with the
implementation.
The doc comment now includes:
- Complete flag descriptions
- Detailed algorithm explanation
- Multiple scenario examples (swap, chain, mixed, clobber, main worktree)
- Implementation notes
- Test case list
Co-authored-by: Maximilian Roos <max-sixty@users.noreply.github.com>
* test: add coverage for step relocate edge cases
Add tests for:
- Template expansion error handling (invalid variable)
- Empty default branch validation (non-existent configured branch)
These cover lines 844-847 and 890-895 in step_commands.rs that were
flagged by codecov/patch.
Co-Authored-By: Claude <noreply@anthropic.com>
* Improve step relocate output messages
- Use gutter formatting for template error details (per output guidelines)
- Fix misleading summary when template errors occurred
- Show source path in temp-relocated worktree success messages
- Use bright-black styling for flags in hints (--commit, --clobber)
- Use concrete example in default branch error message
Co-Authored-By: Claude <noreply@anthropic.com>
* Use gutter for dry-run preview in step relocate
Per output guidelines: every user-facing message needs symbol or gutter.
The dry-run preview now uses gutter formatting instead of plain indentation.
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix: use wt command for setting default branch
The error message now suggests 'wt config state default-branch set main'
instead of the raw git config command.
Co-Authored-By: Claude <noreply@anthropic.com>
* Refactor commit pipeline to accept WorkingTree parameter
Extract commit staging and execution into CommitGenerator to eliminate
duplicate commit logic in step_relocate. Add show_progress parameter to
control progress message display for bulk operations. Add repo() accessor
to WorkingTree for repository access.
* refactor: extract step_relocate into modular pipeline with explicit types
Split the 500-line monolithic step_relocate function into a clean pipeline:
- gather_candidates() finds worktrees not at expected paths
- validate_candidates() checks locked/dirty, handles --commit
- RelocationExecutor encapsulates the dependency graph algorithm
New types document each stage: RelocationCandidate, ValidatedCandidate,
GatherResult, ValidationResult. The complex swap/cycle resolution logic
is now isolated in RelocationExecutor with clear methods for each phase.
Co-authored-by: Claude <noreply@anthropic.com>
* fix: update test to use correct commit.generation config format
The test was using the old `args` field which no longer exists. The
command should be a complete shell string that receives the prompt
via stdin.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Maximilian Roos <max-sixty@users.noreply.github.com>
* docs(config): trim project config section, link to hook.md
Reduce duplication by removing hook examples from the project config
section and linking to hook.md instead. Keep only non-hook settings
(list.url and ci.platform) with concise inline comments.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: update help_config_long snapshot for trimmed project config section
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
- Remove reference to deprecated template-file options
- Add missing {{ git_diff_stat }} template variable
- Clarify which variables are squash-template only
- Move variables table after example for natural reading order
Co-authored-by: Claude <noreply@anthropic.com>
- Update deprecated [commit-generation] config format to [commit.generation]
with single command string (per f8aaead5b)
- Add context window gauge (moon phase 🌕→🌑) to statusline docs
- Add remote-only branch CI status detection note for --remotes flag
- Update demo build script to use new config format
- Sync auto-generated docs and skill references
Co-authored-by: Claude <noreply@anthropic.com>
* feat: add per-project hooks with append semantics
Per-project hooks in user config now append to global hooks rather than
replacing them. Execution order: global → per-project → project.
Also:
- Move hooks into OverridableConfig for consistency
- Rename UserConfig.overrides to UserConfig.configs
- Add schemars for deriving valid config keys from JsonSchema
- Replace manual VALID_USER_CONFIG_KEYS with schema-derived function
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: unify config validation on JsonSchema
Both UserConfig and ProjectConfig now use JsonSchema-derived keys for
validation instead of serde HashMap catchall. This:
- Removes `unknown` field from ProjectConfig
- Removes `unknown()` method from WorktrunkConfig trait
- Simplifies `is_valid_key` to not need value parameter
- Adds JsonSchema to JSON output types for future schema generation
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: document per-project hooks in setting overrides section
- Add per-project hooks to Setting overrides (Experimental) section
- Update hook.md table to show execution order with per-project hooks
- Replace JSON context example with one showing complex conditionals
- Keep documentation DRY by linking from hook.md to config.md
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: use consistent terminology (user config, not settings)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Add a "Monitor hook logs" section to tips-patterns showing how to follow
background hook output in real-time with `tail -f` and create an alias
for frequent use.
Closes#803
Co-authored-by: Claude <noreply@anthropic.com>
* added verbose flag
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* docs: add Codex config and optimize Claude Code for LLM commits
Add OpenAI Codex CLI as an option for LLM commit message generation.
Configure with gpt-5.1-codex-mini model, low reasoning effort, and
read-only sandbox. Uses jq to parse JSON output.
Update Claude Code config with optimization flags that disable tools,
skills, settings, and system prompt for faster text-only output.
Add bench-llm-commits task to Taskfile for comparing tool performance.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Restructure the per-project settings documentation to better distinguish
between user config and project config. The section now clearly explains
the two-config system before introducing per-project user settings as a
third category.
Key changes:
- Rename section from "Per-project settings" to "User project-specific settings"
- Add intro establishing user/project config dichotomy
- Split into subsections: "Approved hook commands" and "Setting overrides"
- Remove misplaced reference to project config hooks
- Link to project config documentation for clarity
Co-authored-by: Claude <noreply@anthropic.com>
* feat: add --hook flag to wt config state logs get
Adds a --hook flag to `wt config state logs get` that returns the path
to a specific hook's log file, making it easy to stream logs:
tail -f "$(wt config state logs get --hook=post-start:server)"
Hook specification formats:
- <hook-type>:<name> (e.g., post-start:server, post-create:install)
- <name> (e.g., remove, for hooks without explicit type)
Also adds --worktree flag to get logs for a different branch.
Closes#803https://claude.ai/code/session_01SuPbdD25Z6BbifGJY1jcRF
* fix: address code review feedback for hook logs feature
- Fix help text: clarify format is `<name>` for simple operations, not `<hook-type>`
- Add missing hook types: pre-remove, post-remove to fallback search
- Replace catch-all `_ =>` with explicit unreachable!() for clarity
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: rename --worktree to --branch for consistency
Other state commands use --branch (ci-status, marker), so use the same
flag name here for consistency.
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: introduce HookLog as single source of truth for log naming
Replace ad-hoc string formatting with a structured HookLog enum that
handles both creation and lookup of log files. The CLI now requires
explicit format: `source:hook-type:name` for hooks or `internal:op`
for internal operations.
- Add HookLog enum with Hook and Internal variants
- Add InternalOp enum for internal operations (currently just Remove)
- Update spawn_detached to take HookLog instead of string
- Update handle_logs_get to use HookLog::parse
- Add strum::EnumString to HookSource for parsing
Co-Authored-By: Claude <noreply@anthropic.com>
* style: move imports to top of modules
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: improve HookLog with to_spec, dynamic valid types, better errors
- Add to_spec() method for roundtrip conversion
- Use strum::IntoEnumIterator to generate valid hook types dynamically
- Inline parse_source/parse_hook_type (thin wrappers)
- Improve "not found" error to show expected filename
- Add roundtrip test for parse(to_spec(x)) == x
- Fix stale doc comment (operation -> internal:op)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: update logs get description and add hook docs reference
- Change "List background operation log files" to "Get log file paths"
- Add wt config state logs to hook docs "See also" section
Co-Authored-By: Claude <noreply@anthropic.com>
* style: use bold styling for dynamic values in error messages
Replace single quotes with <bold> styling for dynamic values in error
messages, per writing-user-outputs guidelines. Also use proper error
context chains for multiline errors.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Add concrete TOML examples immediately after the configuration files
table to make it clearer what each config file is for:
- User config: personal preferences (worktree-path, commit-generation)
- Project config: shared team settings (post-create, pre-merge hooks)
This addresses user feedback that the distinction between user and
project config was confusing.
Closes#801
Co-authored-by: Claude <noreply@anthropic.com>
* refactor: restructure commit-generation config to [commit.generation]
- Move `[commit-generation]` to `[commit.generation]` (nested under commit)
- Replace `command` + `args` with single `command` string (shell execution)
- Add deprecation warning for old format with backward compatibility
- Update docs to present Claude CLI and llm as equal options
The new format uses shell execution (`sh -c`) so environment variables
can be set inline in the command string.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: update tests and docs for new commit.generation config format
Fix test regressions identified by Codex review where tests using
WORKTRUNK_COMMIT_GENERATION__ARGS were silently failing because
args is now ignored with the new shell-based command format.
Tests now use the correct pattern:
WORKTRUNK_COMMIT_GENERATION__COMMAND="cat >/dev/null && echo 'message'"
Also update CLI docs to show:
- New config path: commit.generation.command (not commit-generation.command)
- New env var format: WORKTRUNK_COMMIT__GENERATION__COMMAND
- Remove args documentation (no longer applicable)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: update doc comments and add validation for new config path
Address Codex review feedback:
- Update per-project doc example to show new format
(commit.generation instead of commit-generation)
- Update env var comment to show new format
(COMMIT__GENERATION__COMMAND instead of COMMIT_GENERATION__COMMAND)
- Add validation for projects.*.commit.generation path
(was only validating deprecated commit-generation path)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: address remaining Codex review issues
- Use ShellConfig for LLM command execution (Windows compatibility)
- Improve error handling when LLM stderr is empty
- Format reproduction commands with conditional sh -c wrapping
- Update tests to use new env var format (WORKTRUNK_COMMIT__GENERATION__)
- Make test assertion more specific ([commit] not just "commit")
- Document cformat safety for shell commands in output guidelines
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: use shell_escape crate for reproduction command escaping
Replace manual single-quote escaping with the shell_escape crate
which is already a dependency used elsewhere in the codebase.
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: unify deprecation handling with single .new migration file
Consolidate all deprecation handling into deprecation.rs:
- Add [commit-generation] → [commit.generation] section migration
- Merge deprecated `args` field into `command` string
- Generate single .new file with all migrations (template vars + sections)
- Skip migration if new section already exists (don't overwrite)
- Skip warning for empty deprecated sections
- Use shell_escape for proper quoting when merging args
- Rename hint from deprecated-project-config to deprecated-config
Remove separate warn_deprecated_commit_generation() from user.rs.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: harden commit-generation migration against edge cases
Fixes found during adversarial testing:
1. Args data loss prevention: merge_args_into_command() now validates
preconditions (args is array, command is string) BEFORE removing
the args field. Previously, table.remove("args") happened
unconditionally, losing data if command was missing or non-string.
2. Malformed generation detection: When checking if new [commit.generation]
exists, now verify it's actually a table (is_table || is_inline_table).
A malformed value like `generation = "string"` no longer suppresses
deprecation warnings for the old section.
3. Inline table support: Both detection and migration now handle inline
table format (e.g., `commit-generation = { command = "..." }`).
Detection uses as_inline_table() in addition to as_table().
Migration converts InlineTable to Table via into_table().
Added comprehensive tests for all edge cases.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add coverage for project-level inline table migration
Add tests for:
- Project-level inline table migration
- Preserving existing [commit] fields during migration
- Empty inline table detection (should not flag as deprecated)
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add integration test for commit-generation deprecation warning
Add test that exercises the full deprecation path through check_and_migrate()
for commit-generation section rename and args merge. This improves coverage
on the warning output and migration file generation paths.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add integration test for project-level commit-generation deprecation
Add test that exercises the project_keys iteration path in check_and_migrate()
for project-level commit-generation deprecation warnings. This covers the
warning message format that includes project identifiers.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add edge case tests for merge_args_into_command
Cover the early-return paths in merge_args_into_command():
- Args without command: args preserved (no command to merge into)
- Non-string command: args preserved (can't merge into non-string)
- Command-only: clean migration without args field
These tests exercise the !can_merge validation path.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: cover malformed config fallback branches in migration
Add tests for the `_ => None` fallback branches that handle unusual
cases where commit-generation is neither a table nor inline table
(e.g., a string value like `commit-generation = "not a table"`).
These tests exercise lines 264 and 305 in deprecation.rs.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add coverage for edge cases in deprecation migration
Add unit tests for:
- Empty command with args: args become the command when command=""
- Invalid TOML parsing: returns content unchanged
- Deduplication path: second call with same path hits early return
These tests cover previously uncovered code paths in deprecation.rs.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add unit tests for llm helper functions
Add tests for format_reproduction_command and is_lock_file to improve
code coverage.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add unit tests for config merge logic
Add tests for:
- CommitConfig merge when only base/override has generation
- CommitConfig merge when both have generation
- CommitGenerationConfig merge for squash_template fields
These cover previously uncovered branches in the Merge implementations.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add validation tests for new commit.generation format
Add tests for validation error paths in the new [commit.generation]
config format (both top-level and per-project).
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add save_to() tests for commit.generation serialization
Cover the "create from scratch" branch in save_to() which serializes
commit.generation and deprecated commit-generation sections to new files.
Previously only the "update existing file" branch was tested.
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: fix "Claude CLI" to "Claude Code"
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: deduplicate LLM setup from config page
Remove Claude Code/llm setup examples from config docs since they
duplicate llm-commits.md. Config page now links to llm-commits.md
for setup and keeps only the custom prompt templates section.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: trigger deprecation warnings in `wt config show`
Previously `config show` read files directly without calling the config
loaders, so deprecation warnings weren't shown. Now we call
UserConfig::load() and repo.load_project_config() to trigger warnings
while still displaying invalid configs (the deprecation check runs on
raw content before parsing).
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: move aichat into Setup section with other options
Move aichat example from "Alternative tools" into the Setup section as
"Option 3: aichat" alongside Claude CLI and llm. Add "Custom scripts"
subsection for the generic example. Remove the now-redundant
"Alternative tools" section.
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: reframe LLM setup as examples, not numbered options
Change from "Option 1/2/3" to just showing examples of tools that work.
Lead with the concept: any command that reads stdin and outputs a commit
message. Simplify Claude Code example and condense install instructions.
Co-Authored-By: Claude <noreply@anthropic.com>
* Simplify LLM commit generation setup documentation
Remove redundant setup instructions and tool-specific examples from config templates and documentation. Consolidate guidance to reference the main LLM commits docs page for setup details.
* Skip deprecated section key in unknown fields warning
Skip the "commit-generation" key when warning about unknown fields, since
it's already handled by the deprecated sections warning and this prevents
duplicate warnings in config output.
* Extract DEPRECATED_SECTION_KEYS constant for reuse
Instead of hardcoding "commit-generation" in the skip check, define a
constant that documents which section keys are deprecated. This makes
it easier to add future deprecated sections without forgetting to
update the skip logic.
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove unused has_args field from CommitGenerationDeprecations
The has_args field was tracked but never used in production code — the
migration logic runs unconditionally and handles both cases (with or
without args). This simplifies the struct and removes a redundant test.
Co-Authored-By: Claude <noreply@anthropic.com>
* Move deprecated section filtering to callers of warn_unknown_fields
Instead of having warn_unknown_fields know about deprecated sections
and skip them internally, make the constant public and have callers
filter before calling. This is cleaner because:
1. warn_unknown_fields doesn't need to know about the deprecation system
2. Callers already interact with deprecation, so filtering there is natural
3. The coupling is explicit rather than hidden inside the function
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: use Unix shell escaping for migration hint command
The `mv` command in the migration hint is a Unix command, so use
`shell_escape::unix::escape` instead of the platform-specific `escape`
to get consistent output on all platforms.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: normalize path separators before shell escaping
Convert backslashes to forward slashes before shell escaping so the
migration hint command is consistent across platforms. Forward slashes
work in Git Bash on Windows.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: remove shell escaping from migration hint paths
Shell escaping was producing different output on Windows vs Unix even
with unix::escape, likely due to some invisible path characteristic.
Since config paths rarely contain special characters, just output the
paths directly with forward slashes.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* docs: improve subcommand definitions and subdefinitions
Refine help text for step and config subcommands:
- commit: consolidate definition, drop redundant subdefinition
- squash: restore "since branching" phrasing, simplify subdefinition
- push: add after_long_help with examples and implementation note
- rebase: add after_long_help with examples
- copy-ignored: shorten subdefinition to focus on benefit
- for-each: add concise subdefinition
- default-branch: clarify as "detection and override"
- statusline: remove subdefinition (was redundant with definition)
Co-Authored-By: Claude <noreply@anthropic.com>
* test: update help snapshots
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* docs: improve ci-status documentation clarity
Rewrites the terse 4-line "How it works" section into clear prose
explaining prerequisites, behavior, and caching.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: update ci-status help snapshot
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Demo HTML comments like `<!-- demo: file.gif -->` had blank lines on both
sides in the source. When the comment was stripped for terminal display,
both blanks remained, creating a double blank line.
Fix by removing the trailing blank after demo comments in cli/mod.rs.
Add a check in snapshot_help() to catch this pattern in all help tests.
Co-authored-by: Claude <noreply@anthropic.com>
Subcommand sections in generated docs (via `--help-page`) were missing
their definition — they only showed `after_long_help` content.
Extract `combine_command_docs()` to share the about + subtitle +
after_long_help assembly logic between `handle_help_page()` (top-level
commands) and `format_subcommand_section()` (subcommands).
Before:
## wt step copy-ignored
Git worktrees share the repository but not untracked files...
After:
## wt step copy-ignored
Copy gitignored files to another worktree. By default copies all...
Git worktrees share the repository but not untracked files...
Co-authored-by: Claude <noreply@anthropic.com>
- Change subdefinition from "For finished feature branches. Removes the
current worktree by default." to "Defaults to the current worktree."
- Add Hooks section documenting pre-remove and post-remove hooks
Co-authored-by: Claude <noreply@anthropic.com>
* Add post-remove hook type
* Add tests for wt hook show filter by hook type
Cover lines 430-432 in hook_commands.rs for post-merge, pre-remove,
and post-remove hook type parsing in handle_hook_show().
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix post-remove hook compilation and improve pre-remove example
- Fix compilation error: replace user_hook!(post_remove) with
ctx.config.hooks.post_remove.as_ref() to match other hook types
- Replace pre-remove "git stash" example with more practical
"archive test results" example that demonstrates pre-remove's
key feature: access to worktree files before deletion
- Update documentation to clarify pre-remove runs "with access
to worktree files"
Co-authored-by: Maximilian Roos <max-sixty@users.noreply.github.com>
* Trigger CI rebuild
* Add tests for post-remove hook error paths
- Fix merge conflict: replace removed user_hook! macro with direct access
- Add test for invalid template syntax in post-remove hook
- Add test for name filter that doesn't match any hook
Remaining uncovered lines are defensive code for race conditions:
- worktree/hooks.rs:117 - error during wt remove (config validated at startup)
- handlers.rs:556 - config load failure between command start and hook execution
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: post-remove template vars reference removed worktree
Template variables ({{ branch }}, {{ worktree_path }}, {{ worktree_name }})
now correctly reference the removed worktree, not the worktree where
commands execute from. This allows cleanup scripts to identify resources
(containers, servers, etc.) associated with the removed worktree.
Changes:
- spawn_post_remove_commands now accepts removed_worktree_path parameter
- Extra vars override built-in template variables with removed worktree info
- Updated documentation to clarify this behavior
- Added test verifying template vars reference the removed worktree
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: simplify post-remove template variable description
Remove explicit list of variable names; just say "all template variables
reference the removed worktree" which is clearer and less verbose.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add post-remove hook test during wt merge
The main production use case for post-remove hooks is during `wt merge`,
which removes the worktree after merging. This test verifies that
post-remove hooks run correctly in this flow.
Found via adversarial testing of the post-remove hook implementation.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: capture commit before removal for post-remove hooks
All template variables must reference the removed worktree, not the
execution context. The commit SHA was previously computed from the main
worktree (where hooks execute from), but should reflect the removed
worktree's state.
Changes:
- Add `removed_commit` field to RemoveResult::RemovedWorktree
- Capture commit SHA before removal in prepare_worktree_removal and merge
- Pass commit through to spawn_post_remove_commands
- Add commit and short_commit to extra_vars for post-remove hooks
- Update test to verify commit template variable references removed worktree
This prevents a subtle bug where {{ commit }} would unexpectedly contain
main's HEAD instead of the feature branch's HEAD.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: use slash paths for Windows test compatibility
On Windows, hooks run in Git Bash which converts paths to MSYS2 format
(/c/Users/... instead of C:\Users\...). Use to_slash_lossy() for the
expected path comparison so the test passes on Windows.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Maximilian Roos <max-sixty@users.noreply.github.com>
* feat: add worktree-path support to per-project user config
Allow users to specify different worktree path templates for different
projects in their user config, enabling portable dotfiles across
machines with different project structures.
Config format:
```toml
[projects."github.com/user/repo"]
worktree-path = ".worktrees/{{ branch | sanitize }}"
approved-commands = ["npm ci"]
```
Per-project worktree-path takes precedence over global, which falls
back to the default template.
Closes#596
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: add per-project config for commit-generation, list, commit, and merge
Extend the per-project user config to support overriding more settings:
- [projects."...".commit-generation] - LLM model, args, template
- [projects."...".list] - branches, remotes, full defaults
- [projects."...".commit] - stage mode
- [projects."...".merge] - squash, commit, rebase, remove, verify
Config precedence: CLI arg > project config > global config > default
Implementation:
- Add Merge trait for field-wise config merging (other takes precedence)
- Add effective_* methods to WorktrunkConfig for merged config access
- Add helper methods on CommandEnv/CommandContext for easy access
- Update all commands to use effective configs instead of direct access
- Fix approval clearing to preserve other per-project settings
The approval clearing fix prevents data loss: previously clearing approvals
would wipe all per-project settings (worktree-path, commit-generation, etc).
Now it only clears approved-commands and removes project entries only if
completely empty.
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: extract merge_optional helper to reduce duplication
DRY improvement: the effective_list, effective_commit, and effective_merge
methods all had identical 4-way match logic. Extract to a generic helper
function that handles the merge pattern.
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: simplify per-project config documentation
- Clarify that per-project settings contain approvals + optional overrides
- Put approved-commands first (primary use case)
- Use TOML dotted keys for compact examples (list.full, merge.squash)
- Remove verbose examples that repeated the section header
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: drop `effective_` prefix from config accessor methods
The `project: Option<&str>` parameter already indicates merging behavior.
Renamed methods:
- WorktrunkConfig: commit_generation(), list(), commit(), merge()
- CommandEnv/CommandContext: commit_generation(), commit(), merge()
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: escape brackets in doc comments to avoid rustdoc link errors
Rustdoc interprets `[text]` as intra-doc links. Use backticks to make
them code spans instead.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: update help snapshots after merge
Updated config help snapshots to reflect per-project config documentation.
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add validation tests for config edge cases
Add tests for config validation:
- Empty worktree-path (global and per-project)
- Absolute worktree-path (global and per-project)
- Mutual exclusivity of template/template-file options
Extracted validation into a separate `validate()` method to avoid
code duplication between `load()` and test helper.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: use platform-appropriate absolute paths in validation tests
On Windows, `/absolute/path` is not considered absolute - Windows uses
`C:\path` style. Use cfg!(windows) to conditionally set the test path.
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: fix project_id() doc comments to describe path fallback
The doc comments incorrectly stated that project_id() returns None when
there's no remote URL. The actual implementation falls back to the
canonical repository path, only returning None for non-UTF-8 paths.
Co-Authored-By: Claude <noreply@anthropic.com>
* feat: mark per-project setting overrides as experimental
- Add "(Experimental)" to per-project settings section heading
- Clarify that setting overrides (worktree-path, list, commit, merge) are
new while approved-commands is stable
- Replace manual PartialEq impl with derive for CommitGenerationConfig
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: minor code simplifications
- Replace .to_string().as_str() with &.to_string()
- Replace .is_some() + .unwrap() with tuple pattern match
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: fix if-let formatting
Move opening brace to same line as if-let condition to match code style.
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat: add GitLab MR checkout with `mr:<number>` syntax
Add `wt switch mr:101` to checkout the branch for GitLab merge request !101,
mirroring the existing GitHub PR checkout (`pr:<number>`) functionality.
Same-project MRs switch directly to the source branch. Fork MRs fetch
`refs/merge-requests/N/head` and configure `pushRemote` to the fork URL,
enabling `git push` to update the MR.
Requires `glab` CLI to be installed and authenticated.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: address code review feedback for GitLab MR checkout
- Use find_remote_by_url for fork MR remote selection instead of primary_remote()
- Use ErrorKind::NotFound for glab detection (cross-platform)
- Add shell escaping and -- to branch rename hints
- Consolidate setup_fork_pr_branch and setup_fork_mr_branch into setup_fork_branch
- Add fork MR integration test
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add coverage for branch_tracks_mr paths
- Remove specialized rate limit/network error handlers (fall through to
general error with full stderr)
- Add test for fork MR when branch already tracks the correct MR
- Add test for fork MR when branch tracks a different MR
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add more MR test coverage
- Add test_switch_mr_fork_existing_no_tracking (branch exists, no tracking)
- Add test_switch_mr_unknown_error (general glab error fallback)
These mirror existing GitHub PR tests for better coverage parity.
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor: unify PR/MR checkout code with RefType discriminant
- Create shared branch_tracks_ref() function for checking if a branch
tracks a specific remote ref (PR or MR)
- Add RefType enum with helper methods (symbol, name, syntax) to
encapsulate platform-specific display logic
- Unify error variants: RefCreateConflict, RefBaseConflict,
BranchTracksDifferentRef, CliApiError (replacing separate PR/MR versions)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: prevent git option injection with branch names starting with -
Add -- separator before branch names in git commands to prevent
external branch names (from GitHub/GitLab APIs) that start with -
from being interpreted as git flags.
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: add TODOs for known limitations in PR/MR checkout
Document pre-existing issues identified during code review:
- GitRemoteUrl doesn't handle GitLab nested group URLs
- glab stderr parsing is brittle across versions/locales
- branch_tracks_ref only checks merge config, not remote
- Fork MR remote fallback is silent and can pick wrong remote
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat: reduce background hook output verbosity (#690)
Background hooks (post-start, post-switch) now show a single-line summary
by default instead of verbose per-hook output with command details:
◎ Running post-start hooks @ repo.feature: user:bg, project
Use `-v` to see detailed per-hook output with expanded commands.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: update comment to match actual output format
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add coverage for verbose background hook output
Add test_post_start_verbose_shows_per_hook_output to verify that -v shows
detailed per-hook output with command in gutter format.
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: document -v flag for background hook verbosity
Adds a note in the hook types section explaining that background hooks
show a single-line summary by default, with -v for expanded details.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Reorders documentation to recommend post-start (background) as the default
choice, with post-create (blocking) for when something must complete before
post-start hooks or --execute run.
Changes:
- Hook types table: post-start listed first
- Section order: ### post-start before ### post-create
- Comparison section: renamed to "post-start vs post-create"
- post-start example: now includes copy + server (background tasks)
- post-create example: now shows install + env (things post-start depends on)
- wt step copy-ignored: Setup section uses post-start
Co-authored-by: Claude <noreply@anthropic.com>
* chore: update brew install to use core tap
Signed-off-by: Rui Chen <rui@chenrui.dev>
* docs: restore shell install step in brew instructions
The previous commit removed `&& wt config shell install` from the
Homebrew install command. This restores it so users get shell
integration set up automatically.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Signed-off-by: Rui Chen <rui@chenrui.dev>
Co-authored-by: Maximilian Roos <m@maxroos.com>
Co-authored-by: Claude <noreply@anthropic.com>
* fix: unset unsafe upstream when creating branch from remote base (#713)
When running `wt switch --create feature --base=origin/main`, git
automatically sets up the new branch to track origin/main. This is
dangerous because `git push` without arguments would push to main
instead of the feature branch.
The fix unsets the upstream tracking after creating a branch from a
remote tracking base (like origin/main), preventing accidental pushes
to the base branch.
Changes:
- Add `Branch::unset_upstream()` method to remove upstream tracking
- Add `Repository::is_remote_tracking_branch()` to detect remote refs
- Modify `execute_switch` to unset upstream when base is a remote branch
- Add test to verify no upstream is set after creating from remote base
Fixes#713
* docs: clarify upstream tracking behavior for --create vs DWIM
Explain that branches created with --create have no upstream tracking
(to prevent accidental pushes to wrong branch), while DWIM switches
preserve standard git tracking behavior.
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: update help snapshot for upstream tracking docs
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Merge origin/main into 12
Resolved conflict in src/output/mod.rs:
- Keep library-based verbosity (styling/mod.rs) for library code access
- Add API aliases (set_verbose_level, verbose_level, is_verbose) for compatibility
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: remove unused verbosity alias functions
After the merge from main, some verbosity API alias functions
(set_verbose_level, verbose_level, is_verbose) were left unused.
The codebase uses set_verbosity() through output:: and accesses
verbosity() directly from styling in library code.
Co-Authored-By: Claude <noreply@anthropic.com>
* Refactor template expansion verbosity caching
Cache verbosity level in expand_template() to avoid multiple function
calls and remove redundant hint message for template errors. Update
snapshots to reflect removal of hint message.
* test: update snapshots after merge
Update snapshots for:
- switch_execute_template_base_without_create: template error with SemiStrict
- switch_execute_verbose_template: verbose output format
- switch_execute_verbose_multiline_template: verbose output format
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Add Arch Linux install via AUR
* Alias PKGBUILD source to include version
* Add Maintained at line
* Add depends to PKGBUILD
* docs: move Arch Linux install below Windows
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Evan Sosenko <razorx@evansosenko.com>
Co-authored-by: Claude <noreply@anthropic.com>
* feat: add completion cmd for completion integration
Signed-off-by: Rui Chen <rui@chenrui.dev>
* refactor: move completions command to `wt config shell completions`
- Move from top-level `wt completions` to `wt config shell completions`
- Remove duplicate CompletionShell enum, use existing Shell enum
- Simplify help text to direct users to `wt config shell install`
- Remove Homebrew note from FAQ (no duplication issues found)
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: add TODO about dynamic completions in fish
Add documentation note explaining why static completions are used
instead of dynamic completions, and reference the fish example as a
potential improvement for future implementation.
* chore: sync generated docs
Co-Authored-By: Claude <noreply@anthropic.com>
* test: add coverage for static completions command
Tests `wt config shell completions <shell>` for all supported shells
(bash, fish, zsh, powershell) to satisfy codecov/patch coverage.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Signed-off-by: Rui Chen <rui@chenrui.dev>
Co-authored-by: Maximilian Roos <m@maxroos.com>
Co-authored-by: Claude <noreply@anthropic.com>
* fix: use headRefName directly for fork PR branches
Fork PR branches were named `<owner>/<branch>` to avoid collisions,
but this broke `git push` because the local branch name didn't match
the remote branch name on the fork. With `push.default = current`,
git tried to push to a non-existent remote branch.
Now fork PRs use `headRefName` directly (e.g., `feature-fix` instead
of `contributor/feature-fix`). This ensures `git push` works correctly.
The collision case (two forks with same branch name) is handled by
the existing `branch_tracks_pr()` check which errors if a branch
exists but tracks a different PR.
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: update fork PR documentation and error messages
Update documentation and error messages to reflect new fork PR branch
naming (using headRefName directly instead of owner/branch prefix):
- CLI help: explain that git push works normally with fork PRs
- Error message: clearer wording when local branch conflicts with PR
- Error hint: suggest rename (-old suffix) instead of delete
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Change verbosity threshold from -v to -vv for enabling debug logging and
diagnostic file generation. This frees up -v for other purposes.
Behavior change:
- -v: no effect (reserved for future use)
- -vv: debug logging + verbose.log + diagnostic.md (unchanged)
Co-authored-by: Claude <noreply@anthropic.com>
- Add missing `∅` (orphan) symbol to status symbols table
- Add `"orphan"` to main_state JSON values list
- Add `"no_worktree"` to worktree.state JSON field docs
- Add `base` and `base_worktree_path` to TEMPLATE_VARS for --var validation
- Add Unix-only note for wt select (de-emphasized, at bottom)
Co-authored-by: Claude <noreply@anthropic.com>
Move overflow-x from figure.demo to the picture element so the
figcaption stays in place while the image scrolls horizontally.
Co-authored-by: Claude <noreply@anthropic.com>
* Simplify Windows support FAQ
Remove feature table and consolidate Windows support info into concise statements about Git for Windows requirement and wt select unavailability.
* Reorder FAQ by frequency/importance
Move most-asked questions to the top:
1. Comparisons (evaluation)
2. Shell setup issues (common friction)
3. Files created / can delete / commands executed (trust)
4. Windows support
5. Default branch detection
6. C compilation errors (rare)
7. Contributing sections
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix FAQ accuracy: mention gh/glab for CI status
- CI cache is created when either gh or glab CLI is installed
- Clarify that worktrunk also runs git/gh/glab internally
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat(switch): add pr:<number> syntax for switching to GitHub PRs
Adds support for `wt switch pr:123` which resolves a GitHub PR number
to its branch and switches to it. For same-repo PRs, delegates to
normal switch flow. For fork PRs, fetches from refs/pull/N/head and
configures pushRemote to the fork URL.
Implementation:
- Add pr_ref module with fetch_pr_info(), local_branch_name(), fork_remote_url()
- Handle same-repo PRs by delegating to plan_switch_inner with resolved branch
- Handle fork PRs with CreateFromForkPr plan variant
- Add compute_clobber_backup() helper to deduplicate clobber logic
- Show unified "Fetching PR #N from origin..." progress for all network ops
- Warn when --base is used with pr: syntax (ignored since PR determines branch)
- Check for local branch collisions before creating fork PR branch
Closes#657
Co-Authored-By: Claude <noreply@anthropic.com>
* refactor(switch): unify PR and regular switch paths
Consolidates the patchy pr: implementation into a cleaner design:
- Add CreationMethod enum (Regular vs ForkPr) instead of separate
SwitchPlan variants
- Extract resolve_switch_target() for early --create/--base validation
- Extract check_existing_worktree() and validate_worktree_creation()
as shared validation helpers
- Remove plan_switch_from_pr() and plan_switch_inner() in favor of
unified plan_switch() with clear phases
- Add PrBaseConflict error (--base now fails with pr: instead of warning)
- Extract compute_clobber_backup() helper
The new structure:
plan_switch()
→ resolve_switch_target() (pr: handling, flag validation)
→ check_existing_worktree() (shared)
→ validate_worktree_creation() (shared)
→ SwitchPlan::Create { method: CreationMethod }
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(switch): add cleanup and PR tracking for fork PRs
Addresses several issues found through adversarial testing:
1. **Cleanup on partial failures**: If branch creation succeeds but
worktree creation fails, the orphaned branch is now deleted to
prevent blocking future attempts.
2. **PR tracking verification**: Before erroring on existing branches,
we now check if the branch is tracking the correct PR. If it tracks
the same PR, we reuse it. If it tracks a different PR or nothing,
we error with a helpful message suggesting `git branch -D`.
3. **Improved gh error handling**:
- Case-insensitive error matching for reliability across gh versions
- Detection of gh not installed
- Rate limiting detection
- Network error detection
- Better JSON parsing error messages
- Validation of required fields
New tests cover: --base conflict with pr:, existing branch tracking
same PR (reuse), existing branch tracking different PR (error),
existing branch with no tracking (error).
Co-Authored-By: Claude <noreply@anthropic.com>
* test(switch): add test for path occupied by missing worktree
Covers the error path where a target worktree path is registered
to an existing worktree whose directory was deleted. This tests
the WorktreeMissing error in validate_worktree_creation().
Co-Authored-By: Claude <noreply@anthropic.com>
* docs(switch): mark pr:<number> syntax as experimental
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* docs: add Caddy subdomain routing pattern
Add "Subdomain routing with Caddy" section to Tips & Patterns showing how
to get clean URLs like `feature-auth.lvh.me` without port numbers.
The pattern uses Caddy's admin API for dynamic route registration:
- Starts Caddy if not running (idempotent)
- Creates server structure on first run (self-bootstrapping)
- Registers routes via API (no config files needed)
Key detail: requires `automatic_https: disable` since Caddy auto-enables
HTTPS for public domains like lvh.me.
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: add Caddy subdomain routing pattern
Add pattern for clean URLs like `http://feature-auth.myproject.lvh.me`
using Caddy reverse proxy with dynamic route registration via admin API.
- Routes namespaced by repo to avoid collisions across projects
- pre-remove hook cleans up routes when worktrees deleted
- Idempotent startup: checks Caddy running before starting
Co-Authored-By: Claude <noreply@anthropic.com>
* docs: refine Caddy subdomain routing explanation
Reorder "How it works" to follow chronological flow:
1. wt switch starts dev server on deterministic port
2. Hook registers Caddy route using same port
3. lvh.me DNS explanation
4. Request flow
Co-Authored-By: Claude <noreply@anthropic.com>
* chore: sync skill reference file
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Add expandable Windows section to Install with:
- Winget as recommended install (ships git-wt by default)
- Alternative: disable Windows Terminal's wt alias
Remove redundant FAQ entry about the wt conflict since Install
now covers it. The "Does Worktrunk work on Windows?" FAQ remains
for feature support details.
Closes#133
Co-authored-by: Claude <noreply@anthropic.com>
Add a new section to Tips & Patterns showing how to create a dedicated
tmux session for each worktree with a multi-pane layout (shell, backend,
frontend, Claude).
Key patterns:
- post-create hook creates session named after sanitized branch
- pre-remove hook kills session to stop all services
- --execute flag for immediate attach on worktree creation
Co-authored-by: Claude <noreply@anthropic.com>
Replace angle-bracket URLs (<https://...>) with proper markdown links
that render nicely on web while showing descriptive text in CLI help.
- src/cli/mod.rs: Use Zola @/ syntax for internal links
- dev/config.example.toml: Remove angle brackets (plain URLs for TOML)
- .claude-plugin/CLAUDE.md: Use GitHub shorthand for issue link
CLI now shows "LLM commits docs" and "`wt hook` docs" instead of raw URLs.
Web docs render as clickable links with descriptive text.
Co-authored-by: Claude <noreply@anthropic.com>
Move "What gets copied" section before example to improve clarity on
behavior before showing configuration. Simplify .worktreeinclude example
by removing .cache/ pattern and updating explanatory text for consistency
across all documentation files.
Remove redundant parenthetical and reference to detailed documentation,
consolidating information into a single clearer sentence across docs
and CLI help text.