Appearance
Worktrees
Separate working directories per branch sharing one repository for parallel development without file system conflicts.
Tool Selection: Native vs. Manual Worktree Management
Before following the manual git commands in this skill, check whether your runtime provides a native worktree tool:
Claude Code: If the
EnterWorktreetool is available, use it. It handles worktree creation, branch setup, directory switching, and cleanup automatically. You can also be started with--worktree <name>which pre-configures isolation. Only fall back to the manual instructions below ifEnterWorktreeis not available or is denied in permissions.VS Code + Copilot background agents: If you are running as a background agent, the runtime automatically creates a worktree for your session. You do not need to manage worktrees manually.
OpenAI Codex (app): Worktree creation is handled by the platform. Defer to its built-in worktree management.
All other environments (Cursor, Aider, Cline, Roo, generic CLI, etc.): No native worktree tool exists. Follow the manual instructions in this skill to create and manage worktrees using git commands directly.
Decision rule: If a native tool exists, use it. If not, follow this skill's instructions. Do not duplicate effort by running manual git worktree commands when a native tool has already handled isolation.
When to use
Use worktrees when you need parallel work, isolation, or want to avoid disrupting the user's current state. Common scenarios:
- Working on a feature while reviewing a PR on another branch
- Comparing branches side-by-side
- Running risky refactors in isolation
- Multi-agent coordination where each agent needs its own branch
- Avoiding constant stash/pop cycles
For simple, single-branch tasks, working directly in the project root on the default branch is fine. Worktrees are for when you need more than one branch checked out at the same time.
The pattern
Quick reference
| Action | Command |
|---|---|
| Create | git worktree add .worktrees/<name> <name> |
| New branch | git worktree add .worktrees/<name> -b <name> origin/main |
| List | git worktree list |
| Remove | git worktree remove .worktrees/<name> |
| Prune | git worktree prune |
Core structure
The project root is a normal git checkout on the default branch (main, master, etc.). Worktrees live in a .worktrees/ directory inside the project root:
project/ # Normal checkout on default branch
├── .git/
├── .gitignore # Contains `.worktrees/`
├── .worktrees/
│ ├── feature/
│ │ └── auth/ # Worktree for feature/auth branch
│ │ ├── src/
│ │ ├── package.json
│ │ └── node_modules/
│ └── bugfix/
│ └── login-null/ # Worktree for bugfix/login-null branch
│ └── ...
├── src/ # Root working files (default branch)
├── package.json
└── node_modules/Key principles
- Root stays on default branch — The project root is a normal clone checked out to
main(or whatever the default branch is). It is never a worktree itself. - Name-path-branch identity — The worktree directory path under
.worktrees/, the worktree name, and the branch name are all the same string. No prefixes, no slug transformations.feature/authmeans directory.worktrees/feature/auth/and branchfeature/auth. - Complete isolation — Each worktree has its own working files and needs its own dependency install (
npm install,pip install, etc.) sincenode_modules,venv, and similar directories are per-worktree. - Zero conflicts — Agents and humans work in parallel without file collisions.
First-time setup
Before creating the first worktree in a project, ensure .worktrees/ is excluded from version control:
Check if
.worktrees/is already in.gitignore. If not, add it:echo '.worktrees/' >> .gitignoreCommit the
.gitignorechange if needed.
That's it. No re-cloning, no bare-repo conversion. The project stays as-is.
Creating a worktree
Required information
- Branch name — The name for both the branch and the worktree directory (e.g.,
feature/user-auth,bugfix/login-issue,quick-fix) - Base branch — Branch to create from if making a new branch (typically
origin/main) - Branch existence — Whether the branch already exists at origin or needs creation
Steps
Ensure
.worktrees/is in.gitignore(see First-time setup above).Determine branch status:
- Locally:
git branch -l <name> - At origin:
git ls-remote --heads origin <name>
- Locally:
Create the worktree:
- New branch:
git worktree add .worktrees/<name> -b <name> origin/main - Existing branch:
git worktree add .worktrees/<name> <name>
git worktree addcreates any intermediate directories automatically, so branch names with slashes (likefeature/auth) work without extra steps.- New branch:
Install dependencies —
cd .worktrees/<name>then runnpm install,pip install -r requirements.txt, or whatever the project requires. Each worktree needs its own install because dependency directories are not shared.
Naming examples
The worktree directory path, worktree name, and branch name are always the same string:
| Branch | Worktree Path |
|---|---|
feature/auth | .worktrees/feature/auth/ |
bugfix/login-null | .worktrees/bugfix/login-null/ |
experiment/new-router | .worktrees/experiment/new-router/ |
quick-fix | .worktrees/quick-fix/ |
No renaming, no slug transformation, no prefixing.
Issue-backed branches
When the work corresponds to a tracked issue, use the pattern:
issue-<zero-padded-3-digit-number>-<slug>Examples:
| Issue | Branch | Worktree Path |
|---|---|---|
| #9 | issue-009-integrate | .worktrees/issue-009-integrate/ |
| #42 | issue-042-cache-headers | .worktrees/issue-042-cache-headers/ |
| #286 | issue-286-nested-fences | .worktrees/issue-286-nested-fences/ |
Rules:
- Zero-pad issue numbers to at least 3 digits so branches sort stably in alphabetical listings (
issue-009sorts beforeissue-042, not after). - The slug describes the work (a verb or short phrase), not the artifact. Prefer
integrate,refactor,fix,auditover release names or version numbers (1.0.0is what the PR produces, not what it is). - Name-path-branch identity still holds: the full string
issue-009-integrateis the branch name, the worktree directory, and the identifier everywhere.
Working in a worktree
Once created, a worktree is a normal working directory. Run commands from inside it:
sh
cd .worktrees/feature/auth
# edit files, run tests, build, etc.
git add -A
git commit -m "Add auth middleware"
git push -u origin feature/authThe root checkout and other worktrees are unaffected by changes in this worktree.
Merging back
When work in a worktree is complete and pushed:
- Create a pull request from the worktree's branch into the default branch, or merge directly if appropriate.
- Pull changes into root (if merged directly):sh
cd /path/to/project # back to project root git pull origin main - Clean up the worktree (see below).
Removing a worktree
Required information
- Branch name — Name of the worktree/branch to remove
- Delete branch decision — Whether to delete the branch after removal
- Current location — Ensure you're not inside the worktree being removed
Steps
Verify worktree exists by running
git worktree list.Check current directory — verify you're not inside the worktree being removed (
pwd). If you are, change to the project root first.Check for uncommitted work:
- Uncommitted changes:
git -C .worktrees/<name> status --porcelain - Unpushed commits:
git log <name> --not --remotes --oneline - If either exists, warn the user before proceeding.
- Uncommitted changes:
Remove the worktree:
git worktree remove .worktrees/<name>. Use--forceonly after user confirmation if there are uncommitted changes.Delete the branch (if requested):
- Merged:
git branch -d <name> - Unmerged (force):
git branch -D <name> - Remote:
git push origin --delete <name>
- Merged:
Prune stale references:
git worktree pruneto clean up any stale worktree metadata.Verify cleanup:
git worktree listto confirm worktree removalgit branch -l <name>to confirm branch deletion
Note: <name> may contain slashes (e.g., feature/auth), which is normal. The nested directory structure under .worktrees/ is intentional.
Common issues
- Modified files error: Commit/stash changes or use
--force(loses changes) - "Branch not fully merged": Use
-Dinstead of-dafter user confirms - Remote deletion fails: May lack permissions or branch is protected
- Parent directories left behind: After removing
.worktrees/feature/auth/, the empty.worktrees/feature/directory may remain. This is harmless but can be removed manually.
Cleanup rules
- If a worktree has no changes or commits beyond the base, remove both the worktree and its branch automatically (or offer to).
- If a worktree has changes or commits, prompt the user whether to keep or remove. Keeping preserves both directory and branch. Removing deletes both and discards uncommitted work.
Important rules
- STOP and ASK if:
- Branch name not specified
- User hasn't specified whether to delete the branch
- There are unpushed commits or uncommitted changes
- Currently inside the worktree being removed
- Never remove without checking current directory first
- Warn about potential data loss before proceeding
Listing worktrees
Run git worktree list from anywhere in the repository to see all active worktrees and their branches:
/path/to/project abc1234 [main]
/path/to/project/.worktrees/feature/auth def5678 [feature/auth]
/path/to/project/.worktrees/quick-fix ghi9012 [quick-fix]To prune stale references (worktrees whose directories were deleted without git worktree remove): git worktree prune.
Trade-offs
| Approach | Pros | Cons |
|---|---|---|
| Worktrees | Full isolation, no switching | Disk space, dependency copies |
| Branch switch | Single working directory | Stash/commit needed to switch |
| Stashing | Quick context switch | Easy to lose or forget stash |