Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ wt help # show usage

Aliases: `add`/`create` → `mk`, `remove`/`del` → `rm`, `list` → `ls`

Worktrees are created in `.claude/worktrees/<branch>` inside the repo, the same place Claude Code puts them, so both tools see the same set. Add `.claude/worktrees/` to your `.gitignore` if it isn't already. Slashes in a branch name become dashes in the folder.
Worktrees are created in `.claude/worktrees/<branch>` inside the repo, the same place Claude Code puts them, so both tools see the same set. Add `.claude/worktrees/` to your `.gitignore` if it isn't already. Slashes in a branch name become dashes in the folder, and a leading `worktree-` is dropped (Claude Code names its branches that way, so `wt mk worktree-my-feature` creates `.claude/worktrees/my-feature`, matching what Claude Code would do).

Set `wt.path` to put them somewhere else - `{name}` is the branch with slashes replaced, `{repo}` the repo's folder name, and a relative template resolves against the repo root so it means the same from any worktree:

Expand Down
3 changes: 2 additions & 1 deletion lib/commands/help.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ wt.path:
Where `wt mk` puts a worktree, if you don't want .claude/worktrees/<branch>:
git config wt.path '../{repo}-{name}' # sibling of the repo
git config --global wt.path '~/wt/{name}' # all repos, outside the tree
{name} is the branch with slashes replaced, {repo} the repo's folder name.
{name} is the branch with slashes replaced and a leading worktree- dropped,
{repo} the repo's folder name.
A relative template resolves against the repo root.

.worktreeinclude:
Expand Down
2 changes: 1 addition & 1 deletion lib/commands/mk.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ _wt_mk() {
set -- "${args[@]}"
local branch="${1?usage: wt mk <branch> [path] [--base B] [--pre-hook P] [--post-hook P]}"
local root; root=$(_wt_root) || return 1
local safe="${branch//\//-}"
local safe; safe=$(_wt_safe_name "$branch")
local dest="$2"
[ -n "$dest" ] || { dest=$(_wt_dest_default "$root" "$safe") || return 1; }
_wt_warn_unignored "$root" "$dest"
Expand Down
10 changes: 10 additions & 0 deletions lib/core.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ _wt_copy_worktreeinclude() {
done
}

# folder name for a branch: slashes become dashes, and a leading "worktree-" is
# dropped (Claude Code names branches that way; the folder is already a worktree)
_wt_safe_name() {
local name="${1//\//-}"
case "$name" in
worktree-?*) printf '%s' "${name#worktree-}" ;;
*) printf '%s' "$name" ;;
esac
}

# where a new worktree goes: the wt.path template if set, else .claude/worktrees/<name>.
# {name} is the branch with slashes replaced, {repo} the repo's folder name. A relative
# template resolves against the repo root, so it means the same from any worktree.
Expand Down
2 changes: 1 addition & 1 deletion test/helpers.bash
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ wt_common_setup() {

# default worktree path wt mk uses for a branch, inside the test repo
wt_dest() {
local safe="${1//\//-}"
local safe; safe=$(_wt_safe_name "$1")
printf '%s' "$TEST_REPO/.claude/worktrees/$safe"
}

Expand Down
17 changes: 17 additions & 0 deletions test/mk.bats
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@ teardown() { wt_common_teardown; }
git worktree remove "$expected"
}

@test "wt mk strips a leading worktree- from the folder name" {
local branch="worktree-back-in-stock-report"
wt mk "$branch"
local expected="$TEST_REPO/.claude/worktrees/back-in-stock-report"
[ -d "$expected" ]
[ "$(git -C "$expected" rev-parse --abbrev-ref HEAD)" = "$branch" ]
git worktree remove "$expected"
}

@test "wt mk keeps a branch named exactly worktree- intact" {
local branch="worktree-"
wt mk "$branch"
local expected="$TEST_REPO/.claude/worktrees/worktree-"
[ -d "$expected" ]
git worktree remove "$expected"
}

@test "wt mk accepts explicit path" {
local dest="$TEST_REPO-explicit"
wt mk explicit-path "$dest"
Expand Down
9 changes: 9 additions & 0 deletions test/resolve.bats
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,12 @@ teardown() { wt_common_teardown; }
result=$(_wt_resolve nonexistent)
[ -z "$result" ]
}

@test "_wt_resolve finds a worktree- branch by both branch name and folder name" {
wt mk worktree-resolve-demo
cd "$TEST_REPO"
local expected="$TEST_REPO/.claude/worktrees/resolve-demo"
[ "$(_wt_resolve worktree-resolve-demo)" = "$expected" ]
[ "$(_wt_resolve resolve-demo)" = "$expected" ]
git worktree remove "$expected"
}