Create creates a new git worktree for the repository containing dir and returns it. The worktree lives under the data directory and checks out a freshly created branch so the agent's changes stay isolated from the user's checkout. When name is empty, a friendly random name (e.g. "focused_turing") i
(ctx context.Context, dir, name string, opts ...CreateOption)
| 131 | // Returns [ErrNotGitRepository] when dir is not inside a git worktree, and |
| 132 | // [ErrInvalidName] when an explicit name is not a safe path/branch component. |
| 133 | func Create(ctx context.Context, dir, name string, opts ...CreateOption) (*Worktree, error) { |
| 134 | cfg := resolveCreateConfig(opts) |
| 135 | |
| 136 | root, err := repoRoot(ctx, dir) |
| 137 | if err != nil { |
| 138 | return nil, err |
| 139 | } |
| 140 | |
| 141 | if name == "" { |
| 142 | name = namesgenerator.GetRandomName(0) |
| 143 | } else if err := validateName(name); err != nil { |
| 144 | return nil, err |
| 145 | } |
| 146 | |
| 147 | branch := "worktree-" + name |
| 148 | dest := filepath.Join(cfg.root, "worktrees", name) |
| 149 | |
| 150 | if _, err := os.Stat(dest); err == nil { |
| 151 | return nil, fmt.Errorf("%w: worktree %q already exists at %s", ErrInvalidName, name, dest) |
| 152 | } |
| 153 | |
| 154 | // The branch start-point: a user-chosen base ref, or the current HEAD. |
| 155 | // `git worktree add -b <branch> <dest> [<start-point>]` omits the |
| 156 | // start-point when none was requested, preserving the default behaviour. |
| 157 | addArgs := []string{"worktree", "add", "-b", branch, dest} |
| 158 | if cfg.base != "" { |
| 159 | if err := fetchBase(ctx, root, cfg.base); err != nil { |
| 160 | return nil, err |
| 161 | } |
| 162 | addArgs = append(addArgs, cfg.base) |
| 163 | } |
| 164 | |
| 165 | if err := git(ctx, root, addArgs...); err != nil { |
| 166 | if cfg.base != "" { |
| 167 | return nil, fmt.Errorf("%w: %s: %w", ErrInvalidBase, cfg.base, err) |
| 168 | } |
| 169 | return nil, fmt.Errorf("creating git worktree: %w", err) |
| 170 | } |
| 171 | |
| 172 | wt := &Worktree{Dir: dest, Branch: branch, Name: name, SourceDir: root} |
| 173 | |
| 174 | // Record the branch point so [Status] can later tell whether the |
| 175 | // session added commits. A brand-new repository with no commits has no |
| 176 | // HEAD yet; leave BaseCommit empty in that case. |
| 177 | if head, err := gitOutput(ctx, dest, "rev-parse", "HEAD"); err == nil { |
| 178 | wt.BaseCommit = head |
| 179 | } |
| 180 | |
| 181 | return wt, nil |
| 182 | } |
| 183 | |
| 184 | // CreatePR creates a git worktree that checks out an existing GitHub pull |
| 185 | // request so the agent can continue it. ref is a PR number ("123") or a |