worktree

package
v0.19.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 2, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package worktree manages git worktrees for parallel epic execution.

Worktrees allow tk run to execute multiple epics simultaneously in isolated working directories, each with its own branch. This prevents conflicts between concurrent agents working on different tasks.

Worktree Lifecycle

Each epic gets its own worktree under .claude/worktrees/tk-<epic-id>/ with a corresponding branch named worktree-tk-<epic-id>. The branch is created from the current HEAD (usually main) when the worktree is created.

After an epic completes successfully, its worktree can be merged back to main and then cleaned up.

Usage

manager, err := worktree.NewManager("/path/to/repo")
if err != nil {
    log.Fatal(err)
}

// Create worktree for an epic
wt, err := manager.Create("abc123")
if err != nil {
    log.Fatal(err)
}

// Work in wt.Path...

// Clean up when done
if err := manager.Remove("abc123"); err != nil {
    log.Fatal(err)
}

Package worktree provides git worktree management for isolated feature development.

Index

Constants

View Source
const BranchPrefix = "worktree-" + WorktreeNamePrefix

BranchPrefix is the prefix for worktree branch names.

View Source
const DefaultWorktreeDir = ".claude/worktrees"

DefaultWorktreeDir is the default directory name for storing worktrees.

View Source
const WorktreeNamePrefix = "tk-"

WorktreeNamePrefix keeps tk-managed Claude worktrees isolated from unrelated native Claude worktrees the user may create manually.

Variables

View Source
var ErrMergeConflict = errors.New("merge conflict")

ErrMergeConflict is returned when a merge cannot be completed due to conflicts.

View Source
var ErrNoMergeInProgress = errors.New("no merge in progress")

ErrNoMergeInProgress is returned when trying to abort with no merge in progress.

View Source
var ErrNoTargetBranch = errors.New("no target branch specified and no parent branch recorded")

ErrNoTargetBranch is returned when no target branch is specified and no parent branch is recorded.

View Source
var ErrNotGitRepo = errors.New("not a git repository")

ErrNotGitRepo is returned when the directory is not a git repository.

View Source
var ErrParentBranchNotFound = errors.New("parent branch no longer exists")

ErrParentBranchNotFound is returned when the parent branch no longer exists.

View Source
var ErrWorktreeExists = errors.New("worktree already exists")

ErrWorktreeExists is returned when a worktree already exists for the epic.

View Source
var ErrWorktreeNotFound = errors.New("worktree not found")

ErrWorktreeNotFound is returned when a worktree doesn't exist for the epic.

Functions

func Branch added in v0.11.0

func Branch(epicID string) string

Branch returns the native Claude worktree branch name for an epic.

func EnsureGitignore

func EnsureGitignore(repoRoot string) (bool, error)

EnsureGitignore checks if .claude/worktrees/ is in .gitignore and adds it if not. Creates .gitignore if it doesn't exist. Returns true if .gitignore was modified.

func Name added in v0.11.0

func Name(epicID string) string

Name returns the native Claude worktree name for an epic.

func Path added in v0.11.0

func Path(repoRoot, epicID string) string

Path returns the native Claude worktree path for an epic.

Types

type ConflictHandler

type ConflictHandler struct {
	// contains filtered or unexported fields
}

ConflictHandler manages the conflict lifecycle. It tracks active conflicts and checks for resolution.

func NewConflictHandler

func NewConflictHandler(repoRoot string, merge *MergeManager) *ConflictHandler

NewConflictHandler creates a conflict handler for the given repository.

func (*ConflictHandler) CheckResolved

func (h *ConflictHandler) CheckResolved(epicID string) bool

CheckResolved checks if a conflict has been manually resolved. User resolves by:

  1. cd to main repo
  2. git checkout main
  3. git merge <worktree branch>
  4. Resolve conflicts
  5. git commit

Returns true if the worktree branch is now merged into main.

func (*ConflictHandler) ClearConflict

func (h *ConflictHandler) ClearConflict(epicID string)

ClearConflict removes a conflict from tracking (e.g., after worktree cleanup).

func (*ConflictHandler) GetActiveConflicts

func (h *ConflictHandler) GetActiveConflicts() []*ConflictState

GetActiveConflicts returns all unresolved conflicts. Returns a copy of the conflict states to avoid races.

func (*ConflictHandler) GetConflict

func (h *ConflictHandler) GetConflict(epicID string) *ConflictState

GetConflict returns the conflict state for a specific epic, or nil if none.

func (*ConflictHandler) HandleConflict

func (h *ConflictHandler) HandleConflict(wt *Worktree, conflicts []string, targetBranch string) *ConflictState

HandleConflict is called when a merge fails due to conflict. It aborts the merge (to clean up git state) but leaves the worktree intact for user inspection. Returns ConflictState for tracking/display. The targetBranch parameter is the branch that was being merged into (from MergeResult.TargetBranch).

func (*ConflictHandler) HasConflict

func (h *ConflictHandler) HasConflict(epicID string) bool

HasConflict checks if a specific epic has an active conflict.

type ConflictState

type ConflictState struct {
	EpicID       string    // Epic that had the conflict
	Branch       string    // Branch name (e.g., worktree-tk-abc123)
	Conflicts    []string  // List of conflicting files
	WorktreePath string    // Worktree path (preserved for inspection)
	DetectedAt   time.Time // When conflict was detected
	TargetBranch string    // Branch that was being merged into (e.g., main, feature/auth)
}

ConflictState tracks an unresolved merge conflict.

func (*ConflictState) ConflictInfo

func (s *ConflictState) ConflictInfo() string

ConflictInfo returns a human-readable summary of the conflict.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager handles git worktree lifecycle.

func NewManager

func NewManager(repoRoot string) (*Manager, error)

NewManager creates a worktree manager for the given repository. Returns error if not a git repository.

func (*Manager) AutoCommitTickFiles

func (m *Manager) AutoCommitTickFiles() error

AutoCommitTickFiles commits only .tick/ files with a standard commit message. Returns nil if successful, error otherwise.

func (*Manager) Create

func (m *Manager) Create(epicID string) (*Worktree, error)

Create creates a new worktree for an epic. Branch name: worktree-tk-<epic-id> Path: <repoRoot>/.claude/worktrees/tk-<epic-id> Creates branch from current HEAD if it doesn't exist.

func (*Manager) Exists

func (m *Manager) Exists(epicID string) bool

Exists checks if a worktree exists for the epic.

func (*Manager) Get

func (m *Manager) Get(epicID string) (*Worktree, error)

Get returns the worktree for an epic, or nil if not exists.

func (*Manager) IsDirty

func (m *Manager) IsDirty() (bool, []string, error)

IsDirty checks if the main repository has uncommitted changes. Returns true if there are modified, staged, or untracked files (excluding .claude/worktrees/).

func (*Manager) IsOnlyTickFilesDirty

func (m *Manager) IsOnlyTickFilesDirty(dirtyFiles []string) (bool, []string)

IsOnlyTickFilesDirty checks if only .tick/ files are dirty. Returns true if all dirty files are in .tick/ directory, false if there are other dirty files. Also returns the list of dirty tick files.

func (*Manager) List

func (m *Manager) List() ([]*Worktree, error)

List returns all active tick worktrees.

func (*Manager) Prune

func (m *Manager) Prune() error

Prune removes references to worktrees that no longer exist on disk. This cleans up orphaned entries in .git/worktrees/ that can occur when worktree directories are deleted without using `git worktree remove`.

func (*Manager) Remove

func (m *Manager) Remove(epicID string) error

Remove deletes a worktree and its branch. Force removes even if there are uncommitted changes.

type MergeManager

type MergeManager struct {
	// contains filtered or unexported fields
}

MergeManager handles merging worktree branches to their target branch.

func NewMergeManager

func NewMergeManager(repoRoot string) (*MergeManager, error)

NewMergeManager creates a merge manager for the given repository. Auto-detects the main branch name (main or master).

func (*MergeManager) AbortMerge

func (m *MergeManager) AbortMerge() error

AbortMerge aborts an in-progress merge.

func (*MergeManager) HasConflict

func (m *MergeManager) HasConflict() bool

HasConflict checks if there's an unresolved merge in progress.

func (*MergeManager) MainBranch

func (m *MergeManager) MainBranch() string

MainBranch returns the detected main branch name.

func (*MergeManager) Merge

func (m *MergeManager) Merge(wt *Worktree, opts MergeOptions) (*MergeResult, error)

Merge merges the worktree branch into the target branch. Must be called from main repo (not worktree). Returns MergeResult with conflict details if merge fails.

Target branch resolution: 1. If opts.TargetBranch is set, use it 2. Else if wt.ParentBranch is set, use it 3. Else return ErrNoTargetBranch

type MergeOptions added in v0.9.0

type MergeOptions struct {
	TargetBranch string // Target branch to merge into (overrides worktree's ParentBranch)
}

MergeOptions contains options for the Merge operation.

type MergeResult

type MergeResult struct {
	Success      bool     // True if merge completed successfully
	Merged       bool     // True if merge was performed (not just fast-forward check)
	Conflicts    []string // List of conflicting files if any
	MergeCommit  string   // Commit hash of merge commit (if success)
	ErrorMessage string   // Error details if failed
	TargetBranch string   // The branch that was merged into
}

MergeResult represents the outcome of a merge attempt.

type Worktree

type Worktree struct {
	Path         string    // Absolute path to worktree directory
	Branch       string    // Branch name (e.g., worktree-tk-abc123)
	EpicID       string    // Associated epic ID
	Created      time.Time // When worktree was created
	ParentBranch string    // Branch from which this worktree was created
}

Worktree represents an active git worktree.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL