* Limit concurrent command execution to prevent resource exhaustion
When running `wt list --progressive` on repos with many branches, we
spawn 10+ tasks per branch, each running git commands. With 12+ branches
this means 120+ concurrent git processes, which can hit OS limits
(file descriptors, process limits) causing commands to fail.
Add a semaphore limiting concurrent external commands to 32 (default).
Uses RAII guard pattern to ensure release even on panic. Override with
WT_MAX_CONCURRENT_COMMANDS env var if needed.
Move Semaphore to shared `sync` module, used by both shell_exec and git.
Root cause: "Failed to execute: git show..." errors when too many
git processes spawned simultaneously, resulting in timestamp=0
being displayed as "55y" age.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Standardize environment variables to WORKTRUNK_ prefix
- Rename WT_MAX_CONCURRENT_COMMANDS → WORKTRUNK_MAX_CONCURRENT_COMMANDS
- Rename WT_SKELETON_ONLY → WORKTRUNK_SKELETON_ONLY (benchmarks)
- Remove orphaned env vars (WT_SEQUENTIAL, WT_PROGRESSIVE)
- Remove dead timing.rs module (130 lines, never wired up)
- Rename docs section "Special variables" → "Other environment variables"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Remove `expected` and `current` fields from `SwitchBranchInfo` and simplify
to single `branch` field. Remove branch mismatch detection logic and related
tests. Update shell integration messages to use "but — " pattern for
limitations. Clarify path mismatch warning message. Update path mismatch
symbol documentation from "Path doesn't match template" to "Worktree path
doesn't match branch name".
Changes from separate namespaces to unified format:
- CI cache: worktrunk.cache.<branch>.ci-status → worktrunk.state.<branch>.ci-status
- Markers: worktrunk.marker.<escaped> → worktrunk.state.<branch>.marker
Benefits:
- Numeric branch names (10704) now work - git subsections have no naming restrictions
- No escaping needed for slashes, underscores, hyphens
- Unified namespace for all branch-keyed state
- Removed ~260 lines of escape/unescape code and tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Consolidate all development scripts in dev/:
- fetch-assets: downloads demo GIFs for local docs development
- publish-assets: publishes demo GIFs to worktrunk-assets repo
Update references in .config/wt.toml and docs/CLAUDE.md.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Shell integration allows commands to change directories. Updated documentation
to separate this explanation from the installation command. Refactored CI
status detection to use non-interactive mode for CLI tools (gh, glab) by
disabling TTY features and stdin. Renamed disable_color_output to
configure_non_interactive and set stdin to /dev/null across all tool
invocations. Simplified shell availability checks in tests with dedicated
helper function.
Clarify which git ref is used for different status checks:
- default_branch (local main): Used for informational stats like ahead/behind
counts, branch diff, and conflict detection (✗ symbol)
- target (effective target): Used for integration checks that determine if a
branch is safe to delete. May be origin/main when it's strictly ahead,
catching branches merged remotely before pulling.
Status symbol mapping:
- _ (Same commit): Uses ahead==0 && behind==0 from counts (vs default_branch)
- ⊂ (Integrated): All 5 checks use target
- ✗ (Would conflict): Uses default_branch for consistency with other Main symbols
Documentation updated to list all 5 integration conditions (added Ancestor
between Same commit and No added changes) and clarify which compare against
main vs target.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
* Prevent Worktrunk column from wrapping in README table
Add white-space: nowrap to the Worktrunk column header and cells
to keep commands on a single line.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Use <pre> tags for Worktrunk column to prevent wrapping
GitHub's table rendering gives priority to <pre> blocks for width.
Using <pre> in both columns gives them equal treatment.
Updated both docs/content/worktrunk.md (source) and README.md (generated).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Path column now gets the empty penalty (+10 priority) when all worktrees
have paths matching the naming template (path_mismatch=false). This makes
Path lower priority than other columns when it's redundant with branch name.
Changes:
- Add `path` flag to ColumnDataFlags, computed from path_mismatch
- Change Message allocation to use minimum width initially, allowing empty
columns to be allocated before Message expands into remaining space
- Count ALL hidden columns (not just non-empty) in the summary message
- Update module docs to document progressive mode limitation
The result: Path is hidden at narrow widths but shows at wide terminals
(~125+ columns) when space allows. Summary always reports hidden column
count, regardless of whether they contain data.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Change from imperative "switch to it" to descriptive "Switches to..."
for consistency with other help text.
Co-authored-by: Claude <noreply@anthropic.com>
Change "from --base" to "from the --base branch" to make it clearer
that we're referring to the branch value, not the flag itself.
Co-authored-by: Claude <noreply@anthropic.com>
Change dirty worktree detection from checking only tracked file changes
to using the status_symbols.working_tree field which includes both
tracked and untracked files. This ensures the summary correctly reports
all worktrees with any modifications.
Consider untracked files when determining if a worktree is safe to delete.
Untracked files would be lost on worktree removal, so they should block the
integration state. Pass untracked status to check_integration_state and update
integration detection to require both tracked and untracked files to be clean.
Update snapshots to reflect the visual change from underscore to en-dash for
worktrees with untracked files only (no tracked changes).
When resolving a branch argument in `wt switch` and `wt remove`, now
checks if the branch has a worktree anywhere before checking the
expected path. This is more intuitive - if you type `wt switch foo`,
you get branch foo's worktree, not whatever happens to be at the
expected path.
- Rename resolve_worktree_path_first → resolve_worktree_arg
- Reorder handle_switch to check branch first
- Remove unused WorktreePathMismatch error type
- Simplify argument resolution documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
When passed, merge fails early with a clear error if the branch is not
already rebased onto target, rather than auto-rebasing. This provides
explicit control for workflows that handle rebasing separately.
Also fixes a bug where --no-commit incorrectly skipped rebasing. Rebasing
now happens independently of the commit flag (as it should).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Update documentation and help text to better explain the switch command's behavior when creating worktrees. Restructure the "Creating worktrees" section to clarify that worktree creation happens when the target branch has no worktree, separate from the `--create` flag which specifically creates a new branch. Simplify the introductory description and update examples to be more concise and practical.
Make it explicit that the vhs-keystrokes binary must be built before
regenerating demos, and add a check command to verify it exists.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add documentation for building the custom VHS fork required by the
wt-select demo. Update .gitignore to exclude the locally-built
vhs-keystrokes binary.
Rewrote the intro section to better explain the command's behavior:
- "Switches to a worktree, creating one if needed"
- With --create, explains it creates a new branch based off --base
Previously the help text implied you could only switch to existing
worktrees without --create, but actually a worktree is created
automatically for existing branches that don't have one yet.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
* feat(docs): Add dark theme support for demo GIFs
Demo GIFs now automatically switch between light and dark variants based on
system color scheme preference using the <picture> element with media queries.
Changes:
- Add themes.py with light/dark VHS theme definitions matching doc site CSS
- Parameterize demo.tape files to accept theme variable
- Update build scripts to generate both light and dark GIF variants
- Update markdown to use <picture> element for automatic theme switching
- Update publish-assets to include dark variants
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix CI: generate picture element from demo placeholder
The <picture> element for light/dark theme switching should be generated
by expand_demo_placeholders() in main.rs, not manually edited in the
markdown. This ensures the AUTO-GENERATED region stays in sync.
🤖 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 examples to use shorter branch names and refactor table
styling to properly handle horizontal scrolling within the content area. Tables
now use display: block with overflow-x: auto instead of display: table with
max-content width, preventing layout overflow while maintaining border-radius
appearance.
- 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.
Introduces a new status symbol to differentiate between:
- `_` (Empty): Same commit as main with clean working tree - safe to delete
- `–` (SameCommit): Same commit as main with uncommitted changes - NOT safe
Previously, branches at the same commit as main with dirty working trees
showed no main-state symbol. Now they show `–` (en-dash) to indicate
work in progress. Only `Empty` branches are dimmed and considered
"potentially removable" since `SameCommit` branches have uncommitted
work that would be lost.
Refactors `determine_integration_state()` to `check_integration_state()`
which only returns true integration states (Empty, Integrated). The
`SameCommit` state is now detected separately in the caller since it's
not an integration state.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
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>
Replace hardcoded shadow values with CSS custom properties for consistency
across light and dark modes. Update image dimensions in documentation.
Consolidate code block and terminal styles using SCSS mixins. Improve
table styling with proper border-collapse and overflow handling. Add print
styles for better document output. Expand demo placeholder parser to
support optional dimension attributes.
* Standardize CLI help text placement and improve summaries
- Add guidance to src/commands/CLAUDE.md for three-level help pattern:
- `about` (single line) for title
- `long_about` (1-2 sentences) for summary before options
- `after_long_help` for examples/details after options
- Improve StepCommand summaries:
- commit: mentions staging and LLM
- squash: mentions staging, combining commits, and LLM
- push: clarifies it's a fast-forward to target branch
- Improve HookCommand summaries:
- show: mentions user and project hooks
- post-create/post-start: highlight blocking vs background
- Remove redundant after_long_help (parent table covers it)
- Simplify statusline: remove implementation detail
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Update snapshots and docs for CLI help changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Change `IntegrationReason` descriptions to be more precise about the
relationship between branches. Replace vague phrases like "already in"
with specific descriptions:
- SameCommit: "same commit as" (instead of "already in")
- Ancestor: "ancestor of" (instead of "already in")
- NoAddedChanges: "no added changes" (instead of "no file changes")
- TreesMatch: "tree matches" (instead of "files match")
- MergeAddsNothing: "all changes in" (unchanged)
Update all test snapshots and documentation to reflect the new messaging.
Add documentation in the `description()` method explaining that some
descriptions include a `{target}` placeholder for the target branch name.
Update version from 0.2.0 to 0.1.22, adjust git-wt binary to be opt-in via
feature flag instead of always built, update dist configuration to enable
git-wt feature in release builds, and update documentation to reflect the
new installation method using --features flag.
Remove git-wt feature gate to build git-wt binary by default alongside wt.
Both binaries are now installed automatically, providing a workaround for
Windows Terminal's wt command conflict.
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>
* Add git-wt binary for Windows (wt conflicts with Windows Terminal)
- Add `git-wt` binary behind `--features git-wt` feature flag
- Add `--cmd` option to `config shell init/install` (defaults to argv[0])
- Shell templates now use `{{ cmd }}` for binary name throughout
- Fix `--source` flag to use correct binary with `cargo run --bin`
- Extract `add_standard_env_redactions()` for DRY snapshot settings
- Document Windows workaround in FAQ
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix rustdoc link in argv[0] doc comment
* Fix Windows binary name detection stripping .exe extension
Use `file_stem()` instead of `file_name()` to strip the `.exe` extension
on Windows. This fixes `test_configure_shell_already_exists` which was
failing because the config line detection compared `wt` (in file) with
`wt.exe` (from argv[0]).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Enable ~49 more Windows tests
Now that we've verified echo commands work through Git Bash on Windows,
enable all tests that use shell commands like 'echo ... > file.txt'.
Remaining 19 Windows-ignored tests have actual platform incompatibilities:
- chmod command (Unix only)
- File locking during worktree removal
- git status CRLF/LF differences
- /tmp paths
- cat command
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Enable 16 Windows tests that use simple echo commands
Selectively enable tests that use:
- Simple echo commands without path template variables
- Non-path template variables ({{ branch }}, {{ target }}, {{ default_branch }})
Tests using path template variables ({{ worktree }}, {{ main_worktree }},
{{ repo_root }}, {{ worktree_name }}) remain ignored due to shell quoting
differences when these paths are echoed on Windows via Git Bash.
Enabled tests by file:
- approval_ui.rs: 7 tests
- merge.rs: 3 tests
- switch.rs: 2 tests
- user_hooks.rs: 2 tests
- remove.rs: 1 test
- post_start_commands.rs: 1 test
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix Windows path quoting in shell templates
Convert Windows native paths (D:\...) to POSIX format (/d/...)
in hook context variables. This avoids shell escaping of `:` and `\`
characters that caused snapshot mismatches between Windows and Unix.
The root cause was that shell_escape::escape() uses unix escaping
when MSYSTEM is set (as it is in Git Bash), and Windows paths contain
characters not in the unix safe character set, causing them to be
wrapped in single quotes.
Changes:
- Add to_posix_path() helper for Git Bash compatibility
- Update build_hook_context() to use POSIX paths for worktree/repo_root
- Enable 15+ tests that were previously skipped due to path differences
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add POSIX path filters for Windows snapshot redaction
The to_posix_path() conversion in command_executor.rs converts Windows
paths like C:\Users\...\repo to POSIX format /c/Users/.../repo for Git
Bash compatibility. However, snapshot redaction patterns weren't catching
these POSIX-formatted paths.
Add:
- to_posix_path() helper in test common module
- POSIX path filters for repo and worktree paths
- Regex fallback pattern for POSIX-style Windows temp paths
This ensures template variables like ${worktree} and ${repo_root} are
properly redacted in snapshots regardless of path format.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Format: split long filter line
* Update user_hooks snapshots after rebase
* Use cygpath for Windows path conversion
Instead of hand-rolling POSIX path conversion, use cygpath from Git for
Windows which handles all edge cases (UNC paths, verbatim paths, etc.).
- Derive cygpath location from cached ShellConfig (no duplicate Git-finding)
- Fall back to pass-through if cygpath unavailable
- Remove duplicate to_posix_path implementations from command_executor and tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Test: enable for_each tests on Windows
Remove stale Windows skip attributes from for_each tests.
These tests run commands through Git Bash (via ShellConfig), so
echo and git commands should behave identically to Unix.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add .gitattributes to force LF line endings in test repos
The for_each tests were skipped on Windows because `git status`
showed files as modified due to CRLF conversion. Adding `.gitattributes`
with `* text=auto eol=lf` ensures consistent line endings across all
platforms.
Changes:
- Add .gitattributes to template-repo
- Update copy_fixture_template() to copy .gitattributes
- Regenerate template git objects with .gitattributes tracked
- Update snapshots (git warning removed, env vars normalized)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Update snapshots and documentation for CI help text changes to clarify that CI indicators link to either PR or pipeline pages, and that PRs/MRs are checked first before branch workflows/pipelines.
Replace generic `all` transitions with explicit property lists to improve
performance and maintainability. Specifies only the properties that actually
change on interaction (color, background, box-shadow, text-decoration).
- Add `insert_anchor_links = "heading"` to Zola markdown config for automatic heading anchors
- Style anchor links with hover effects: h2 underlines intensify, h3/h4 shift to accent color
- Add `scroll-margin-top` to content area to account for sticky header when scrolling to anchors
- Wrap homepage and page title headings with anchor links for deep linking
- Add new test fixtures: `repo_with_remote_and_feature`, `repo_with_alternate_primary`, `repo_with_multi_commit_feature`, and `add_feature()` shorthand
- Consolidate help tests from individual functions to parameterized rstest
- Update directives and merge/push tests to use new fixture helpers
- Update snapshot tests with corrected commit messages from new fixture usage
Refactor search container to use :focus-within for expanded state and
view-transition-name to freeze the search box during page navigation.
This prevents layout shifts caused by input shrinking when focus is lost
during the view transition. Update search.js to only clear suggestions
on modifier-click (new tab/window) to avoid jarring shrink during normal
navigation.
Update documentation page title and file references from "Why Worktrunk?" to
"Worktrunk" for simpler naming. Update all related paths in config, templates,
and tests accordingly. Add "For context," to intro sentence for clarity.
Replace `git init` with pre-initialized fixture template to save ~10ms per test.
The fixture at tests/fixtures/template-repo/ contains a minimal git repo with
one deterministic commit (hash 23e5a15, timestamp 2025-01-01T00:00:00Z).
Changes:
- TestRepo::new() now copies fixture instead of running git init
- TestRepo::empty() added for tests needing uninitialized repos
- Removed ~320 redundant `repo.commit("Initial commit")` calls from tests
- Reduced fixture from 32 files to 9 (removed sample hooks, logs, etc.)
- Fixed path canonicalization in TestRepo::empty() for Windows compatibility
- Added typos exception for commit hash substring 'ede'
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove references to the `--full` flag limitation for the `⊂` (content integrated) symbol and related merge simulation functionality. The WouldMergeAdd task is now always computed to properly detect squash-merged branches, with a TODO noting potential future performance optimization if needed.