Skip to content
This repository was archived by the owner on Jul 28, 2026. It is now read-only.

Latest commit

History

33 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

wtree

A CLI tool for managing git worktrees with powerful workflow automation, on both bare-hub and standard repositories.

Git worktrees let you work on multiple branches simultaneously in separate directories. wtree wraps git worktree with a lifecycle hook system that automates your workflow—install dependencies, copy environment files, run setup scripts—all triggered automatically when you create, switch, or remove worktrees.

It works in two layouts (see Layouts): the original bare-hub layout created by wt clone, and any standard cloned repository adopted with wt init.

Why wtree?

Workflow Automation via Hooks

Most worktree tools stop at git worktree add. wtree goes further with a two-phase hook system that automates your entire development workflow:

# .wtree/hooks.toml
[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]

Every time you create a new worktree, your environment is automatically set up. Switch to an existing worktree? Dependencies are synced. No manual steps, no forgotten setup.

Installation

Cargo

cargo install wtree

Shell Setup

Add to your .bashrc or .zshrc:

# Basheval"$(wt shell-init bash)"# Zsheval"$(wt shell-init zsh)"

Breaking change in v0.7.0: the shell-integration command moved from wt init <shell> to wt shell-init <shell>. wt init (no shell argument) now adopts a standard repository (see Layouts). Update your .bashrc/.zshrc accordingly. The emitted shell function is otherwise unchanged.

Layouts

wtree detects your repository layout automatically and behaves identically across both.

Bare-hub layout. Created by wt clone <url>, which clones into <repo>/.bare and places each worktree as a sibling directory (<repo>/<name>). State and hooks live in <repo>/.wtree/. This is the original layout and is unchanged.

Standard layout. Any ordinary cloned repository. Adopt it with wt init from inside the repo. Worktrees are created under .claude/worktrees/<name>/ by default, state and hooks live in .git/wtree/, and the worktree directory is added to .gitignore automatically. wt create also lazily initializes a never-adopted standard repo on first use, so wt init is optional.

cd my-cloned-repo
wt init # adopt this repo (state dir, hooks template, gitignore entry)
wt create feature-x # creates .claude/worktrees/feature-x/

Override where standard-layout worktrees are created with a worktree_base entry in .git/wtree/config.toml (relative paths resolve against the repo root, absolute paths are used as-is):

# .git/wtree/config.tomlworktree_base = "../my-worktrees"

Usage

CommandDescription
wt clone <url> [-switch]Clone repo as bare with default branch worktree
wt initAdopt the current standard repo for wtree
wt create <name> [--checkout branch] [--base worktree] [-s]Create new worktree (alias: c)
wt switch <name>Switch to worktree (alias: sw)
wt listList all worktrees (alias: ls)
wt remove <name>...Remove one or more worktrees (alias: rm)
wt prune [-f]Remove all worktrees except the default (alias: p)

Examples

# Clone a repository
wt clone git@github.com:user/repo.git
wt clone git@github.com:user/repo.git -s # clone and switch to default branch# Create worktrees
wt create feature-auth # new worktree from bare repo HEAD
wt create hotfix --checkout main # check out existing branch 'main' in new worktree
wt create feature-ui -s # create and switch to the new worktree
wt create fix-123 --base feature-auth # branch off 'feature-auth' worktree's current commit# Switch between worktrees
wt switch main
wt sw feature-auth
# List and remove
wt ls
wt rm feature-auth # remove single worktree
wt rm feature-one feature-two # remove multiple worktrees# Prune all non-default worktrees
wt prune # interactive confirmation
wt prune -f # skip confirmation

Flags

  • -s, --switch: After clone/create, switch to the new worktree
  • --checkout <branch>: Check out an existing branch in the new worktree. Fails if that branch is already checked out in another worktree. Use this when the branch already exists in the repository but is not currently active.
  • --base <worktree>: Create the new worktree as a new branch starting at the given worktree's current commit. Use this to branch off work-in-progress from another worktree, even if its branch is already checked out. Cannot be combined with --checkout.
  • -f, --force: Skip the confirmation prompt when pruning worktrees

Hooks

The hook system is wtree's core feature. Define shell commands that run automatically during worktree lifecycle events.

Local Hooks

When you clone a repository with wt clone, a customisble template .wtree/hooks.toml is created:

Global Default Hooks

Define default hooks that apply to all new repositories:

mkdir -p ~/.wtree
cat >~/.wtree/default-hooks.toml << 'EOF'[create]pre = []post = ["cp \"$WT_HUB_ROOT/main/.env\" \"$WT_WORKTREE_PATH/.env\""][switch]pre = []post = [][remove]pre = []post = []EOF

When you run wt clone, the tool will:

  1. Check if ~/.wtree/default-hooks.toml exists
  2. If it exists, copy its content as the new repository's .wtree/hooks.toml
  3. If it doesn't exist, use the built-in template with commented examples

Environment Variables

Hooks receive full context via environment variables:

VariableDescriptionAvailable in
WT_COMMANDCommand name (create/switch/remove)All hooks
WT_WORKTREE_NAMEName of the target worktreeAll hooks
WT_WORKTREE_PATHAbsolute path to target worktreeAll hooks
WT_HUB_ROOTRepo root: hub root (parent of .bare) in bare layout, main worktree in standard layoutAll hooks
WT_BRANCHBranch name (if specified)create only

In the standard layout WT_HUB_ROOT is the main worktree path rather than the parent of .bare; the variable keeps its name for backward compatibility, but its meaning is the repo root in the active layout.

Execution Model

PhaseWorking DirectoryOn Failure
Pre-hooksRepo root (hub root / main worktree)Command aborted
Post-hooksTarget worktree directoryWarning logged, command completes

This design lets you:

  • Use pre-hooks as gates (validate branch names, check prerequisites)
  • Use post-hooks for setup (install deps, copy files) without blocking on failures

Real-World Examples

Node.js project with shared environment:

[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]
[switch]
post = ["npm install"]

Python project with virtual environments:

[create]
post = [
"python -m venv .venv",
"source .venv/bin/activate && pip install -r requirements.txt"
]
[switch]
post = ["source .venv/bin/activate"]

Validate branch naming convention:

[create]
pre = ["[[ \"$WT_WORKTREE_NAME\" =~ ^(feature|fix|hotfix)- ]]"]
post = []

Development

cargo build # debug build
cargo build --release # release build
cargo test# run tests

Install from source

git clone https://github.com/imqdee/wtree.git
cd wtree
cargo build --release
cp target/release/wt ~/.local/bin/ # or anywhere in your PATH

Development Git Hooks

This project uses lefthook for git hooks.

# Install lefthook (macOS)
brew install lefthook
# Install hooks
lefthook install

Hooks run automatically on commit (fmt, clippy) and push (test, build).

License

MIT

About

CLI tool for managing git worktrees with powerful workflow automation, and AI support

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - imqdee/wtree: CLI tool for managing git worktrees with powerful workflow automation, and AI support · GitHub
Skip to content
This repository was archived by the owner on Jul 28, 2026. It is now read-only.

Latest commit

History

33 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

wtree

A CLI tool for managing git worktrees with powerful workflow automation, on both bare-hub and standard repositories.

Git worktrees let you work on multiple branches simultaneously in separate directories. wtree wraps git worktree with a lifecycle hook system that automates your workflow—install dependencies, copy environment files, run setup scripts—all triggered automatically when you create, switch, or remove worktrees.

It works in two layouts (see Layouts): the original bare-hub layout created by wt clone, and any standard cloned repository adopted with wt init.

Why wtree?

Workflow Automation via Hooks

Most worktree tools stop at git worktree add. wtree goes further with a two-phase hook system that automates your entire development workflow:

# .wtree/hooks.toml
[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]

Every time you create a new worktree, your environment is automatically set up. Switch to an existing worktree? Dependencies are synced. No manual steps, no forgotten setup.

Installation

Cargo

cargo install wtree

Shell Setup

Add to your .bashrc or .zshrc:

# Basheval"$(wt shell-init bash)"# Zsheval"$(wt shell-init zsh)"

Breaking change in v0.7.0: the shell-integration command moved from wt init <shell> to wt shell-init <shell>. wt init (no shell argument) now adopts a standard repository (see Layouts). Update your .bashrc/.zshrc accordingly. The emitted shell function is otherwise unchanged.

Layouts

wtree detects your repository layout automatically and behaves identically across both.

Bare-hub layout. Created by wt clone <url>, which clones into <repo>/.bare and places each worktree as a sibling directory (<repo>/<name>). State and hooks live in <repo>/.wtree/. This is the original layout and is unchanged.

Standard layout. Any ordinary cloned repository. Adopt it with wt init from inside the repo. Worktrees are created under .claude/worktrees/<name>/ by default, state and hooks live in .git/wtree/, and the worktree directory is added to .gitignore automatically. wt create also lazily initializes a never-adopted standard repo on first use, so wt init is optional.

cd my-cloned-repo
wt init # adopt this repo (state dir, hooks template, gitignore entry)
wt create feature-x # creates .claude/worktrees/feature-x/

Override where standard-layout worktrees are created with a worktree_base entry in .git/wtree/config.toml (relative paths resolve against the repo root, absolute paths are used as-is):

# .git/wtree/config.tomlworktree_base = "../my-worktrees"

Usage

CommandDescription
wt clone <url> [-switch]Clone repo as bare with default branch worktree
wt initAdopt the current standard repo for wtree
wt create <name> [--checkout branch] [--base worktree] [-s]Create new worktree (alias: c)
wt switch <name>Switch to worktree (alias: sw)
wt listList all worktrees (alias: ls)
wt remove <name>...Remove one or more worktrees (alias: rm)
wt prune [-f]Remove all worktrees except the default (alias: p)

Examples

# Clone a repository
wt clone git@github.com:user/repo.git
wt clone git@github.com:user/repo.git -s # clone and switch to default branch# Create worktrees
wt create feature-auth # new worktree from bare repo HEAD
wt create hotfix --checkout main # check out existing branch 'main' in new worktree
wt create feature-ui -s # create and switch to the new worktree
wt create fix-123 --base feature-auth # branch off 'feature-auth' worktree's current commit# Switch between worktrees
wt switch main
wt sw feature-auth
# List and remove
wt ls
wt rm feature-auth # remove single worktree
wt rm feature-one feature-two # remove multiple worktrees# Prune all non-default worktrees
wt prune # interactive confirmation
wt prune -f # skip confirmation

Flags

  • -s, --switch: After clone/create, switch to the new worktree
  • --checkout <branch>: Check out an existing branch in the new worktree. Fails if that branch is already checked out in another worktree. Use this when the branch already exists in the repository but is not currently active.
  • --base <worktree>: Create the new worktree as a new branch starting at the given worktree's current commit. Use this to branch off work-in-progress from another worktree, even if its branch is already checked out. Cannot be combined with --checkout.
  • -f, --force: Skip the confirmation prompt when pruning worktrees

Hooks

The hook system is wtree's core feature. Define shell commands that run automatically during worktree lifecycle events.

Local Hooks

When you clone a repository with wt clone, a customisble template .wtree/hooks.toml is created:

Global Default Hooks

Define default hooks that apply to all new repositories:

mkdir -p ~/.wtree
cat >~/.wtree/default-hooks.toml << 'EOF'[create]pre = []post = ["cp \"$WT_HUB_ROOT/main/.env\" \"$WT_WORKTREE_PATH/.env\""][switch]pre = []post = [][remove]pre = []post = []EOF

When you run wt clone, the tool will:

  1. Check if ~/.wtree/default-hooks.toml exists
  2. If it exists, copy its content as the new repository's .wtree/hooks.toml
  3. If it doesn't exist, use the built-in template with commented examples

Environment Variables

Hooks receive full context via environment variables:

VariableDescriptionAvailable in
WT_COMMANDCommand name (create/switch/remove)All hooks
WT_WORKTREE_NAMEName of the target worktreeAll hooks
WT_WORKTREE_PATHAbsolute path to target worktreeAll hooks
WT_HUB_ROOTRepo root: hub root (parent of .bare) in bare layout, main worktree in standard layoutAll hooks
WT_BRANCHBranch name (if specified)create only

In the standard layout WT_HUB_ROOT is the main worktree path rather than the parent of .bare; the variable keeps its name for backward compatibility, but its meaning is the repo root in the active layout.

Execution Model

PhaseWorking DirectoryOn Failure
Pre-hooksRepo root (hub root / main worktree)Command aborted
Post-hooksTarget worktree directoryWarning logged, command completes

This design lets you:

  • Use pre-hooks as gates (validate branch names, check prerequisites)
  • Use post-hooks for setup (install deps, copy files) without blocking on failures

Real-World Examples

Node.js project with shared environment:

[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]
[switch]
post = ["npm install"]

Python project with virtual environments:

[create]
post = [
"python -m venv .venv",
"source .venv/bin/activate && pip install -r requirements.txt"
]
[switch]
post = ["source .venv/bin/activate"]

Validate branch naming convention:

[create]
pre = ["[[ \"$WT_WORKTREE_NAME\" =~ ^(feature|fix|hotfix)- ]]"]
post = []

Development

cargo build # debug build
cargo build --release # release build
cargo test# run tests

Install from source

git clone https://github.com/imqdee/wtree.git
cd wtree
cargo build --release
cp target/release/wt ~/.local/bin/ # or anywhere in your PATH

Development Git Hooks

This project uses lefthook for git hooks.

# Install lefthook (macOS)
brew install lefthook
# Install hooks
lefthook install

Hooks run automatically on commit (fmt, clippy) and push (test, build).

License

MIT

About

CLI tool for managing git worktrees with powerful workflow automation, and AI support

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - imqdee/wtree: CLI tool for managing git worktrees with powerful workflow automation, and AI support · GitHub
Skip to content
This repository was archived by the owner on Jul 28, 2026. It is now read-only.

Latest commit

History

33 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

wtree

A CLI tool for managing git worktrees with powerful workflow automation, on both bare-hub and standard repositories.

Git worktrees let you work on multiple branches simultaneously in separate directories. wtree wraps git worktree with a lifecycle hook system that automates your workflow—install dependencies, copy environment files, run setup scripts—all triggered automatically when you create, switch, or remove worktrees.

It works in two layouts (see Layouts): the original bare-hub layout created by wt clone, and any standard cloned repository adopted with wt init.

Why wtree?

Workflow Automation via Hooks

Most worktree tools stop at git worktree add. wtree goes further with a two-phase hook system that automates your entire development workflow:

# .wtree/hooks.toml
[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]

Every time you create a new worktree, your environment is automatically set up. Switch to an existing worktree? Dependencies are synced. No manual steps, no forgotten setup.

Installation

Cargo

cargo install wtree

Shell Setup

Add to your .bashrc or .zshrc:

# Basheval"$(wt shell-init bash)"# Zsheval"$(wt shell-init zsh)"

Breaking change in v0.7.0: the shell-integration command moved from wt init <shell> to wt shell-init <shell>. wt init (no shell argument) now adopts a standard repository (see Layouts). Update your .bashrc/.zshrc accordingly. The emitted shell function is otherwise unchanged.

Layouts

wtree detects your repository layout automatically and behaves identically across both.

Bare-hub layout. Created by wt clone <url>, which clones into <repo>/.bare and places each worktree as a sibling directory (<repo>/<name>). State and hooks live in <repo>/.wtree/. This is the original layout and is unchanged.

Standard layout. Any ordinary cloned repository. Adopt it with wt init from inside the repo. Worktrees are created under .claude/worktrees/<name>/ by default, state and hooks live in .git/wtree/, and the worktree directory is added to .gitignore automatically. wt create also lazily initializes a never-adopted standard repo on first use, so wt init is optional.

cd my-cloned-repo
wt init # adopt this repo (state dir, hooks template, gitignore entry)
wt create feature-x # creates .claude/worktrees/feature-x/

Override where standard-layout worktrees are created with a worktree_base entry in .git/wtree/config.toml (relative paths resolve against the repo root, absolute paths are used as-is):

# .git/wtree/config.tomlworktree_base = "../my-worktrees"

Usage

CommandDescription
wt clone <url> [-switch]Clone repo as bare with default branch worktree
wt initAdopt the current standard repo for wtree
wt create <name> [--checkout branch] [--base worktree] [-s]Create new worktree (alias: c)
wt switch <name>Switch to worktree (alias: sw)
wt listList all worktrees (alias: ls)
wt remove <name>...Remove one or more worktrees (alias: rm)
wt prune [-f]Remove all worktrees except the default (alias: p)

Examples

# Clone a repository
wt clone git@github.com:user/repo.git
wt clone git@github.com:user/repo.git -s # clone and switch to default branch# Create worktrees
wt create feature-auth # new worktree from bare repo HEAD
wt create hotfix --checkout main # check out existing branch 'main' in new worktree
wt create feature-ui -s # create and switch to the new worktree
wt create fix-123 --base feature-auth # branch off 'feature-auth' worktree's current commit# Switch between worktrees
wt switch main
wt sw feature-auth
# List and remove
wt ls
wt rm feature-auth # remove single worktree
wt rm feature-one feature-two # remove multiple worktrees# Prune all non-default worktrees
wt prune # interactive confirmation
wt prune -f # skip confirmation

Flags

  • -s, --switch: After clone/create, switch to the new worktree
  • --checkout <branch>: Check out an existing branch in the new worktree. Fails if that branch is already checked out in another worktree. Use this when the branch already exists in the repository but is not currently active.
  • --base <worktree>: Create the new worktree as a new branch starting at the given worktree's current commit. Use this to branch off work-in-progress from another worktree, even if its branch is already checked out. Cannot be combined with --checkout.
  • -f, --force: Skip the confirmation prompt when pruning worktrees

Hooks

The hook system is wtree's core feature. Define shell commands that run automatically during worktree lifecycle events.

Local Hooks

When you clone a repository with wt clone, a customisble template .wtree/hooks.toml is created:

Global Default Hooks

Define default hooks that apply to all new repositories:

mkdir -p ~/.wtree
cat >~/.wtree/default-hooks.toml << 'EOF'[create]pre = []post = ["cp \"$WT_HUB_ROOT/main/.env\" \"$WT_WORKTREE_PATH/.env\""][switch]pre = []post = [][remove]pre = []post = []EOF

When you run wt clone, the tool will:

  1. Check if ~/.wtree/default-hooks.toml exists
  2. If it exists, copy its content as the new repository's .wtree/hooks.toml
  3. If it doesn't exist, use the built-in template with commented examples

Environment Variables

Hooks receive full context via environment variables:

VariableDescriptionAvailable in
WT_COMMANDCommand name (create/switch/remove)All hooks
WT_WORKTREE_NAMEName of the target worktreeAll hooks
WT_WORKTREE_PATHAbsolute path to target worktreeAll hooks
WT_HUB_ROOTRepo root: hub root (parent of .bare) in bare layout, main worktree in standard layoutAll hooks
WT_BRANCHBranch name (if specified)create only

In the standard layout WT_HUB_ROOT is the main worktree path rather than the parent of .bare; the variable keeps its name for backward compatibility, but its meaning is the repo root in the active layout.

Execution Model

PhaseWorking DirectoryOn Failure
Pre-hooksRepo root (hub root / main worktree)Command aborted
Post-hooksTarget worktree directoryWarning logged, command completes

This design lets you:

  • Use pre-hooks as gates (validate branch names, check prerequisites)
  • Use post-hooks for setup (install deps, copy files) without blocking on failures

Real-World Examples

Node.js project with shared environment:

[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]
[switch]
post = ["npm install"]

Python project with virtual environments:

[create]
post = [
"python -m venv .venv",
"source .venv/bin/activate && pip install -r requirements.txt"
]
[switch]
post = ["source .venv/bin/activate"]

Validate branch naming convention:

[create]
pre = ["[[ \"$WT_WORKTREE_NAME\" =~ ^(feature|fix|hotfix)- ]]"]
post = []

Development

cargo build # debug build
cargo build --release # release build
cargo test# run tests

Install from source

git clone https://github.com/imqdee/wtree.git
cd wtree
cargo build --release
cp target/release/wt ~/.local/bin/ # or anywhere in your PATH

Development Git Hooks

This project uses lefthook for git hooks.

# Install lefthook (macOS)
brew install lefthook
# Install hooks
lefthook install

Hooks run automatically on commit (fmt, clippy) and push (test, build).

License

MIT

About

CLI tool for managing git worktrees with powerful workflow automation, and AI support

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - imqdee/wtree: CLI tool for managing git worktrees with powerful workflow automation, and AI support · GitHub
Skip to content
This repository was archived by the owner on Jul 28, 2026. It is now read-only.

Latest commit

History

33 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

wtree

A CLI tool for managing git worktrees with powerful workflow automation, on both bare-hub and standard repositories.

Git worktrees let you work on multiple branches simultaneously in separate directories. wtree wraps git worktree with a lifecycle hook system that automates your workflow—install dependencies, copy environment files, run setup scripts—all triggered automatically when you create, switch, or remove worktrees.

It works in two layouts (see Layouts): the original bare-hub layout created by wt clone, and any standard cloned repository adopted with wt init.

Why wtree?

Workflow Automation via Hooks

Most worktree tools stop at git worktree add. wtree goes further with a two-phase hook system that automates your entire development workflow:

# .wtree/hooks.toml
[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]

Every time you create a new worktree, your environment is automatically set up. Switch to an existing worktree? Dependencies are synced. No manual steps, no forgotten setup.

Installation

Cargo

cargo install wtree

Shell Setup

Add to your .bashrc or .zshrc:

# Basheval"$(wt shell-init bash)"# Zsheval"$(wt shell-init zsh)"

Breaking change in v0.7.0: the shell-integration command moved from wt init <shell> to wt shell-init <shell>. wt init (no shell argument) now adopts a standard repository (see Layouts). Update your .bashrc/.zshrc accordingly. The emitted shell function is otherwise unchanged.

Layouts

wtree detects your repository layout automatically and behaves identically across both.

Bare-hub layout. Created by wt clone <url>, which clones into <repo>/.bare and places each worktree as a sibling directory (<repo>/<name>). State and hooks live in <repo>/.wtree/. This is the original layout and is unchanged.

Standard layout. Any ordinary cloned repository. Adopt it with wt init from inside the repo. Worktrees are created under .claude/worktrees/<name>/ by default, state and hooks live in .git/wtree/, and the worktree directory is added to .gitignore automatically. wt create also lazily initializes a never-adopted standard repo on first use, so wt init is optional.

cd my-cloned-repo
wt init # adopt this repo (state dir, hooks template, gitignore entry)
wt create feature-x # creates .claude/worktrees/feature-x/

Override where standard-layout worktrees are created with a worktree_base entry in .git/wtree/config.toml (relative paths resolve against the repo root, absolute paths are used as-is):

# .git/wtree/config.tomlworktree_base = "../my-worktrees"

Usage

CommandDescription
wt clone <url> [-switch]Clone repo as bare with default branch worktree
wt initAdopt the current standard repo for wtree
wt create <name> [--checkout branch] [--base worktree] [-s]Create new worktree (alias: c)
wt switch <name>Switch to worktree (alias: sw)
wt listList all worktrees (alias: ls)
wt remove <name>...Remove one or more worktrees (alias: rm)
wt prune [-f]Remove all worktrees except the default (alias: p)

Examples

# Clone a repository
wt clone git@github.com:user/repo.git
wt clone git@github.com:user/repo.git -s # clone and switch to default branch# Create worktrees
wt create feature-auth # new worktree from bare repo HEAD
wt create hotfix --checkout main # check out existing branch 'main' in new worktree
wt create feature-ui -s # create and switch to the new worktree
wt create fix-123 --base feature-auth # branch off 'feature-auth' worktree's current commit# Switch between worktrees
wt switch main
wt sw feature-auth
# List and remove
wt ls
wt rm feature-auth # remove single worktree
wt rm feature-one feature-two # remove multiple worktrees# Prune all non-default worktrees
wt prune # interactive confirmation
wt prune -f # skip confirmation

Flags

  • -s, --switch: After clone/create, switch to the new worktree
  • --checkout <branch>: Check out an existing branch in the new worktree. Fails if that branch is already checked out in another worktree. Use this when the branch already exists in the repository but is not currently active.
  • --base <worktree>: Create the new worktree as a new branch starting at the given worktree's current commit. Use this to branch off work-in-progress from another worktree, even if its branch is already checked out. Cannot be combined with --checkout.
  • -f, --force: Skip the confirmation prompt when pruning worktrees

Hooks

The hook system is wtree's core feature. Define shell commands that run automatically during worktree lifecycle events.

Local Hooks

When you clone a repository with wt clone, a customisble template .wtree/hooks.toml is created:

Global Default Hooks

Define default hooks that apply to all new repositories:

mkdir -p ~/.wtree
cat >~/.wtree/default-hooks.toml << 'EOF'[create]pre = []post = ["cp \"$WT_HUB_ROOT/main/.env\" \"$WT_WORKTREE_PATH/.env\""][switch]pre = []post = [][remove]pre = []post = []EOF

When you run wt clone, the tool will:

  1. Check if ~/.wtree/default-hooks.toml exists
  2. If it exists, copy its content as the new repository's .wtree/hooks.toml
  3. If it doesn't exist, use the built-in template with commented examples

Environment Variables

Hooks receive full context via environment variables:

VariableDescriptionAvailable in
WT_COMMANDCommand name (create/switch/remove)All hooks
WT_WORKTREE_NAMEName of the target worktreeAll hooks
WT_WORKTREE_PATHAbsolute path to target worktreeAll hooks
WT_HUB_ROOTRepo root: hub root (parent of .bare) in bare layout, main worktree in standard layoutAll hooks
WT_BRANCHBranch name (if specified)create only

In the standard layout WT_HUB_ROOT is the main worktree path rather than the parent of .bare; the variable keeps its name for backward compatibility, but its meaning is the repo root in the active layout.

Execution Model

PhaseWorking DirectoryOn Failure
Pre-hooksRepo root (hub root / main worktree)Command aborted
Post-hooksTarget worktree directoryWarning logged, command completes

This design lets you:

  • Use pre-hooks as gates (validate branch names, check prerequisites)
  • Use post-hooks for setup (install deps, copy files) without blocking on failures

Real-World Examples

Node.js project with shared environment:

[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]
[switch]
post = ["npm install"]

Python project with virtual environments:

[create]
post = [
"python -m venv .venv",
"source .venv/bin/activate && pip install -r requirements.txt"
]
[switch]
post = ["source .venv/bin/activate"]

Validate branch naming convention:

[create]
pre = ["[[ \"$WT_WORKTREE_NAME\" =~ ^(feature|fix|hotfix)- ]]"]
post = []

Development

cargo build # debug build
cargo build --release # release build
cargo test# run tests

Install from source

git clone https://github.com/imqdee/wtree.git
cd wtree
cargo build --release
cp target/release/wt ~/.local/bin/ # or anywhere in your PATH

Development Git Hooks

This project uses lefthook for git hooks.

# Install lefthook (macOS)
brew install lefthook
# Install hooks
lefthook install

Hooks run automatically on commit (fmt, clippy) and push (test, build).

License

MIT

About

CLI tool for managing git worktrees with powerful workflow automation, and AI support

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - imqdee/wtree: CLI tool for managing git worktrees with powerful workflow automation, and AI support · GitHub
Skip to content
This repository was archived by the owner on Jul 28, 2026. It is now read-only.

Latest commit

History

33 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

wtree

A CLI tool for managing git worktrees with powerful workflow automation, on both bare-hub and standard repositories.

Git worktrees let you work on multiple branches simultaneously in separate directories. wtree wraps git worktree with a lifecycle hook system that automates your workflow—install dependencies, copy environment files, run setup scripts—all triggered automatically when you create, switch, or remove worktrees.

It works in two layouts (see Layouts): the original bare-hub layout created by wt clone, and any standard cloned repository adopted with wt init.

Why wtree?

Workflow Automation via Hooks

Most worktree tools stop at git worktree add. wtree goes further with a two-phase hook system that automates your entire development workflow:

# .wtree/hooks.toml
[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]

Every time you create a new worktree, your environment is automatically set up. Switch to an existing worktree? Dependencies are synced. No manual steps, no forgotten setup.

Installation

Cargo

cargo install wtree

Shell Setup

Add to your .bashrc or .zshrc:

# Basheval"$(wt shell-init bash)"# Zsheval"$(wt shell-init zsh)"

Breaking change in v0.7.0: the shell-integration command moved from wt init <shell> to wt shell-init <shell>. wt init (no shell argument) now adopts a standard repository (see Layouts). Update your .bashrc/.zshrc accordingly. The emitted shell function is otherwise unchanged.

Layouts

wtree detects your repository layout automatically and behaves identically across both.

Bare-hub layout. Created by wt clone <url>, which clones into <repo>/.bare and places each worktree as a sibling directory (<repo>/<name>). State and hooks live in <repo>/.wtree/. This is the original layout and is unchanged.

Standard layout. Any ordinary cloned repository. Adopt it with wt init from inside the repo. Worktrees are created under .claude/worktrees/<name>/ by default, state and hooks live in .git/wtree/, and the worktree directory is added to .gitignore automatically. wt create also lazily initializes a never-adopted standard repo on first use, so wt init is optional.

cd my-cloned-repo
wt init # adopt this repo (state dir, hooks template, gitignore entry)
wt create feature-x # creates .claude/worktrees/feature-x/

Override where standard-layout worktrees are created with a worktree_base entry in .git/wtree/config.toml (relative paths resolve against the repo root, absolute paths are used as-is):

# .git/wtree/config.tomlworktree_base = "../my-worktrees"

Usage

CommandDescription
wt clone <url> [-switch]Clone repo as bare with default branch worktree
wt initAdopt the current standard repo for wtree
wt create <name> [--checkout branch] [--base worktree] [-s]Create new worktree (alias: c)
wt switch <name>Switch to worktree (alias: sw)
wt listList all worktrees (alias: ls)
wt remove <name>...Remove one or more worktrees (alias: rm)
wt prune [-f]Remove all worktrees except the default (alias: p)

Examples

# Clone a repository
wt clone git@github.com:user/repo.git
wt clone git@github.com:user/repo.git -s # clone and switch to default branch# Create worktrees
wt create feature-auth # new worktree from bare repo HEAD
wt create hotfix --checkout main # check out existing branch 'main' in new worktree
wt create feature-ui -s # create and switch to the new worktree
wt create fix-123 --base feature-auth # branch off 'feature-auth' worktree's current commit# Switch between worktrees
wt switch main
wt sw feature-auth
# List and remove
wt ls
wt rm feature-auth # remove single worktree
wt rm feature-one feature-two # remove multiple worktrees# Prune all non-default worktrees
wt prune # interactive confirmation
wt prune -f # skip confirmation

Flags

  • -s, --switch: After clone/create, switch to the new worktree
  • --checkout <branch>: Check out an existing branch in the new worktree. Fails if that branch is already checked out in another worktree. Use this when the branch already exists in the repository but is not currently active.
  • --base <worktree>: Create the new worktree as a new branch starting at the given worktree's current commit. Use this to branch off work-in-progress from another worktree, even if its branch is already checked out. Cannot be combined with --checkout.
  • -f, --force: Skip the confirmation prompt when pruning worktrees

Hooks

The hook system is wtree's core feature. Define shell commands that run automatically during worktree lifecycle events.

Local Hooks

When you clone a repository with wt clone, a customisble template .wtree/hooks.toml is created:

Global Default Hooks

Define default hooks that apply to all new repositories:

mkdir -p ~/.wtree
cat >~/.wtree/default-hooks.toml << 'EOF'[create]pre = []post = ["cp \"$WT_HUB_ROOT/main/.env\" \"$WT_WORKTREE_PATH/.env\""][switch]pre = []post = [][remove]pre = []post = []EOF

When you run wt clone, the tool will:

  1. Check if ~/.wtree/default-hooks.toml exists
  2. If it exists, copy its content as the new repository's .wtree/hooks.toml
  3. If it doesn't exist, use the built-in template with commented examples

Environment Variables

Hooks receive full context via environment variables:

VariableDescriptionAvailable in
WT_COMMANDCommand name (create/switch/remove)All hooks
WT_WORKTREE_NAMEName of the target worktreeAll hooks
WT_WORKTREE_PATHAbsolute path to target worktreeAll hooks
WT_HUB_ROOTRepo root: hub root (parent of .bare) in bare layout, main worktree in standard layoutAll hooks
WT_BRANCHBranch name (if specified)create only

In the standard layout WT_HUB_ROOT is the main worktree path rather than the parent of .bare; the variable keeps its name for backward compatibility, but its meaning is the repo root in the active layout.

Execution Model

PhaseWorking DirectoryOn Failure
Pre-hooksRepo root (hub root / main worktree)Command aborted
Post-hooksTarget worktree directoryWarning logged, command completes

This design lets you:

  • Use pre-hooks as gates (validate branch names, check prerequisites)
  • Use post-hooks for setup (install deps, copy files) without blocking on failures

Real-World Examples

Node.js project with shared environment:

[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]
[switch]
post = ["npm install"]

Python project with virtual environments:

[create]
post = [
"python -m venv .venv",
"source .venv/bin/activate && pip install -r requirements.txt"
]
[switch]
post = ["source .venv/bin/activate"]

Validate branch naming convention:

[create]
pre = ["[[ \"$WT_WORKTREE_NAME\" =~ ^(feature|fix|hotfix)- ]]"]
post = []

Development

cargo build # debug build
cargo build --release # release build
cargo test# run tests

Install from source

git clone https://github.com/imqdee/wtree.git
cd wtree
cargo build --release
cp target/release/wt ~/.local/bin/ # or anywhere in your PATH

Development Git Hooks

This project uses lefthook for git hooks.

# Install lefthook (macOS)
brew install lefthook
# Install hooks
lefthook install

Hooks run automatically on commit (fmt, clippy) and push (test, build).

License

MIT

About

CLI tool for managing git worktrees with powerful workflow automation, and AI support

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - imqdee/wtree: CLI tool for managing git worktrees with powerful workflow automation, and AI support · GitHub
Skip to content
This repository was archived by the owner on Jul 28, 2026. It is now read-only.

Latest commit

History

33 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

wtree

A CLI tool for managing git worktrees with powerful workflow automation, on both bare-hub and standard repositories.

Git worktrees let you work on multiple branches simultaneously in separate directories. wtree wraps git worktree with a lifecycle hook system that automates your workflow—install dependencies, copy environment files, run setup scripts—all triggered automatically when you create, switch, or remove worktrees.

It works in two layouts (see Layouts): the original bare-hub layout created by wt clone, and any standard cloned repository adopted with wt init.

Why wtree?

Workflow Automation via Hooks

Most worktree tools stop at git worktree add. wtree goes further with a two-phase hook system that automates your entire development workflow:

# .wtree/hooks.toml
[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]

Every time you create a new worktree, your environment is automatically set up. Switch to an existing worktree? Dependencies are synced. No manual steps, no forgotten setup.

Installation

Cargo

cargo install wtree

Shell Setup

Add to your .bashrc or .zshrc:

# Basheval"$(wt shell-init bash)"# Zsheval"$(wt shell-init zsh)"

Breaking change in v0.7.0: the shell-integration command moved from wt init <shell> to wt shell-init <shell>. wt init (no shell argument) now adopts a standard repository (see Layouts). Update your .bashrc/.zshrc accordingly. The emitted shell function is otherwise unchanged.

Layouts

wtree detects your repository layout automatically and behaves identically across both.

Bare-hub layout. Created by wt clone <url>, which clones into <repo>/.bare and places each worktree as a sibling directory (<repo>/<name>). State and hooks live in <repo>/.wtree/. This is the original layout and is unchanged.

Standard layout. Any ordinary cloned repository. Adopt it with wt init from inside the repo. Worktrees are created under .claude/worktrees/<name>/ by default, state and hooks live in .git/wtree/, and the worktree directory is added to .gitignore automatically. wt create also lazily initializes a never-adopted standard repo on first use, so wt init is optional.

cd my-cloned-repo
wt init # adopt this repo (state dir, hooks template, gitignore entry)
wt create feature-x # creates .claude/worktrees/feature-x/

Override where standard-layout worktrees are created with a worktree_base entry in .git/wtree/config.toml (relative paths resolve against the repo root, absolute paths are used as-is):

# .git/wtree/config.tomlworktree_base = "../my-worktrees"

Usage

CommandDescription
wt clone <url> [-switch]Clone repo as bare with default branch worktree
wt initAdopt the current standard repo for wtree
wt create <name> [--checkout branch] [--base worktree] [-s]Create new worktree (alias: c)
wt switch <name>Switch to worktree (alias: sw)
wt listList all worktrees (alias: ls)
wt remove <name>...Remove one or more worktrees (alias: rm)
wt prune [-f]Remove all worktrees except the default (alias: p)

Examples

# Clone a repository
wt clone git@github.com:user/repo.git
wt clone git@github.com:user/repo.git -s # clone and switch to default branch# Create worktrees
wt create feature-auth # new worktree from bare repo HEAD
wt create hotfix --checkout main # check out existing branch 'main' in new worktree
wt create feature-ui -s # create and switch to the new worktree
wt create fix-123 --base feature-auth # branch off 'feature-auth' worktree's current commit# Switch between worktrees
wt switch main
wt sw feature-auth
# List and remove
wt ls
wt rm feature-auth # remove single worktree
wt rm feature-one feature-two # remove multiple worktrees# Prune all non-default worktrees
wt prune # interactive confirmation
wt prune -f # skip confirmation

Flags

  • -s, --switch: After clone/create, switch to the new worktree
  • --checkout <branch>: Check out an existing branch in the new worktree. Fails if that branch is already checked out in another worktree. Use this when the branch already exists in the repository but is not currently active.
  • --base <worktree>: Create the new worktree as a new branch starting at the given worktree's current commit. Use this to branch off work-in-progress from another worktree, even if its branch is already checked out. Cannot be combined with --checkout.
  • -f, --force: Skip the confirmation prompt when pruning worktrees

Hooks

The hook system is wtree's core feature. Define shell commands that run automatically during worktree lifecycle events.

Local Hooks

When you clone a repository with wt clone, a customisble template .wtree/hooks.toml is created:

Global Default Hooks

Define default hooks that apply to all new repositories:

mkdir -p ~/.wtree
cat >~/.wtree/default-hooks.toml << 'EOF'[create]pre = []post = ["cp \"$WT_HUB_ROOT/main/.env\" \"$WT_WORKTREE_PATH/.env\""][switch]pre = []post = [][remove]pre = []post = []EOF

When you run wt clone, the tool will:

  1. Check if ~/.wtree/default-hooks.toml exists
  2. If it exists, copy its content as the new repository's .wtree/hooks.toml
  3. If it doesn't exist, use the built-in template with commented examples

Environment Variables

Hooks receive full context via environment variables:

VariableDescriptionAvailable in
WT_COMMANDCommand name (create/switch/remove)All hooks
WT_WORKTREE_NAMEName of the target worktreeAll hooks
WT_WORKTREE_PATHAbsolute path to target worktreeAll hooks
WT_HUB_ROOTRepo root: hub root (parent of .bare) in bare layout, main worktree in standard layoutAll hooks
WT_BRANCHBranch name (if specified)create only

In the standard layout WT_HUB_ROOT is the main worktree path rather than the parent of .bare; the variable keeps its name for backward compatibility, but its meaning is the repo root in the active layout.

Execution Model

PhaseWorking DirectoryOn Failure
Pre-hooksRepo root (hub root / main worktree)Command aborted
Post-hooksTarget worktree directoryWarning logged, command completes

This design lets you:

  • Use pre-hooks as gates (validate branch names, check prerequisites)
  • Use post-hooks for setup (install deps, copy files) without blocking on failures

Real-World Examples

Node.js project with shared environment:

[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]
[switch]
post = ["npm install"]

Python project with virtual environments:

[create]
post = [
"python -m venv .venv",
"source .venv/bin/activate && pip install -r requirements.txt"
]
[switch]
post = ["source .venv/bin/activate"]

Validate branch naming convention:

[create]
pre = ["[[ \"$WT_WORKTREE_NAME\" =~ ^(feature|fix|hotfix)- ]]"]
post = []

Development

cargo build # debug build
cargo build --release # release build
cargo test# run tests

Install from source

git clone https://github.com/imqdee/wtree.git
cd wtree
cargo build --release
cp target/release/wt ~/.local/bin/ # or anywhere in your PATH

Development Git Hooks

This project uses lefthook for git hooks.

# Install lefthook (macOS)
brew install lefthook
# Install hooks
lefthook install

Hooks run automatically on commit (fmt, clippy) and push (test, build).

License

MIT

About

CLI tool for managing git worktrees with powerful workflow automation, and AI support

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - imqdee/wtree: CLI tool for managing git worktrees with powerful workflow automation, and AI support · GitHub
Skip to content
This repository was archived by the owner on Jul 28, 2026. It is now read-only.

Latest commit

History

33 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

wtree

A CLI tool for managing git worktrees with powerful workflow automation, on both bare-hub and standard repositories.

Git worktrees let you work on multiple branches simultaneously in separate directories. wtree wraps git worktree with a lifecycle hook system that automates your workflow—install dependencies, copy environment files, run setup scripts—all triggered automatically when you create, switch, or remove worktrees.

It works in two layouts (see Layouts): the original bare-hub layout created by wt clone, and any standard cloned repository adopted with wt init.

Why wtree?

Workflow Automation via Hooks

Most worktree tools stop at git worktree add. wtree goes further with a two-phase hook system that automates your entire development workflow:

# .wtree/hooks.toml
[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]

Every time you create a new worktree, your environment is automatically set up. Switch to an existing worktree? Dependencies are synced. No manual steps, no forgotten setup.

Installation

Cargo

cargo install wtree

Shell Setup

Add to your .bashrc or .zshrc:

# Basheval"$(wt shell-init bash)"# Zsheval"$(wt shell-init zsh)"

Breaking change in v0.7.0: the shell-integration command moved from wt init <shell> to wt shell-init <shell>. wt init (no shell argument) now adopts a standard repository (see Layouts). Update your .bashrc/.zshrc accordingly. The emitted shell function is otherwise unchanged.

Layouts

wtree detects your repository layout automatically and behaves identically across both.

Bare-hub layout. Created by wt clone <url>, which clones into <repo>/.bare and places each worktree as a sibling directory (<repo>/<name>). State and hooks live in <repo>/.wtree/. This is the original layout and is unchanged.

Standard layout. Any ordinary cloned repository. Adopt it with wt init from inside the repo. Worktrees are created under .claude/worktrees/<name>/ by default, state and hooks live in .git/wtree/, and the worktree directory is added to .gitignore automatically. wt create also lazily initializes a never-adopted standard repo on first use, so wt init is optional.

cd my-cloned-repo
wt init # adopt this repo (state dir, hooks template, gitignore entry)
wt create feature-x # creates .claude/worktrees/feature-x/

Override where standard-layout worktrees are created with a worktree_base entry in .git/wtree/config.toml (relative paths resolve against the repo root, absolute paths are used as-is):

# .git/wtree/config.tomlworktree_base = "../my-worktrees"

Usage

CommandDescription
wt clone <url> [-switch]Clone repo as bare with default branch worktree
wt initAdopt the current standard repo for wtree
wt create <name> [--checkout branch] [--base worktree] [-s]Create new worktree (alias: c)
wt switch <name>Switch to worktree (alias: sw)
wt listList all worktrees (alias: ls)
wt remove <name>...Remove one or more worktrees (alias: rm)
wt prune [-f]Remove all worktrees except the default (alias: p)

Examples

# Clone a repository
wt clone git@github.com:user/repo.git
wt clone git@github.com:user/repo.git -s # clone and switch to default branch# Create worktrees
wt create feature-auth # new worktree from bare repo HEAD
wt create hotfix --checkout main # check out existing branch 'main' in new worktree
wt create feature-ui -s # create and switch to the new worktree
wt create fix-123 --base feature-auth # branch off 'feature-auth' worktree's current commit# Switch between worktrees
wt switch main
wt sw feature-auth
# List and remove
wt ls
wt rm feature-auth # remove single worktree
wt rm feature-one feature-two # remove multiple worktrees# Prune all non-default worktrees
wt prune # interactive confirmation
wt prune -f # skip confirmation

Flags

  • -s, --switch: After clone/create, switch to the new worktree
  • --checkout <branch>: Check out an existing branch in the new worktree. Fails if that branch is already checked out in another worktree. Use this when the branch already exists in the repository but is not currently active.
  • --base <worktree>: Create the new worktree as a new branch starting at the given worktree's current commit. Use this to branch off work-in-progress from another worktree, even if its branch is already checked out. Cannot be combined with --checkout.
  • -f, --force: Skip the confirmation prompt when pruning worktrees

Hooks

The hook system is wtree's core feature. Define shell commands that run automatically during worktree lifecycle events.

Local Hooks

When you clone a repository with wt clone, a customisble template .wtree/hooks.toml is created:

Global Default Hooks

Define default hooks that apply to all new repositories:

mkdir -p ~/.wtree
cat >~/.wtree/default-hooks.toml << 'EOF'[create]pre = []post = ["cp \"$WT_HUB_ROOT/main/.env\" \"$WT_WORKTREE_PATH/.env\""][switch]pre = []post = [][remove]pre = []post = []EOF

When you run wt clone, the tool will:

  1. Check if ~/.wtree/default-hooks.toml exists
  2. If it exists, copy its content as the new repository's .wtree/hooks.toml
  3. If it doesn't exist, use the built-in template with commented examples

Environment Variables

Hooks receive full context via environment variables:

VariableDescriptionAvailable in
WT_COMMANDCommand name (create/switch/remove)All hooks
WT_WORKTREE_NAMEName of the target worktreeAll hooks
WT_WORKTREE_PATHAbsolute path to target worktreeAll hooks
WT_HUB_ROOTRepo root: hub root (parent of .bare) in bare layout, main worktree in standard layoutAll hooks
WT_BRANCHBranch name (if specified)create only

In the standard layout WT_HUB_ROOT is the main worktree path rather than the parent of .bare; the variable keeps its name for backward compatibility, but its meaning is the repo root in the active layout.

Execution Model

PhaseWorking DirectoryOn Failure
Pre-hooksRepo root (hub root / main worktree)Command aborted
Post-hooksTarget worktree directoryWarning logged, command completes

This design lets you:

  • Use pre-hooks as gates (validate branch names, check prerequisites)
  • Use post-hooks for setup (install deps, copy files) without blocking on failures

Real-World Examples

Node.js project with shared environment:

[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]
[switch]
post = ["npm install"]

Python project with virtual environments:

[create]
post = [
"python -m venv .venv",
"source .venv/bin/activate && pip install -r requirements.txt"
]
[switch]
post = ["source .venv/bin/activate"]

Validate branch naming convention:

[create]
pre = ["[[ \"$WT_WORKTREE_NAME\" =~ ^(feature|fix|hotfix)- ]]"]
post = []

Development

cargo build # debug build
cargo build --release # release build
cargo test# run tests

Install from source

git clone https://github.com/imqdee/wtree.git
cd wtree
cargo build --release
cp target/release/wt ~/.local/bin/ # or anywhere in your PATH

Development Git Hooks

This project uses lefthook for git hooks.

# Install lefthook (macOS)
brew install lefthook
# Install hooks
lefthook install

Hooks run automatically on commit (fmt, clippy) and push (test, build).

License

MIT

About

CLI tool for managing git worktrees with powerful workflow automation, and AI support

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - imqdee/wtree: CLI tool for managing git worktrees with powerful workflow automation, and AI support · GitHub
Skip to content
This repository was archived by the owner on Jul 28, 2026. It is now read-only.

Latest commit

History

33 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

wtree

A CLI tool for managing git worktrees with powerful workflow automation, on both bare-hub and standard repositories.

Git worktrees let you work on multiple branches simultaneously in separate directories. wtree wraps git worktree with a lifecycle hook system that automates your workflow—install dependencies, copy environment files, run setup scripts—all triggered automatically when you create, switch, or remove worktrees.

It works in two layouts (see Layouts): the original bare-hub layout created by wt clone, and any standard cloned repository adopted with wt init.

Why wtree?

Workflow Automation via Hooks

Most worktree tools stop at git worktree add. wtree goes further with a two-phase hook system that automates your entire development workflow:

# .wtree/hooks.toml
[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]

Every time you create a new worktree, your environment is automatically set up. Switch to an existing worktree? Dependencies are synced. No manual steps, no forgotten setup.

Installation

Cargo

cargo install wtree

Shell Setup

Add to your .bashrc or .zshrc:

# Basheval"$(wt shell-init bash)"# Zsheval"$(wt shell-init zsh)"

Breaking change in v0.7.0: the shell-integration command moved from wt init <shell> to wt shell-init <shell>. wt init (no shell argument) now adopts a standard repository (see Layouts). Update your .bashrc/.zshrc accordingly. The emitted shell function is otherwise unchanged.

Layouts

wtree detects your repository layout automatically and behaves identically across both.

Bare-hub layout. Created by wt clone <url>, which clones into <repo>/.bare and places each worktree as a sibling directory (<repo>/<name>). State and hooks live in <repo>/.wtree/. This is the original layout and is unchanged.

Standard layout. Any ordinary cloned repository. Adopt it with wt init from inside the repo. Worktrees are created under .claude/worktrees/<name>/ by default, state and hooks live in .git/wtree/, and the worktree directory is added to .gitignore automatically. wt create also lazily initializes a never-adopted standard repo on first use, so wt init is optional.

cd my-cloned-repo
wt init # adopt this repo (state dir, hooks template, gitignore entry)
wt create feature-x # creates .claude/worktrees/feature-x/

Override where standard-layout worktrees are created with a worktree_base entry in .git/wtree/config.toml (relative paths resolve against the repo root, absolute paths are used as-is):

# .git/wtree/config.tomlworktree_base = "../my-worktrees"

Usage

CommandDescription
wt clone <url> [-switch]Clone repo as bare with default branch worktree
wt initAdopt the current standard repo for wtree
wt create <name> [--checkout branch] [--base worktree] [-s]Create new worktree (alias: c)
wt switch <name>Switch to worktree (alias: sw)
wt listList all worktrees (alias: ls)
wt remove <name>...Remove one or more worktrees (alias: rm)
wt prune [-f]Remove all worktrees except the default (alias: p)

Examples

# Clone a repository
wt clone git@github.com:user/repo.git
wt clone git@github.com:user/repo.git -s # clone and switch to default branch# Create worktrees
wt create feature-auth # new worktree from bare repo HEAD
wt create hotfix --checkout main # check out existing branch 'main' in new worktree
wt create feature-ui -s # create and switch to the new worktree
wt create fix-123 --base feature-auth # branch off 'feature-auth' worktree's current commit# Switch between worktrees
wt switch main
wt sw feature-auth
# List and remove
wt ls
wt rm feature-auth # remove single worktree
wt rm feature-one feature-two # remove multiple worktrees# Prune all non-default worktrees
wt prune # interactive confirmation
wt prune -f # skip confirmation

Flags

  • -s, --switch: After clone/create, switch to the new worktree
  • --checkout <branch>: Check out an existing branch in the new worktree. Fails if that branch is already checked out in another worktree. Use this when the branch already exists in the repository but is not currently active.
  • --base <worktree>: Create the new worktree as a new branch starting at the given worktree's current commit. Use this to branch off work-in-progress from another worktree, even if its branch is already checked out. Cannot be combined with --checkout.
  • -f, --force: Skip the confirmation prompt when pruning worktrees

Hooks

The hook system is wtree's core feature. Define shell commands that run automatically during worktree lifecycle events.

Local Hooks

When you clone a repository with wt clone, a customisble template .wtree/hooks.toml is created:

Global Default Hooks

Define default hooks that apply to all new repositories:

mkdir -p ~/.wtree
cat >~/.wtree/default-hooks.toml << 'EOF'[create]pre = []post = ["cp \"$WT_HUB_ROOT/main/.env\" \"$WT_WORKTREE_PATH/.env\""][switch]pre = []post = [][remove]pre = []post = []EOF

When you run wt clone, the tool will:

  1. Check if ~/.wtree/default-hooks.toml exists
  2. If it exists, copy its content as the new repository's .wtree/hooks.toml
  3. If it doesn't exist, use the built-in template with commented examples

Environment Variables

Hooks receive full context via environment variables:

VariableDescriptionAvailable in
WT_COMMANDCommand name (create/switch/remove)All hooks
WT_WORKTREE_NAMEName of the target worktreeAll hooks
WT_WORKTREE_PATHAbsolute path to target worktreeAll hooks
WT_HUB_ROOTRepo root: hub root (parent of .bare) in bare layout, main worktree in standard layoutAll hooks
WT_BRANCHBranch name (if specified)create only

In the standard layout WT_HUB_ROOT is the main worktree path rather than the parent of .bare; the variable keeps its name for backward compatibility, but its meaning is the repo root in the active layout.

Execution Model

PhaseWorking DirectoryOn Failure
Pre-hooksRepo root (hub root / main worktree)Command aborted
Post-hooksTarget worktree directoryWarning logged, command completes

This design lets you:

  • Use pre-hooks as gates (validate branch names, check prerequisites)
  • Use post-hooks for setup (install deps, copy files) without blocking on failures

Real-World Examples

Node.js project with shared environment:

[create]
post = [
"cp \"$WT_HUB_ROOT/main/.env\"\"$WT_WORKTREE_PATH/.env\"",
"npm install"
]
[switch]
post = ["npm install"]

Python project with virtual environments:

[create]
post = [
"python -m venv .venv",
"source .venv/bin/activate && pip install -r requirements.txt"
]
[switch]
post = ["source .venv/bin/activate"]

Validate branch naming convention:

[create]
pre = ["[[ \"$WT_WORKTREE_NAME\" =~ ^(feature|fix|hotfix)- ]]"]
post = []

Development

cargo build # debug build
cargo build --release # release build
cargo test# run tests

Install from source

git clone https://github.com/imqdee/wtree.git
cd wtree
cargo build --release
cp target/release/wt ~/.local/bin/ # or anywhere in your PATH

Development Git Hooks

This project uses lefthook for git hooks.

# Install lefthook (macOS)
brew install lefthook
# Install hooks
lefthook install

Hooks run automatically on commit (fmt, clippy) and push (test, build).

License

MIT

About

CLI tool for managing git worktrees with powerful workflow automation, and AI support

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages