A CLI tool for managing Git worktrees with a focus on opening them in the Cursor editor.
New to worktrees? Check out the Quick Start Guide for practical examples and common workflows.
- Interactive TUI: Fuzzy-searchable selection when arguments are omitted
- Bare Repository Support: Works with bare repositories for optimal worktree workflows
- Atomic Operations: Automatic rollback on failure for safe worktree creation
- Stash-aware: Gracefully handles dirty worktrees with stash/pop workflow
- PR Integration: Create worktrees directly from GitHub PRs or GitLab MRs
- Setup Automation: Run setup scripts automatically with trust-based security
- Trust Mode: Skip confirmation prompts for automated workflows
- Subfolder Organization: Keep worktrees organized in dedicated subdirectories
- Status Overview: Quick status check of all worktrees with git state
pnpm install -g @johnlindquist/worktreewt new <branchName> [options]Options:
-p, --path <path>: Specify a custom path for the worktree-c, --checkout: Create new branch if it doesn't exist and checkout automatically-i, --install <packageManager>: Package manager to use for installing dependencies (npm, pnpm, bun, etc.)-e, --editor <editor>: Editor to use for opening the worktree (overrides default editor)
Example:
wt new feature/login
wt new feature/chat --checkout
wt new feature/auth -p ./auth-worktree
wt new feature/deps -i pnpm
wt new feature/vscode -e codeDirty Worktree Handling: If your main worktree has uncommitted changes, you'll be prompted with options:
- Stash changes: Automatically stash before creating, restore after
- Abort: Cancel the operation
- Continue anyway: Proceed with uncommitted changes
wt setup <branchName> [options]Creates a new worktree and automatically runs setup commands from worktrees.json or .cursor/worktrees.json. This is useful for automating dependency installation, copying configuration files, or running custom setup scripts.
Options:
-p, --path <path>: Specify a custom path for the worktree-c, --checkout: Create new branch if it doesn't exist and checkout automatically-i, --install <packageManager>: Package manager to use for installing dependencies (npm, pnpm, bun, etc.)-e, --editor <editor>: Editor to use for opening the worktree (overrides default editor)-t, --trust: Trust and run setup commands without confirmation (for CI environments)
Example:
wt setup feature/new-feature
wt setup feature/quick-start -i pnpm
wt setup feature/ci-build --trust # Skip confirmation in CIwt pr [prNumber] [options]Interactive Selection: Run wt pr without a number to see a list of open PRs/MRs to choose from.
Uses the GitHub CLI (gh) or GitLab CLI (glab) to fetch the branch associated with the given Pull Request or Merge Request number directly (without switching your current branch), and creates a worktree for it.
Benefit: Your main worktree stays untouched. Commits made in the PR worktree can be pushed directly using git push to update the PR/MR.
Requires GitHub CLI (gh) or GitLab CLI (glab) to be installed and authenticated.
The tool automatically detects whether you're working with a GitHub or GitLab repository based on the remote URL.
Options:
-p, --path <path>: Specify a custom path for the worktree (defaults to<repoName>-<branchName>)-i, --install <packageManager>: Package manager to use for installing dependencies (npm, pnpm, bun, etc.)-e, --editor <editor>: Editor to use for opening the worktree (overrides default editor)-s, --setup: Run setup scripts fromworktrees.jsonor.cursor/worktrees.json
Example:
# Interactive PR selection
wt pr
# Create worktree for GitHub PR #123
wt pr 123
# Create worktree for GitLab MR #456 with deps and editor
wt pr 456 -i pnpm -e code
# Create worktree and run setup scripts
wt pr 123 --setupwt open [pathOrBranch]Interactive Selection: Run wt open without arguments to see a fuzzy-searchable list of worktrees.
Example:
wt open # Interactive selection
wt open feature/login # Open by branch name
wt open ./path/to/worktree # Open by pathwt listShows all worktrees with their status:
- Branch name or detached HEAD state
- Locked/prunable status indicators
- Main worktree marker
wt statusDisplays comprehensive status information for all worktrees:
- Git status: Clean vs dirty (uncommitted changes)
- Tracking status: Ahead/behind upstream branch
- Indicators: Main worktree, locked, prunable status
- Branch info: Current branch or detached HEAD state
Example output:
$ wt status
Worktree Status:
main β /Users/me/projects/myapp [main] [clean] [up-to-date]
feature/auth β /Users/me/projects/myapp-worktrees/feature-auth [dirty] [ahead 2]
feature/api β /Users/me/projects/myapp-worktrees/feature-api [clean] [no upstream]Status indicators:
[main]- Main worktree[clean]/[dirty]- Working tree status[up-to-date]- In sync with upstream[ahead N]- N commits ahead of upstream[behind N]- N commits behind upstream[ahead N, behind M]- Diverged from upstream[no upstream]- No tracking branch configured[locked]- Worktree is locked
wt remove [pathOrBranch] [options]Interactive Selection: Run wt remove without arguments to select a worktree to remove.
Options:
-f, --force: Force removal without confirmation
Example:
wt remove # Interactive selection
wt remove feature/login # Remove by branch name
wt remove ./path/to/worktree # Remove by path
wt remove feature/old -f # Force removewt purgeInteractive multi-select interface to remove multiple worktrees at once. The main worktree is excluded from selection.
wt extract [branchName] [options]Extracts the current (or specified) branch into a separate worktree, useful when you want to continue working on a branch in isolation.
wt merge <branchName> [options]Merge a branch from its worktree into the current branch. The command has been designed with safety in mind to prevent accidental data loss.
Safety Features:
- Checks for uncommitted changes in the target worktree by default
- Requires explicit opt-in flags for destructive operations
- Preserves the source worktree after merge by default
Options:
--auto-commit: Automatically commit uncommitted changes in the target worktree before merging-m, --message <message>: Custom commit message when using--auto-commit(defaults to auto-generated message)--remove: Remove the source worktree after successful merge (opt-in destructive cleanup)-f, --force: Force removal of worktree when used with--remove
Examples:
# Basic merge (fails if target worktree has uncommitted changes)
wt merge feature/login
# Auto-commit changes with custom message, then merge
wt merge feature/login --auto-commit -m "WIP: Login implementation"
# Merge and remove the source worktree
wt merge feature/login --remove
# Auto-commit, merge, and remove in one command
wt merge feature/login --auto-commit --remove
# Force remove worktree even if it has uncommitted changes
wt merge feature/login --remove --forceDefault Behavior Changes:
The wt merge command now follows these safer defaults:
- Dirty State Check: Fails if the target worktree has uncommitted changes (use
--auto-committo override) - Worktree Preservation: Keeps the source worktree after merge (use
--removeto clean up)
This prevents the previous destructive behavior where uncommitted changes were auto-committed with generic messages and worktrees were automatically deleted.
You can set a default editor to be used when creating new worktrees:
# Set default editor
wt config set editor <editorName>
# Examples:
wt config set editor code # Use VS Code
wt config set editor webstorm # Use WebStorm
wt config set editor cursor # Use Cursor (default)
wt config set editor none # Skip opening editor entirely
# Get current default editor
wt config get editor
# Show config file location
wt config pathThe default editor will be used when creating new worktrees unless overridden with the -e flag.
Setting the editor to none will skip opening any editor after creating a worktree, which is useful for CI/CD pipelines or scripts.
You can manually set the git provider for wt pr if auto-detection doesn't work:
# Set git provider
wt config set provider gh # GitHub CLI
wt config set provider glab # GitLab CLI
# Get current provider
wt config get providerYou can set a global directory where all worktrees will be created:
# Set default worktree directory
wt config set worktreepath <path>
# Examples:
wt config set worktreepath ~/worktrees # Use ~/worktrees
wt config set worktreepath /Users/me/dev/.wt # Use absolute path
# Get current default worktree directory
wt config get worktreepath
# Clear the setting (revert to sibling directory behavior)
wt config clear worktreepathSkip confirmation prompts for setup scripts (useful for CI/CD and automated workflows):
# Enable trust mode
wt config set trust true
# Disable trust mode (default)
wt config set trust false
# Get current trust mode setting
wt config get trustWhen trust mode is enabled, wt setup commands will execute setup scripts without confirmation prompts.
Organize worktrees in a dedicated subdirectory instead of as siblings:
# Enable subfolder mode
wt config set subfolder true
# Disable subfolder mode (default)
wt config set subfolder false
# Get current subfolder mode setting
wt config get subfolderWithout subfolder mode (default):
my-app/ # main repo
my-app-feature-auth/ # worktree (sibling)
my-app-feature-api/ # worktree (sibling)
With subfolder mode:
my-app/ # main repo
my-app-worktrees/
βββ feature-auth/ # worktree
βββ feature-api/ # worktree
Path Resolution Priority:
--pathflag (highest priority)defaultWorktreePathconfig setting (with repo namespace)- Sibling directory behavior (default fallback)
Path Collision Prevention:
When using a global worktree directory, paths are automatically namespaced by repository name to prevent collisions:
Without global path configured (default):
- Current directory:
/Users/me/projects/myrepo - Command:
wt new feature/login - Creates:
/Users/me/projects/myrepo-feature-login
With global path configured (~/worktrees):
- Current directory:
/Users/me/projects/myrepo - Command:
wt new feature/login - Creates:
~/worktrees/myrepo/feature-login
Branch Name Sanitization:
Branch names with slashes are converted to dashes for directory names:
feature/authβfeature-authhotfix/urgent-fixβhotfix-urgent-fix
This ensures uniqueness: feature/auth and hotfix/auth create different directories.
You can define setup commands in one of two locations to automatically execute them when using wt setup:
- Cursor's format:
.cursor/worktrees.jsonin the repository root - Generic format:
worktrees.jsonin the repository root
The tool checks for .cursor/worktrees.json first, then falls back to worktrees.json.
Note: Setup scripts only run when using the wt setup command. The wt new command will not execute setup scripts.
Option 1: worktrees.json (recommended for new projects):
{
"setup-worktree": [
"npm install",
"cp $ROOT_WORKTREE_PATH/.local.env .local.env",
"echo 'Setup complete'"
]
}Option 2: .cursor/worktrees.json (Cursor's native format):
[
"npm install",
"cp $ROOT_WORKTREE_PATH/.local.env .local.env",
"echo 'Setup complete'"
]Setup commands use a trust-based security model:
- Default behavior: Commands are displayed before execution and require confirmation
- Trust mode: Use
--trustflag to skip confirmation (for CI environments) - No blocklist: Unlike regex-based filtering, this model lets you run any legitimate command
# Interactive confirmation (default)
wt setup feature/new
# Trust mode for CI/scripts
wt setup feature/new --trust- Commands are executed in the new worktree directory
- The
$ROOT_WORKTREE_PATHenvironment variable is available, pointing to the main repository root - Commands run with shell execution, so complex commands and piping are supported
- If a command fails, the error is logged, but setup continues with the next command
- The setup runs after worktree creation but before dependency installation (if
--installis used)
The CLI fully supports bare repositories, which is the most efficient workflow for heavy worktree users:
# Clone as bare repository
git clone --bare git@github.com:user/repo.git repo.git
cd repo.git
# Create worktrees for different branches
wt new main -p ../main
wt new feature/auth -p ../auth
wt new hotfix/urgent -p ../urgentEach worktree is a separate working directory, while the bare repo contains only the .git data.
All worktree creation operations are atomic with automatic rollback on failure:
- If worktree creation succeeds but dependency installation fails, the worktree is automatically removed
- Stashed changes are restored in the finally block, even if an error occurs
- Failed commands are logged but don't leave the system in an inconsistent state
- Git
- Node.js
- An editor installed and available in PATH (defaults to Cursor, can be set to
noneto skip) - For
wt prcommand: GitHub CLI (gh) or GitLab CLI (glab) installed and authenticated
# Install dependencies
pnpm install
# Build
pnpm build
# Run tests
pnpm test
# Run in development mode
pnpm devThe project includes comprehensive test coverage:
# Run all tests
pnpm test
# Run with coverage
pnpm test -- --coverageThis project includes a custom slash command for Claude Code. The command is defined in .claude/commands/worktree.md and provides quick access to worktree management workflows.
Usage in Claude Code:
/worktree create three parallel features for authentication, UI, and API
# Headless operation (no editor auto-open)
wt config set editor none
# Skip confirmation prompts
wt config set trust true
# Organized directory structure
wt config set subfolder trueThe wt CLI is designed to work seamlessly with parallel AI agents (like Cursor's parallel agents feature):
- Each agent gets its own worktree
- Agents work independently without conflicts
- Changes are merged back when ready
- Setup scripts ensure consistent environments
Example workflow:
# Create worktrees for parallel tasks
wt setup task-1-auth -c
wt setup task-2-ui -c
wt setup task-3-api -c
# Check status of all tasks
wt status
# Merge completed tasks
wt merge task-1-auth --auto-commit --remove
wt merge task-2-ui --auto-commit --remove
wt merge task-3-api --auto-commit --removeSee the Quick Start Guide for more examples.
MIT