From 59f03408147507656ebbb1c71ba81c28e998ed3f Mon Sep 17 00:00:00 2001 From: Jonatan Dahl Date: Mon, 2 Feb 2026 16:15:00 -0500 Subject: [PATCH] feat: symlink .env file into worktrees When creating a worktree, automatically symlink the .env file from the repo root if it exists. This ensures environment configuration is shared across worktrees without duplication. Co-Authored-By: Claude Opus 4.5 --- cmd/worktree.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/cmd/worktree.go b/cmd/worktree.go index b84291a..42bf56e 100644 --- a/cmd/worktree.go +++ b/cmd/worktree.go @@ -281,6 +281,7 @@ func createNewBranchWorktree(gitClient git.GitClient, branchName, baseBranch, wo if !dryRun { fmt.Println(ui.Success(fmt.Sprintf("Created worktree at %s", worktreePath))) fmt.Println(ui.Success(fmt.Sprintf("Branch %s with parent %s", ui.Branch(branchName), ui.Branch(baseBranch)))) + symlinkEnvFile(gitClient, worktreePath) fmt.Printf("\nTo switch to this worktree, run:\n %s\n", ui.Command(fmt.Sprintf("cd %s", worktreePath))) } @@ -296,6 +297,7 @@ func createWorktreeForExisting(gitClient git.GitClient, branchName, worktreePath } if !dryRun { fmt.Println(ui.Success(fmt.Sprintf("Created worktree at %s", worktreePath))) + symlinkEnvFile(gitClient, worktreePath) fmt.Printf("\nTo switch to this worktree, run:\n %s\n", ui.Command(fmt.Sprintf("cd %s", worktreePath))) } return nil @@ -309,6 +311,7 @@ func createWorktreeForExisting(gitClient git.GitClient, branchName, worktreePath } if !dryRun { fmt.Println(ui.Success(fmt.Sprintf("Created worktree at %s (tracking origin/%s)", worktreePath, branchName))) + symlinkEnvFile(gitClient, worktreePath) fmt.Printf("\nTo switch to this worktree, run:\n %s\n", ui.Command(fmt.Sprintf("cd %s", worktreePath))) } return nil @@ -334,6 +337,7 @@ func createWorktreeForExisting(gitClient git.GitClient, branchName, worktreePath if !dryRun { fmt.Println(ui.Success(fmt.Sprintf("Created worktree at %s", worktreePath))) fmt.Println(ui.Success(fmt.Sprintf("Branch %s with parent %s", ui.Branch(branchName), ui.Branch(currentBranch)))) + symlinkEnvFile(gitClient, worktreePath) fmt.Printf("\nTo switch to this worktree, run:\n %s\n", ui.Command(fmt.Sprintf("cd %s", worktreePath))) } return nil @@ -512,3 +516,29 @@ func pathWithinDir(path, dir string) bool { } return rel != ".." && !strings.HasPrefix(rel, ".."+string(os.PathSeparator)) } + +func symlinkEnvFile(gitClient git.GitClient, worktreePath string) { + repoRoot, err := gitClient.GetRepoRoot() + if err != nil { + return + } + + envPath := filepath.Join(repoRoot, ".env") + if _, err := os.Stat(envPath); os.IsNotExist(err) { + return // No .env file, nothing to do + } + + targetPath := filepath.Join(worktreePath, ".env") + + if dryRun { + fmt.Printf("Would symlink .env from %s\n", envPath) + return + } + + if err := os.Symlink(envPath, targetPath); err != nil { + // Silently ignore errors (e.g., symlink already exists) + return + } + + fmt.Println(ui.Success("Symlinked .env file")) +}