## Summary
- Add bare repo `worktree-path` example (`{{ repo_path }}/../{{ branch |
sanitize }}`) to config docs alongside existing examples
- Update `repo_path` variable description to note bare repo behavior
- Expand "Bare repository layout" section in tips-patterns: explains why
bare repos suit worktree workflows and documents the `git clone --bare
<url> project/.git` setup
## Test plan
- [x] `cargo run -- hook pre-merge --yes` passes
- [x] Doc sync tests pass
(`test_command_pages_and_skill_files_are_in_sync`,
`test_config_source_generates_example_toml`)
- [x] Help snapshots updated and accepted
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
Phase 1 of the template variable redesign discussed in #1633. Adds
directional vars (`base`, `target`, `target_worktree_path`, `cwd`) to
all two-worktree hooks — non-breaking additions only, no existing
behavior changes.
## New variables
- **`cwd`** — execution directory, always exists on disk (all hooks).
Enables the Active model in Phase 2 where `worktree_path` becomes
identity rather than execution context.
- **`target_worktree_path`** — target worktree path, added alongside
existing `target` for merge hooks (pre-merge, post-merge) and remove
hooks (pre-remove, post-remove).
- **`base` / `base_worktree_path`** — source branch/worktree, added to
pre-switch hooks. For existing destinations, `target` /
`target_worktree_path` are also provided.
These follow the "Active" model where each two-worktree operation has a
base (source/origin) and target (destination) side:
- **Arriving ops** (switch, create): Active = destination. `base` =
where you came from.
- **Departing ops** (merge, remove): Active = source. `target` = where
it's going.
Mnemonic: *"Are you going there, or is it going away?"*
Phase 2 (separate PR) will change bare var semantics so `worktree_path`
consistently points to the Active worktree, with `cwd` as the
execution-context escape hatch.
Ref #1633
> _This was written by Claude Code on behalf of @max-sixty_
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Moves the rename-based staging directory from a visible sibling path
(`project.wt-removing-<timestamp>`) into `.git/wt/trash/`, hiding it
from the user's workspace
- Consolidates all worktrunk-managed `.git/wt-*` directories under a
single `.git/wt/` parent
- Adds `Repository::wt_dir()` accessor as the single root for all
worktrunk state
- Renames `wt-relocate-tmp` to `wt/relocate-staging` for consistency
with `wt/promote-staging`
- Falls back to legacy `git worktree remove` if the trash directory
can't be created
- The `.git/` directory is always on the same filesystem as worktrees,
so the instant rename guarantee is preserved
## Path migration
| Before | After |
|--------|-------|
| `.git/wt-logs/` | `.git/wt/logs/` |
| `.git/wt-cache/summaries/` | `.git/wt/cache/summaries/` |
| `.git/wt-cache/ci-status/` | `.git/wt/cache/ci-status/` |
| `.git/wt-promote-staging/` | `.git/wt/promote-staging/` |
| `.git/wt-relocate-tmp/` | `.git/wt/relocate-staging/` |
| (new) `.git/wt/trash/` | Staging for background removal |
## Context
Users reported confusion when seeing `.wt-removing-*` directories in
their workspace after `wt remove` (#1572). By staging in
`.git/wt/trash/` instead, the directory is completely hidden — even if
the background `rm -rf` is slow or gets interrupted.
The `.git/wt-*` sibling directories were also consolidated into
`.git/wt/` for tidiness per review feedback.
## Test plan
- [x] Unit tests for `generate_removing_path` and
`build_remove_command_staged` updated and passing
- [x] All 105 remove-related integration tests passing
- [x] `test_remove_background_path_gone_immediately` — verifies instant
removal still works
- [x] `test_remove_background_fallback_on_rename_failure` — verifies
fallback when staging path is blocked
- [x] `test_remove_stale_staging_dir_from_crashed_removal` — verifies
stale dirs land inside `.git/`
- [x] All 2496 tests pass (lib + bin + integration)
- [x] Help snapshots, doc sync, and lint checks all pass
Closes#1572🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com>
## Summary
- Add experimental `wt step eval` subcommand that evaluates a minijinja
template in the current worktree context and prints the result to stdout
- Reuses existing hook template infrastructure — all variables
(`branch`, `repo`, `worktree_path`, etc.) and filters (`hash_port`,
`sanitize`, `sanitize_db`) are available
- Output goes to stdout with no decoration or shell escaping, designed
for scripting and shell substitution
```
$ wt step eval '{{ branch | hash_port }}'
16066
$ curl http://localhost:$(wt step eval '{{ branch | hash_port }}')/health
```
This is the first step from the
[IDEAS.md](https://github.com/max-sixty/worktrunk/blob/arbitrary-data/IDEAS.md)
design doc, directly addressing the user request in #947 — "found no way
to run it on a single branch."
## Test plan
- [x] 6 integration tests: basic branch, hash_port, multiple values,
sanitize_db, conditionals, template error
- [x] Help text and completion snapshots updated
- [x] stdout guard allowlisted
- [x] Doc pages auto-synced
- [x] All lints pass
- [x] 2360 tests pass (5 pre-existing shell_wrapper failures excluded)
Ref #947
> _This was written by Claude Code on behalf of @max-sixty_
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Co-authored-by: worktrunk-bot <w@worktrunk.dev>
Follow-up to #1531. These three tools were only documented in
`llm-commits.md` — adding them as double-commented entries in the config
example makes them discoverable via `wt config create` and keeps all
tool commands in one place, verified by the existing sync test.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- **Trimmed upstream tracking paragraph** — `--create` doesn't configure
upstream tracking, but that's standard `git switch -c` behavior. Removed
the prominent explanation and folded the remote-branch note into the
existing sentence.
- **Added missing hooks to creation lifecycle** — The numbered list now
includes `pre-switch` (step 1) and `post-switch` (step 6), matching the
actual execution order in `handle_switch.rs`.
- **Combined GitHub/GitLab sections** — Merged two near-identical
sections into a single "Pull requests and merge requests" section,
reducing repetition.
Closes#1518
## Test plan
- [x] `test_command_pages_and_skill_files_are_in_sync` passes (docs
auto-synced)
- [x] Unit tests pass
- [ ] CI green
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com>
## Summary
- Moves branch resolution (`plan_switch`) before `pre-switch` hook
execution, so `{{ branch }}` in pre-switch hooks is the **destination**
branch rather than the source
- Applies to both `wt switch` and the interactive picker (`wt switch`
without args)
- Adds a test verifying `{{ branch }}` expands to the destination
Discussed in #1494 — `{{ branch }}` was chosen over `{{ target }}` per
[this
comment](https://github.com/max-sixty/worktrunk/issues/1494#issuecomment-4059068313).
## Test plan
- [x] All 5 pre-switch hook tests pass
- [x] All 62 user hook tests pass
- [ ] CI passes on all platforms
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The Claude/Codex recommended commands were duplicated across 4 locations
(Rust code, llm-commits.md, config.md, Taskfile) with no automated sync
— they were already drifting (missing `CLAUDECODE=` prefix, missing `-c
system_prompt=''`).
Now the double-commented entries in `config.example.toml` are the single
source of truth. `recommended_config()` parses them at runtime via
`include_str!` + `LazyLock`, and a new sync test verifies
`llm-commits.md` matches. Also fixes the existing drift in all copies.
> _This was written by Claude Code on behalf of @max-sixty_
---------
Co-authored-by: Claude <noreply@anthropic.com>
Add the `[experimental]` → empty `<span>` mapping to the post-processing
table in docs CLAUDE.md, which was missing after the badge-to-heading
change in #1523.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
Move experimental badges from the start of description paragraphs to
after the heading text in web docs.
Uses empty `<span>` elements with CSS `::after` for badge text, so the
span doesn't affect Zola's heading slug generation or page TOC entries.
This avoids the need for `{#slug}` anchor overrides and keeps sidebar
TOC entries clean (no "experimental" suffix).
Before: `## wt step relocate` / `EXPERIMENTAL Move worktrees to expected
paths.`
After: `## wt step relocate EXPERIMENTAL` / `Move worktrees to expected
paths.`
> _This was written by Claude Code on behalf of @max-sixty_
---------
Co-authored-by: Claude <noreply@anthropic.com>
\`colorize_ci_status_for_html\` was renamed to \`post_process_for_html\`
and moved from \`src/main.rs\` to \`src/help.rs\` in #1499. The docs
CLAUDE.md reference was stale.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
The picker had its own hardcoded 200ms per-command timeout default plus
a `WORKTRUNK_PICKER_BUDGET_MS` env var escape hatch, while `wt list` had
a separate experimental `[list] timeout-ms` for per-task timeouts. This
consolidates into a shared config model with clear separation between
per-task and wall-clock timeouts.
**New config model:**
- `[list] task-timeout-ms` — per-task command timeout, shared by both
list and picker (default: disabled)
- `[list] timeout-ms` — wall-clock budget for list's collect phase
(default: disabled)
- `[switch.picker] timeout-ms` — wall-clock budget for picker (default:
500ms, was 200ms per-command)
The picker's old per-command timeout goes away — the wall-clock budget
is sufficient. `collect_deadline` moves from a `collect()` parameter
into `ShowConfig::Resolved` where it belongs. Removes the
`WORKTRUNK_PICKER_BUDGET_MS` env var and a dead benchmark that tested a
non-functional env var.
Note: `[list] timeout-ms` changes semantics from per-task to wall-clock
budget. The old field was marked "(Experimental)" and not shown in
user-facing docs.
> _This was written by Claude Code on behalf of max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
Replaces plain `[experimental]` text in web docs with styled pill badges
— small uppercase labels with a subtle border that read as metadata
rather than emphasis.
Canonicalizes all experimental markers to `[experimental]` (was a mix of
`[experimental]`, `(experimental)`, `(Experimental)`). One marker format
in cli.rs, one `.replace()` in the post-processing.
Also renames `colorize_ci_status_for_html` → `post_process_for_html` (it
handles badges and URLs too), adds a module docstring documenting the
full `--help-page` pipeline, and fixes a latent double-application of
the post-processor on subdoc content.
> _This was written by Claude Code on behalf of @max-sixty_
---------
Co-authored-by: Claude <noreply@anthropic.com>
The cross-device rename happens when the worktree is on a different
filesystem from `.git/`, not "if `.git/` is on a different filesystem."
Minor accuracy fix.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
Remove the TODO ("promote this feature more prominently once it's been
tested in the wild") since LLM summaries are now on the homepage.
Tighten the subsection — the prerequisites are already in the Columns
table above, so the text now focuses on the mechanism (reuses
`commit.generation`), how to enable (`summary = true`), and caching
behavior.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
The promote command swaps branches *and* gitignored files between
worktrees — the old definition ("Put a branch into the main worktree")
undersold what it does. Updated to "Swap a branch into the main
worktree" with a subdefinition that mentions the gitignored file
exchange.
Added promote as a subdoc section on the step page (it was the only step
command with substantial `after_long_help` content that lacked one).
Expanded the gitignored files documentation to mention the shared
discovery mechanism with `copy-ignored`, `.worktreeinclude` filtering,
and the `rename()`-based swap approach.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
Add three new entries to the "Workflow automation" feature list on the
homepage: `wt list --full` (CI status & AI summaries), PR checkout (`wt
switch pr:123`), and dev server per worktree (`hash_port`). Also add a
"Full mode" section to the list docs as a link target, and link tips &
patterns from next steps.
> _This was written by Claude Code on behalf of @max-sixty_
---------
Co-authored-by: Claude <noreply@anthropic.com>
The Aliases section was sandwiched between the Operations list and See
Also — disconnected from the subcommand documentation below. Every other
step operation (commit, squash, copy-ignored, etc.) gets its own section
after the command reference, but aliases didn't.
Moved aliases after the last subdoc marker so it appears alongside the
other subcommand sections. Also added `[experimental]` prefix to match
the operations list entry, and fixed the `console → bash` code block
transform to apply before the subdoc split (it was only applied to main
content, so anything after subdoc markers missed it).
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
Adds a legend for the `⋯` (loading) and `·` (skipped) placeholder
symbols to `wt list --help`, under the existing Status symbols section.
These symbols appear across all columns during progressive table
rendering but weren't documented. The `·` symbol was introduced
alongside the picker budget feature — it indicates data collection was
truncated (timed out or branch too stale), as opposed to `⋯` which means
data is still arriving.
> _This was written by Claude Code on behalf of @max-sixty_
---------
Co-authored-by: Claude <noreply@anthropic.com>
Link subcommands from the Operations index to their detailed sections
below. Previously all items were plain text; now commit, squash, diff,
copy-ignored, for-each, prune, relocate, and alias are clickable
anchors.
Also adds `diff` as a subdoc expansion (it had `after_long_help` content
but wasn't included as a subdoc), and fixes the repetitive opener in
diff's `after_long_help` — the definition+subdefinition already listed
what's included, so the opener now just adds the `wt merge` context.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Draft implementation per @max-sixty's
[suggestion](https://github.com/max-sixty/worktrunk/pull/1404#issuecomment-4041170944):
reuse `--no-cd` to make the picker print-only instead of adding a
separate `--print` flag.
- When `wt switch --no-cd` opens the interactive picker (no branch
argument), selecting a branch prints its name to stdout and exits — no
switching, no cd directive, no hooks
- When `wt switch --no-cd <branch>` is used with an explicit branch,
behavior is unchanged (switches without cd)
- `alt-r` (remove) is blocked in print mode since it's a read-only
operation
This avoids adding a new CLI flag while giving the same scripting
capability that #1404 proposed.
## Test plan
- [x] Unit tests for `resolve_print_identifier` (switch, create, remove
cases)
- [x] PTY integration test: `--no-cd` picker prints branch name, emits
no cd directive
- [x] Existing `--no-cd` tests still pass (directive suppression, hooks,
execute)
- [x] Help snapshots and doc sync updated
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Without this flag, `claude -p` saves the commit generation conversation
to session history. When the user later runs `claude --continue`, it
resumes that ephemeral commit session instead of their previous working
session.
> _This was written by Claude Code on behalf of @max-sixty_
---------
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Updates example heading from "Remove specific worktrees:" to "Remove
specific worktrees / branches:" to clarify that `wt remove` also works
on branches
Ref #1415
## Test plan
- [x] Snapshot test updated and passing
- [x] Doc sync test passes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
For iOS developers, this PR add a `post-remove` hook recipe to Tips &
Patterns that cleans up Xcode's DerivedData when removing a worktree.
## Context
Xcode's DerivedData directory names are hashed from the `.xcodeproj`
path, making them hard to match by name alone. Each DerivedData
directory contains an `info.plist` with a `WorkspacePath` field that
records the original project path. This recipe leverages that to find
and remove only the matching cache.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The JSON context section had two issues:
- It described hook_type and hook_name as extras "plus" the template
variables, but they're regular template variables already in the table.
Fixed to say "all template variables".
- It showed a floating Python script without the toml hook definition
that calls it. Added the toml entry so the reader sees how JSON stdin
gets wired up.
Also trimmed the example (removed bridge text and filename comment) to
keep it concise.
> _This was written by Claude Code on behalf of @max-sixty_
---------
Co-authored-by: Claude <noreply@anthropic.com>
The `@/hook.md#command-approval` anchor in step.md doesn't exist,
causing
the `publish-docs` workflow to fail (`zola build` rejects broken
internal
anchors). The approval docs live under the `# Security` heading, so the
correct anchor is `#security`.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
Removes the deprecated `--no-background` flag (replaced by
`--foreground`) from
`remove`, `hook post-start`, `hook post-switch`, and `hook post-remove`.
Removes
all supporting deprecation infrastructure: warning message,
`is_foreground_mode`
helper, `DEPRECATED_ARGS` completion filtering.
Promotes `--no-progressive` from deprecated to hidden flag with inline
mention
in `--progressive`'s help text, using `flag_pair()` for consistent
handling.
Carries `foreground: bool` through the entire call chain instead of
negating to
`background` at call sites. Refactors `print_message` to use
`success_message()`/`progress_message()` helpers instead of manual color
construction, adding `FormattedMessage::append()` for integration
symbols that
need native styling outside the message's color span.
> _This was written by Claude Code on behalf of maximilian_
---------
Co-authored-by: Claude <noreply@anthropic.com>
Group `--branches`/`--remotes` under "Picker Options" and
`--yes`/`--no-verify` under "Automation" in `wt switch`, `wt remove`,
and `wt merge` help output, using clap's `help_heading`.
> _This was written by Claude Code on behalf of @max-sixty_
---------
Co-authored-by: Claude <noreply@anthropic.com>
These were already included in the JSON context piped to stdin but
couldn't be used as `{{ hook_type }}` or `{{ hook_name }}` in templates
— the values were inserted into `cmd_context` *after* template
expansion.
Now both code paths (`expand_commands` for execution,
`expand_command_template` for `wt hook show --expanded`) include them
before rendering. Also added to `TEMPLATE_VARS` so `--var hook_type=...`
works for testing.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
Promotes major sections of `wt hook --help` to H1 headings (rendered as
uppercase bold green), matching the pattern from `wt config --help`.
Subsections become H2.
Before: flat `##`/`###` headings made the long help text hard to scan.
After: five landmark sections — Hook Types, Security, Configuration,
Running Hooks Manually, Designing Effective Hooks.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
The home page (`/`) and `/worktrunk/` serve identical content (the index
template renders `worktrunk.content` directly), but each declared its
own
canonical URL. Google saw two competing pages and wasn't indexing either
as
the home page result.
- Set canonical + og:url on `/worktrunk/` to point to `/`
- Fix home page og:title/twitter:title — was just "Worktrunk", now uses
the
full tagline from `config.extra.site_description`
- Align `worktrunk.md` description with `site_description`
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
The Blocking column's "No (background)" was overspecified — the column
header
and footer definition already explain what "No" means.
> _This was written by Claude Code on behalf of max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
Move `--branches` and `--remotes` into a "Picker Options" section in `wt
switch --help`, since they only apply to the interactive picker mode and
conflict with all direct-switch flags.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Adds `wt step <alias-name>` for running user-defined command templates
configured in `[aliases]` sections of user or project config
- Aliases support the same template variables as hooks (`{{ branch }}`,
`{{ worktree }}`, etc.) plus custom `--var KEY=VALUE` variables
- Project-config aliases require the same command approval flow as
project hooks; user-config aliases are trusted. `--dry-run` skips
approval since it's a read-only preview
- Alias names matching built-in step commands are filtered from the
"available" list in error messages (shadowed by the built-in)
- Introduces `Phase` enum (`Hook(HookType)` | `Alias`) replacing the old
`hook_type` + `phase_override` pattern in the approval system
- Renames `HookCommand` to `ApprovableCommand` since it now covers both
hooks and aliases
## Test plan
- [x] Unit tests for `AliasOptions::parse` (name-only, --dry-run, --yes,
--var, empty key rejection, positional arg rejection)
- [x] Integration tests for alias execution, dry-run (without --yes),
exit code propagation
- [x] Integration tests for shadowing (filtered from available list)
- [x] Integration tests for user/project config merging
- [x] Integration tests for approval flow (project prompts, user skips,
override skips, already-approved, --yes bypass, decline)
- [x] Unit tests for `merge_alias_maps` coverage
- [x] Sync test: `BUILTIN_STEP_COMMANDS` matches actual `StepCommand`
clap variants
> _This was written by Claude Code on behalf of max-sixty_
---------
Co-authored-by: Claude <noreply@anthropic.com>
Replace `.lvh.me` with `.localhost` in all Caddy subdomain routing
examples
(docs, CLI help, tests). `.localhost` resolves to 127.0.0.1 via the OS
on
macOS and Linux with systemd-resolved — no external DNS dependency.
Also fixes a flaky PTY test: `WORKTRUNK_TEST_DELAYED_STREAM_MS` was
missing
from `STANDARD_TEST_ENV` in shell_wrapper.rs, causing `git worktree add`
output to appear non-deterministically under heavy parallel load.
Closes#1334
> _This was written by Claude Code on behalf of maximilian_
---------
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Maximilian Roos <m@maxroos.com>
The `summary` field was wired up in the table UI but never added to
`JsonItem`, so `wt list --format=json` never included LLM summaries even
when configured. Also improves doc comments to mention all three
requirements for summary generation.
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Change the `pre-switch` hook example from `git fetch` to `git pull`
- `git fetch` only updates remote tracking refs without advancing the
local branch, so a new worktree created after fetch is still based on
the old local HEAD — not the latest remote
Reported by @jdb8 in #1085.
## Test plan
- [x] Doc sync test passes (docs and skill reference updated
automatically)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
Adds an `alt-d` keybinding to the `wt switch` interactive picker that
removes the highlighted worktree directly, without needing to type the
branch name or switch first.
- **Safe defaults**: no `-D` (force-delete unmerged branches), no `-f`
(force-remove dirty worktrees) — matches the safety behavior requested
in #1251
- Removes the worktree and its merged branch in foreground (immediate
feedback)
- Shows standard `wt remove` success/failure output after picker exits
- Controls line in the preview pane updated to show `alt-d: delete`
Closes#1251
## Test plan
- [x] All 554 unit tests pass (`cargo test --lib --bins`)
- [x] Clippy clean
- [x] Doc sync test passes
- [ ] Manual testing: open `wt switch`, highlight a worktree, press
`alt-d` — verify it removes the worktree and shows the success message
- [ ] Manual testing: try `alt-d` on main worktree — verify it shows
"Cannot remove the main working tree" error
- [ ] Manual testing: try `alt-d` on a worktree with uncommitted changes
— verify it shows the dirty worktree error
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
## Summary
- Add opencode as a supported tool for LLM commit message generation
- Condense opencode, llm, and aichat into a single "Other tools" section
with just recommended commands
- Claude Code and Codex retain their own detailed sections
- Auto-sync skill reference file
Closes#911
## Feedback welcome
@viicslen @gabimoncha — does `opencode run -m anthropic/claude-haiku-4.5
--variant fast` work correctly? Happy to adjust the flags.
---------
Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
- Add early `check_ffmpeg_libass()` at demo build startup — exits with
install
instructions when ffmpeg lacks libass (required for keystroke overlay
ASS
subtitles)
- Add output verification in `record_vhs()` — catches silent failures
where VHS
exits 0 but produces no GIF
- Document the Homebrew API-bottle vs tap-formula issue in demos
CLAUDE.md
Homebrew's API-sourced formula strips `libass`; the tap formula includes
it.
The fix is `HOMEBREW_NO_INSTALL_FROM_API=1 brew install
--build-from-source ffmpeg`.
## Test plan
- [x] Verified `check_ffmpeg_libass()` passes with correct ffmpeg
- [x] Verified full demo build succeeds with `--only wt-switch-picker`
- [x] Lints pass (`pre-commit run --all-files`)
> _This was written by Claude Code on behalf of @max-sixty_
Co-authored-by: Claude <noreply@anthropic.com>