# Git Worktree Support

> Run CodeBuddy in isolated workspaces for parallel development and safe isolation.

## Overview

Git worktree allows you to have multiple working directories simultaneously within the same repository, each checked out to a different branch. CodeBuddy Code leverages this feature to provide:

- **Parallel development**: Perform experimental development without affecting the main workspace
- **Safe isolation**: All AI changes are made in a separate directory
- **Zero storage overhead**: Worktrees share Git objects without duplicating the entire repository
- **Sub-agent isolation**: Multiple AI sub-agents can work in parallel in independent worktrees
- **tmux integration**: Optionally run in a dedicated tmux session
- **Non-Git support**: SVN, Perforce, and other projects can also use worktree isolation via WorktreeCreate/WorktreeRemove hooks

## Quick Start

```bash
# Create a worktree with an auto-generated name
codebuddy --worktree

# Create a worktree with a specific name
codebuddy --worktree feature-auth

# Create a worktree based on a specific branch
codebuddy --worktree --worktree-branch origin/develop  # Based on remote develop branch
codebuddy --worktree --worktree-branch feature/foo     # Based on local feature/foo branch

# Run in a tmux session (recommended for long-running tasks)
codebuddy --worktree --tmux

# Create a worktree based on a PR/MR (for code review)
codebuddy --worktree "#123"                                    # GitHub PR number
codebuddy --worktree "https://github.com/owner/repo/pull/123" # GitHub PR URL
codebuddy --worktree "https://gitlab.com/owner/repo/-/merge_requests/456" # GitLab MR URL
codebuddy --worktree "https://cnb.woa.com/owner/repo/-/pulls/789" # CNB PR URL
```

### Creating Within a Session

After starting a CodeBuddy Code session, you can create a worktree via natural language:

```
> start a worktree
> work in a worktree
> 启动 worktree
```

The AI will automatically invoke the `EnterWorktree` tool to create an isolated working directory and switch to it.

> **Note**: This is only triggered when "worktree" is explicitly mentioned. Saying "create a branch for me" or "fix this bug" will not automatically create a worktree.

## CLI Parameters

| Parameter | Description | Example |
|:----------|:------------|:--------|
| `--worktree [name]` | Create and enter a worktree | `--worktree` or `--worktree my-feature` |
| `--worktree-branch <branch>` | Specify the base branch (requires `--worktree`) | `--worktree-branch origin/develop` or `--worktree-branch feature/foo` |
| `--tmux` | Run in a tmux session (requires tmux installed) | `--worktree --tmux` |
| `--tmux-classic` | Use classic tmux mode (without popup) | `--worktree --tmux --tmux-classic` |

## Workflow

### Creating a Worktree

When starting with the `--worktree` parameter:

1. CodeBuddy creates a new worktree under the `.codebuddy/worktrees/` directory
2. Determines the base branch:
   - If `--worktree-branch origin/xxx` is specified, uses the remote branch `origin/xxx`
   - If `--worktree-branch xxx` is specified, uses the local branch `xxx`
   - If not specified, defaults to the remote default branch (usually `origin/main` or `origin/master`)
3. Automatically creates a corresponding branch (e.g., `worktree-feature-auth`)
4. Switches the working directory to the worktree; if you started from a subdirectory of the repository, it will preferentially enter the corresponding relative subdirectory in the new worktree
5. Runs initialization (copies settings, creates symlinks, copies `.worktreeinclude` files, etc.)

**Behavior when the branch does not exist**:
- If the specified branch (remote or local) does not exist, a warning is printed and the creation falls back to the remote default branch
- The startup process is not interrupted

### Options on Exit

When you exit a worktree session, CodeBuddy detects changes and offers options:

- **Keep Worktree**: Preserve all changes and the branch for later continuation
- **Remove Worktree**: Clean up the worktree and associated branch
- **Keep but exit tmux**: (tmux mode) Preserve the worktree but close the tmux session

### Change Detection

Before exiting, CodeBuddy checks for:

- Uncommitted file changes
- Unpushed commits

If no changes are detected, the worktree is automatically cleaned up.

## Configuration

Configure worktree behavior in `settings.json`:

```json
{
  "worktree": {
    "symlinkDirectories": ["node_modules", ".next", ".cache", "dist"]
  }
}
```

### Configuration Options

| Option | Description | Default |
|:-------|:------------|:--------|
| `symlinkDirectories` | Directories to symlink from the main repository to the worktree | `[]` |

Symlinked directories avoid redundant dependency installation in each worktree, saving time and disk space.

### Syncing Local Ignored Files (.worktreeinclude)

Local configuration files like `.env.local` and `.env.development` are typically excluded by `.gitignore`, but new worktrees need them to function properly.

**Solution**: Create a `.worktreeinclude` file in the repository root listing files to copy (uses the same syntax as `.gitignore`):

```gitignore
# .worktreeinclude
# List local files to copy to new worktrees

# Environment variables
.env.local
.env.development.local
.env.test.local

# Local IDE configuration
.vscode/settings.json

# Local certificates or keys (if any)
certs/localhost.pem
```

These files are automatically copied from the main repository root each time a new worktree is created. **Files are not re-copied when reusing an existing worktree**.

> **Tip**: `.worktreeinclude` should be committed to Git so all team members benefit.

## Hook-based Worktree

By default, the worktree feature relies on the built-in `git worktree` command. For projects using SVN, Perforce, or those without version control, you can use worktree isolation by configuring **WorktreeCreate / WorktreeRemove hooks**.

### Decision Priority

```
1. WorktreeCreate hook configured? → Use hook to create (takes priority even in a Git repo)
2. In a Git repository?           → Use git worktree
3. Neither?                       → Error with a prompt to configure hooks
```

**Core rules**:
- **Hooks take priority over Git**: Once a WorktreeCreate hook is configured, all worktree operations go through the hook, even in a Git repository
- **No fallback on failure**: If the WorktreeCreate hook fails, it does not fall back to `git worktree` — it errors immediately
- **Removal failure does not block exit**: A WorktreeRemove hook failure only logs a warning and does not prevent the exit process

### Configuration

Configure in `.codebuddy/settings.json` (project-level) or `~/.codebuddy/settings.json` (global):

```json
{
    "hooks": {
        "WorktreeCreate": [
            {
                "hooks": [
                    {
                        "type": "command",
                        "command": "bash ~/.codebuddy/hooks/worktree-create.sh"
                    }
                ]
            }
        ],
        "WorktreeRemove": [
            {
                "hooks": [
                    {
                        "type": "command",
                        "command": "bash ~/.codebuddy/hooks/worktree-remove.sh"
                    }
                ]
            }
        ]
    }
}
```

The two hooks are configured independently — you can configure only WorktreeCreate without WorktreeRemove (in which case the worktree will not be automatically cleaned up on exit, and a prompt will ask you to manually delete the directory).

### Input Data (stdin)

Hook scripts receive JSON-formatted context data via **stdin**.

**WorktreeCreate input**:

```json
{
    "hook_event_name": "WorktreeCreate",
    "session_id": "abc123def456",
    "cwd": "/Users/user/project",
    "transcript_path": "/Users/user/.codebuddy/sessions/abc123/transcript.md",
    "name": "feature-auth"
}
```

| Field | Description |
|:------|:------------|
| `name` | Worktree name (user-specified or auto-generated) |
| `cwd` | Current working directory |
| `session_id` | Current session ID |
| `transcript_path` | Path to the conversation transcript file |

**WorktreeRemove input**:

```json
{
    "hook_event_name": "WorktreeRemove",
    "session_id": "abc123def456",
    "cwd": "/Users/user/project",
    "transcript_path": "/Users/user/.codebuddy/sessions/abc123/transcript.md",
    "worktree_path": "/tmp/codebuddy-worktrees/feature-auth"
}
```

| Field | Description |
|:------|:------------|
| `worktree_path` | Absolute path of the worktree to be removed |

### Output and Exit Code

**WorktreeCreate**:

- **stdout**: Must output the **absolute path** of the created worktree (the last non-empty line is used)
- **stderr**: Logs can be written here without affecting path parsing
- **exit code 0**: Success — the path in stdout is parsed
- **exit code non-0**: Creation failed — errors out and exits (no fallback to `git worktree`)

```bash
# Correct example: logs to stderr, path to stdout
echo "Initializing SVN checkout..." >&2
echo "/home/user/.codebuddy/worktrees/feature-auth"
```

**WorktreeRemove**:

- No decision control: any exit code does not prevent the exit process
- Failure only logs a warning

### Exit Behavior Difference

Unlike Git worktrees, hook-based worktrees **always show the keep/remove menu** on exit without change detection (since non-Git projects don't have `git status`).

### Hook Script Templates

**WorktreeCreate** (`~/.codebuddy/hooks/worktree-create.sh`):

```bash
#!/bin/bash
set -e

INPUT=$(cat)
NAME=$(echo "$INPUT" | jq -r '.name')
CWD=$(echo "$INPUT" | jq -r '.cwd')

WORKTREE_PATH="$HOME/.codebuddy/worktrees/$NAME"
mkdir -p "$WORKTREE_PATH"

# Add VCS initialization logic here (SVN checkout, P4 sync, directory copy, etc.)
cp -r "$CWD"/* "$WORKTREE_PATH/" 2>/dev/null || true

# Output the absolute path to stdout on the last line (required)
echo "$WORKTREE_PATH"
```

**WorktreeRemove** (`~/.codebuddy/hooks/worktree-remove.sh`):

```bash
#!/bin/bash

INPUT=$(cat)
WORKTREE_PATH=$(echo "$INPUT" | jq -r '.worktree_path')

# Safety check: ensure path is within the expected directory
if [[ "$WORKTREE_PATH" != "$HOME/.codebuddy/worktrees/"* ]]; then
    echo "Refusing to remove path outside worktrees directory: $WORKTREE_PATH" >&2
    exit 1
fi

rm -rf "$WORKTREE_PATH"
```

> **Tip**: The scripts depend on `jq` for JSON parsing. macOS: `brew install jq`, Linux: `apt install jq`.

### Real-world Examples

**SVN project**:

```json
{
    "hooks": {
        "WorktreeCreate": [
            {
                "hooks": [
                    {
                        "type": "command",
                        "command": "bash -c 'INPUT=$(cat); NAME=$(echo $INPUT | jq -r .name); DIR=\"$HOME/.codebuddy/worktrees/$NAME\"; svn checkout https://svn.example.com/repo/trunk \"$DIR\" >&2 && echo \"$DIR\"'"
                    }
                ]
            }
        ],
        "WorktreeRemove": [
            {
                "hooks": [
                    {
                        "type": "command",
                        "command": "bash -c 'cat | jq -r .worktree_path | xargs rm -rf'"
                    }
                ]
            }
        ]
    }
}
```

**Non-VCS project (directory copy)**:

```json
{
    "hooks": {
        "WorktreeCreate": [
            {
                "hooks": [
                    {
                        "type": "command",
                        "command": "bash -c 'INPUT=$(cat); NAME=$(echo $INPUT | jq -r .name); CWD=$(echo $INPUT | jq -r .cwd); DIR=\"$HOME/.codebuddy/worktrees/$NAME\"; cp -r \"$CWD\" \"$DIR\" && echo \"$DIR\"'"
                    }
                ]
            }
        ],
        "WorktreeRemove": [
            {
                "hooks": [
                    {
                        "type": "command",
                        "command": "bash -c 'cat | jq -r .worktree_path | xargs rm -rf'"
                    }
                ]
            }
        ]
    }
}
```

## tmux Integration

Use the `--tmux` parameter to run CodeBuddy in a dedicated tmux session:

```bash
# Basic usage
codebuddy --worktree --tmux

# Use classic mode (without popup)
codebuddy --worktree --tmux --tmux-classic
```

### tmux Requirements

- tmux version 3.2 or higher (for popup support)
- Automatically falls back to classic mode if the version is lower

### Exiting a tmux Session

- Press `Ctrl+D` or type `/exit` to quit CodeBuddy
- The tmux session will be preserved or closed based on your choice

## Directory Structure

```
your-repo/
├── .codebuddy/
│   └── worktrees/
│       ├── feature-auth/      # worktree directory
│       │   ├── node_modules -> ../../node_modules  # symlink
│       │   └── ...
│       └── fix-bug-123/
├── .worktreeinclude           # defines local files to copy (recommended to commit)
└── ...
```

## Manual Worktree Management

CodeBuddy Code automatically handles worktree cleanup when a session exits. However, sometimes you need to manage worktrees outside of a session — for example, cleaning up leftover worktrees or having more flexible control over branches and directory locations.

### Cleaning Up Worktrees Outside a Session

Use Git commands directly:

```bash
# List all current worktrees
git worktree list

# Remove a specific worktree (when there are no uncommitted changes)
git worktree remove .codebuddy/worktrees/feature-auth

# Force remove (when there are uncommitted changes)
git worktree remove --force .codebuddy/worktrees/feature-auth

# Also delete the corresponding branch
git branch -D worktree-feature-auth

# Prune stale worktree references (directory deleted but Git still tracks it)
git worktree prune
```

### Creating Worktrees Directly with Git

Sometimes you need to check out an existing branch, or place the worktree outside the repository directory. You can bypass CodeBuddy Code and create worktrees directly with Git, then start a session inside:

```bash
# Create a new branch and worktree (outside the repository)
git worktree add ../project-feature-a -b feature-a

# Check out an existing branch
git worktree add ../project-bugfix bugfix-123

# Enter the worktree and start CodeBuddy Code
cd ../project-feature-a && codebuddy

# Clean up when done
git worktree remove ../project-feature-a
```

This approach is suitable for scenarios where you need to place the worktree in a specific location or reuse an existing branch.

## Sub-agent Isolation

When having CodeBuddy Code launch multiple sub-agents to work in parallel, each sub-agent can run in an independent worktree to avoid file conflicts.

### What is `isolation: worktree`

Adding `isolation: worktree` to a custom Agent's frontmatter means that each time the `Task` tool launches this Agent, the system automatically creates an independent worktree for it instead of running directly in the main repository directory.

This means:
- Multiple sub-agents can modify files with the same name simultaneously without affecting each other
- The main repository directory stays clean — sub-agents' temporary changes do not pollute it
- After a sub-agent finishes, the worktree is kept or removed as needed

### Creating an Isolated Custom Agent

Create a Markdown file in the `.codebuddy/agents/` directory:

```markdown

You are running in an isolated git worktree.
Focus on completing the task assigned to you, and report results when done.
```

### How It Works

When the main Agent launches this Agent using the `Task` tool, an independent worktree is automatically created for it. Multiple sub-agents can work simultaneously, even modifying the same files without conflicts.

After a sub-agent finishes:
- **No changes**: The worktree is automatically deleted
- **Has changes**: The worktree is preserved, and the main Agent receives the worktree location information

### Verifying Isolation

```
> Use the isolated-worker agent to create test.txt in the current directory with the content "hello"
```

Check the result:

```bash
# The file does not exist in the main repository
ls test.txt
# → No such file or directory ✓

# The file is in the sub-agent's worktree
ls .codebuddy/worktrees/agent-xxx/test.txt
# → exists ✓
```

## Typical Use Cases

### Scenario 1: Developing Based on a Specific Branch

**Problem**: You need to develop a new feature on the develop branch rather than the main branch.

**Solution**:

```bash
# Create a worktree based on remote develop branch
codebuddy --worktree feature-xxx --worktree-branch origin/develop

# Create based on a local branch (preserving local unpushed commits)
codebuddy --worktree feature-yyy --worktree-branch my-local-branch
```

### Scenario 2: Handling Urgent Bugs in Parallel

**Problem**: You're in the middle of developing a new feature with half-written code, and an urgent bug needs fixing.

**Solution**:

```bash
# Terminal 1: Continue developing the new feature
codebuddy --worktree feature-payment

# Terminal 2: Fix the bug separately, without interference
codebuddy --worktree hotfix-login-crash
```

Both worktrees are open simultaneously without affecting each other. Once the bug is fixed and a PR is submitted, switch back to feature development.

### Scenario 3: High-Risk Refactoring

**Problem**: You want to attempt a large-scale refactor but aren't sure if it will succeed, and you don't want to pollute the main repository.

**Solution**:

```bash
codebuddy --worktree refactor-esm
```

In the session:
```
> Help me migrate the src/core directory from CommonJS to ESM
```

Result:
- **Success**: Commit, push PR, merge
- **Failure**: Choose "Remove worktree" on exit — all changes are discarded with one click

### Scenario 4: Reviewing a PR

**Problem**: You want to run a colleague's PR code locally without polluting your working directory.

**Solution**:

```bash
codebuddy --worktree "#456"
```

In the session:
```
> Help me review what this PR changed and check for potential issues
> Run the tests
```

Exit when done — the worktree is automatically cleaned up.

### Scenario 5: Parallel Tasks

**Problem**: You have multiple independent tasks (writing docs, adding tests, developing a new API) and want to work on them separately.

**Solution**:

```bash
codebuddy --worktree task-docs --tmux
codebuddy --worktree task-tests --tmux
codebuddy --worktree task-new-api --tmux
```

Each worktree lets the AI focus on one thing, with tmux enabling true parallel work.

### Scenario 6: Sub-agent Collaboration

**Problem**: A large task requires multiple AI agents to process different modules in parallel.

**Solution**:

First create an isolated Agent (see the "Sub-agent Isolation" section above), then:

```
> Use three parallel api-worker sub-agents:
  The first handles the src/api/user/ directory
  The second handles the src/api/order/ directory
  The third handles the src/api/product/ directory
```

Three sub-agents each work in independent worktrees — even if they modify shared files, there are no conflicts.

## FAQ

**Q: Should I pass a remote or local branch to `--worktree-branch`?**

They are strictly distinct:
- `--worktree-branch origin/xxx` → Uses the remote branch (fetches the latest code first)
- `--worktree-branch xxx` → Uses the local branch (preserves local unpushed commits)

If the specified branch does not exist, a warning is printed and the creation falls back to the remote default branch without interrupting startup.

**Q: Will worktrees take up a lot of disk space?**

No. All worktrees share the Git object database and only need to store the working files themselves. With `symlinkDirectories` configured, large directories are also shared, resulting in virtually no extra space usage.

**Q: When reusing an existing worktree, will files like .env.local be re-copied?**

No. When reusing, the existing directory is entered directly, skipping initialization. To sync new configurations, remove the worktree and recreate it:

```bash
git worktree remove --force .codebuddy/worktrees/my-feature
git branch -D worktree-my-feature
codebuddy --worktree my-feature
```

**Q: Will commits in a worktree affect the main repository?**

No. A worktree has its own branch, and commits are only made on that branch. To merge into the main branch, follow the normal PR process or manually run `git merge`.

**Q: What if the worktree creation was interrupted, leaving an incomplete directory?**

```bash
git worktree remove --force .codebuddy/worktrees/<name>
git branch -D worktree-<name>
```

Then recreate it.

**Q: symlinkDirectories is configured but not working?**

Reusing an existing worktree does not re-run initialization. Remove the old worktree and recreate it.

**Q: Is sub-agent isolation a security sandbox?**

No. Sub-agents are isolated at the file level, but they have the same permissions as the main Agent and can theoretically access files outside the worktree. This feature is designed to prevent **file conflicts** between multiple Agents, not to enforce security restrictions.

**Q: Can I still use Git Worktree after configuring a WorktreeCreate hook?**

No, they cannot be used simultaneously. Hooks take priority over Git — once a WorktreeCreate hook is configured, all worktree operations go through the hook, even in a Git repository. To revert to using `git worktree`, remove the WorktreeCreate configuration from `settings.json`.

**Q: What happens if I configure WorktreeCreate but not WorktreeRemove?**

Creation works normally, but the worktree will not be automatically cleaned up on exit. The system will prompt you with the location of the worktree directory, which you need to manually delete.

**Q: What should I do if the hook script fails?**

A WorktreeCreate failure will error out immediately without falling back to `git worktree` — check the script's stderr output to diagnose the problem. A WorktreeRemove failure only logs a warning and does not affect the exit process.

**Q: Why is there no automatic cleanup when exiting a hook-based worktree in a non-Git project?**

Hook-based worktrees always show the keep/remove menu on exit without performing change detection (since non-Git projects don't have `git status`). You need to manually choose whether to delete it.

## Important Notes

- **Git repository or hook required**: `--worktree` requires a Git repository or a configured WorktreeCreate hook (non-Git projects like SVN and Perforce can use hooks)
- **Branch naming**: Automatically created branches are prefixed with `worktree-`
- **Cleanup**: Long-unused worktrees are not automatically cleaned up — they need to be manually deleted or cleaned using the `/rewind` command
- **Symlinks**: Some tools may not support symlinked directories — configure based on your project's needs

## Related Documentation

- [CLI Reference](./cli-reference.md) - Complete command-line parameter reference
- [Hooks Reference](./hooks.md) - Detailed Hook system documentation
- [Settings Configuration](./settings.md) - Configuration file reference
