Commit Graph

1003 Commits

Author SHA1 Message Date
worktrunk-bot 5eb7a76176 docs: clarify hook execution order (post-create before post-start) (#1573) 2026-03-16 22:01:17 -07:00
Sirio Balmelli 799aab0eb9 merge: add --no-ff flag for merge commit (semi-linear history) (#1438) 2026-03-16 18:15:23 -07:00
Maximilian Roos a7f224d263 feat: add wt step eval for template expression evaluation (#1004)
## 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>
2026-03-16 05:55:23 +00:00
Maximilian Roos 7512d8695e Add opencode, llm, and aichat to example config (#1533)
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>
2026-03-14 17:41:29 -07:00
worktrunk-bot df54d28c3a docs(switch): trim upstream tracking, add missing hooks, combine PR/MR sections (#1521)
## 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>
2026-03-14 23:31:26 +00:00
worktrunk-bot e47778d5b9 feat(switch): expose destination branch in pre-switch hooks (#1497)
## 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>
2026-03-14 16:29:35 -07:00
Maximilian Roos 5a2895cd03 Add LLM tool commands to example config as single source of truth (#1531)
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>
2026-03-14 16:08:53 -07:00
Maximilian Roos 18aab7b171 docs: add experimental badge to post-processing table (#1526)
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>
2026-03-14 14:51:42 -07:00
Maximilian Roos 879cbd906b feat(docs): move experimental badges to headings (#1523)
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>
2026-03-14 14:29:41 -07:00
worktrunk-bot b5a2bb2e9c docs(list): restore --full prerequisite for LLM summaries (#1517) 2026-03-14 16:51:29 +00:00
Maximilian Roos 73fbf5a54b docs: fix stale function name in docs CLAUDE.md (#1516)
\`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>
2026-03-14 01:10:38 -07:00
Maximilian Roos 7834271528 Unify timeout model for list and switch picker (#1515)
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>
2026-03-14 01:08:36 -07:00
Maximilian Roos 0760817af7 feat(docs): style experimental markers as badge pills (#1499)
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>
2026-03-14 00:12:22 -07:00
Maximilian Roos 50edfbfb36 docs(step): fix cross-filesystem fallback description (#1513)
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>
2026-03-13 23:48:24 -07:00
Maximilian Roos e00654b3ed docs(list): rewrite LLM summaries section (#1506)
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>
2026-03-13 21:20:06 -07:00
Maximilian Roos 1cfa5f6806 docs(step): add promote subdoc, improve swap description (#1505)
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>
2026-03-13 21:14:30 -07:00
Maximilian Roos a892caa39b docs(homepage): add headline features and tips link (#1501)
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>
2026-03-13 20:48:13 -07:00
Maximilian Roos 6048546e3a docs(step): move aliases section after subcommands (#1502)
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>
2026-03-13 20:38:34 -07:00
Maximilian Roos e89049a321 docs(list): document placeholder symbols in help text (#1496)
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>
2026-03-13 15:39:57 -07:00
Maximilian Roos f2ea4d65f7 docs(step): link Operations index to subcommand sections (#1495)
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>
2026-03-13 15:34:50 -07:00
Jarryd Tilbrook 00eb04a042 feat(switch): add no-cd config option (#1401) 2026-03-13 07:42:40 -07:00
worktrunk-bot 905aa273df docs: add manual commit message recipes (#1469) 2026-03-13 06:06:25 -07:00
worktrunk-bot 54f34bb19c feat(switch): make --no-cd print-only in picker mode (#1445)
## 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>
2026-03-11 22:12:16 -07:00
Maximilian Roos 9b77ab2d93 fix: add --no-session-persistence to Claude commit generation (#1454)
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>
2026-03-11 16:20:00 -07:00
worktrunk-bot 3080eb0922 docs(remove): update example heading to mention branches (#1449)
## 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>
2026-03-11 22:07:11 +00:00
Rickey 26333bc87b docs: add Xcode DerivedData cleanup recipe (#1423)
## 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>
2026-03-10 13:04:47 -07:00
Maximilian Roos 1389a0b783 docs(hook): improve JSON context section (#1360)
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>
2026-03-09 21:12:18 -07:00
Maximilian Roos 4dfac6cde8 fix(docs): broken anchor link in step.md (#1391)
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>
2026-03-08 19:57:52 -07:00
Maximilian Roos fe56eaa335 Remove --no-background, promote --no-progressive, carry foreground through (#1381)
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>
2026-03-08 17:25:56 -07:00
Maximilian Roos 2bca89a886 Group help options into Picker and Automation headings (#1355)
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>
2026-03-08 14:07:58 -07:00
Maximilian Roos 486a8195d2 feat(hook): make hook_type and hook_name available as template variables (#1364)
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>
2026-03-08 00:31:19 -08:00
Maximilian Roos 6d8415f58c Group hook help into navigational sections (#1359)
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>
2026-03-08 00:01:18 -08:00
Maximilian Roos 0638cd5a93 docs: fix home page SEO — canonical dedup and consistent tagline (#1357)
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>
2026-03-07 23:55:05 -08:00
Maximilian Roos 10f752453b Remove redundant "(background)" from hook help table (#1356)
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>
2026-03-07 23:40:26 -08:00
Maximilian Roos 9988530bf8 Group picker options under separate help heading in wt switch (#1353)
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>
2026-03-07 23:15:00 -08:00
Maximilian Roos 55bc9188b4 feat(step): add alias command for user-defined command templates (#1348)
## 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>
2026-03-07 21:46:41 -08:00
worktrunk-bot 2e29a275dd docs: use .localhost subdomains instead of .lvh.me for Caddy routing (#1343)
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>
2026-03-07 17:11:15 -08:00
Maximilian Roos 3327edcb31 fix(list): add missing summary field to JSON output (#1339)
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>
2026-03-07 14:08:30 -08:00
worktrunk-bot 691060e665 fix(docs): use git pull instead of git fetch in pre-switch hook example (#1323)
## 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>
2026-03-06 19:03:08 -08:00
worktrunk-bot afc3754a5a feat: add alt-d shortcut to delete worktrees from switch picker (#1253)
## 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>
2026-03-06 05:52:29 +00:00
worktrunk-bot e596a07db6 docs: add empty system prompt to codex command for speed (#1300)
## Summary

- Add `-c system_prompt=''` to the Codex example command to skip the
default system prompt, reducing tokens and latency for commit message
generation

Follow-up from #1295 — @max-sixty asked about using empty system prompts
for speed.

**opencode**: Does not currently support disabling the system prompt.
The system prompt is always injected, and even the plugin system has a
safety fallback that restores the original if emptied. There are open
feature requests
([#1242](https://github.com/anomalyco/opencode/issues/1242),
[#1894](https://github.com/sst/opencode/issues/1894),
[#5005](https://github.com/anomalyco/opencode/issues/5005)) but nothing
available yet.

**Codex**: Has an undocumented `system_prompt` config key that can be
overridden via `-c system_prompt=''`. There are feature requests for
dedicated `--system-prompt` flags
([#6023](https://github.com/openai/codex/issues/6023),
[#11588](https://github.com/openai/codex/issues/11588)) but not yet
merged.

Co-authored-by: worktrunk-bot <254187624+worktrunk-bot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 21:13:16 -08:00
worktrunk-bot b49ab2bbc0 docs: add opencode and condense other LLM commit tools (#1295)
## 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>
2026-03-05 19:45:05 -08:00
Maximilian Roos 0f317c79db Add DevOpsToolbox video link to further reading 2026-03-04 11:10:51 -08:00
worktrunk-bot 070e23f6e3 fix: exclude VCS metadata directories from copy-ignored (#1250) 2026-03-03 21:07:25 -08:00
Maximilian Roos 340a83f6d0 fix: fail fast when ffmpeg lacks libass for demo GIF builds (#1237)
## 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>
2026-02-28 20:11:49 -08:00
Maximilian Roos 44ce42e4a8 fix: improve wt step prune reliability and UX (#1234)
## Summary

- Mark `wt step prune` as `[experimental]`
- Remove candidates inline as they're discovered instead of
scan-then-remove — each worktree is pruned immediately, with the current
worktree deferred to last
- Handle per-candidate errors gracefully (warn and skip) rather than
aborting the entire prune — dirty worktrees are caught by the same
`ensure_clean` check that `wt remove` uses
- Dry-run lists candidates with `○` lines; actual removal only shows `◎
Removing` output
- Drop redundant help text ("uncommitted changes are skipped" is
inherited from `wt remove`; "Note: experimental" is redundant with
`[experimental]` tag)
- Add test for dirty worktree handling

## Test plan

- [x] All 2740 tests pass (`wt hook pre-merge --yes`)
- [x] Snapshot tests reviewed for all prune scenarios (dry-run,
multiple, dirty, locked, stale, orphan branches, current worktree,
detached, min-age)
- [ ] Manual test: run `wt step prune --dry-run` on a repo with merged
worktrees

> _This was written by Claude Code on behalf of @max-sixty_

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-28 01:08:39 -08:00
Maximilian Roos 35c2172b74 feat: add wt step prune to remove merged worktrees (#1191) 2026-02-26 00:06:34 -08:00
Maximilian Roos 1cf2c8203f Add page metadata, canonical URLs, and structured data to docs (#1167)
## Summary

- Add per-page `<meta name="description">` to all doc pages — command
pages auto-generated from CLI `about`/`long_about` via new
`--help-description` flag, non-command pages manually written
- Add `<link rel="canonical">` URLs and JSON-LD structured data (WebSite
+ SoftwareApplication) on the homepage
- Add custom `sitemap.xml` template with `<lastmod>` dates and
descriptive homepage `<title>`
- Extract shared `extract_about_and_subtitle()` helper, eliminating
duplicated subtitle logic between `handle_help_description` and
`combine_command_docs`
- Fix broken anchor in faq.md (`#picker-summaries` →
`#branch-summaries-experimental`)

## Test plan

- [x] Full test suite passes (2713 tests via `wt hook pre-merge --yes`)
- [x] All lints clean (pre-commit, clippy, cargo fmt)
- [x] Doc sync test confirms auto-generated descriptions match CLI help
- [x] Zola build succeeds with all template changes

> _This was written by Claude Code on behalf of @max-sixty_

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-22 13:58:34 -08:00
Maximilian Roos bc2ee2dcb6 Add experimental wt step promote command (#789)
## Summary

Adds `wt step promote` — an experimental command to exchange branches
between the main worktree and another worktree, including swapping
gitignored files (build artifacts, `.env`, `node_modules/`, etc.). This
addresses #738 where users want to move a branch from a worktree into
the main worktree.

This is useful when the main worktree has special significance (Docker
Compose configs, IDE settings, heavy build artifacts anchored to project
root) and hooks aren't yet set up to run on arbitrary worktrees.

**Key features:**
- Exchange branches between main worktree and any other worktree
- Swap gitignored files so build artifacts follow their branch
- Auto-restore: `wt step promote` from main worktree (no args) restores
default branch
- Shows mismatch state in `wt list` with ⚑ indicator
- Warns when creating mismatch, with hint to restore
- `.worktreeinclude` filtering respected per worktree

**Swap algorithm (stage → exchange → distribute):**
1. Discover gitignored entries before branch exchange (`.gitignore`
belongs to the branch)
2. Stage files to `.git/wt-promote-staging/` before `git switch`
(prevents tracked file collision)
3. Exchange branches with per-step rollback
4. Cross-distribute staged files to new worktrees
5. Best-effort restore on failure with recovery guidance

**Adversarial testing (4 rounds, 9 issues found and fixed):**
- Stage before switch to prevent tracked file collision
- Per-step rollback in `exchange_branches()`
- Bail on leftover staging (don't destroy previous run's files)
- Recovery guidance on all failure paths
- Dedicated `restore_staged()` for rollback semantics
- `ErrorKind::CrossesDevices` for cross-device fallback
- `Option<PathBuf>` instead of sentinel empty path

## Test plan

- [x] 25 integration tests covering: bidirectional swap, round-trip,
`.worktreeinclude` filtering, nested directories,
same-filename-different-content, tracked-vs-ignored separation, stale
staging detection, bare repo rejection, detached HEAD, dirty worktrees,
no-arg from main/linked, branch argument, already-in-main, mismatch
indicator in `wt list`
- [x] All 2576 tests pass
- [x] All lints clean
- [x] `copy-ignored` tests still pass after
`list_and_filter_ignored_entries` extraction

🤖 Generated with [Claude Code](https://claude.com/claude-code)

> _This was written by Claude Code on behalf of max-sixty_

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-21 10:44:38 -08:00
Maximilian Roos bba3a209b8 fix: align user-facing output with formatting guidelines (#1138)
## Summary
- Replace `<bold>` with `<bright-black>` inside `hint_message()` calls —
bold's close tag (`[22m`) resets both bold and dim, breaking hint
styling
- Use `format_path_for_display()` instead of raw `.display()` in
user-facing messages (config warning, relocate errors, step_commands
output)
- Remove "you/your" pronouns from help text and rephrase typo
suggestions
- Reorder hint phrasing to canonical "To X, run/use Y" pattern

## Test plan
- [x] All 1084 integration tests pass
- [x] All lints pass (`pre-commit run --all-files`)
- [x] Snapshot tests updated to reflect new wording

> _This was written by Claude Code on behalf of @max-sixty_

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-20 16:10:58 -08:00