@@ -5914,69 +5914,50 @@ func (h *Home) createSessionInGroupWithWorktreeAndOptions(
59145914 if multiRepoEnabled && len (additionalPaths ) > 0 {
59155915 inst .MultiRepoEnabled = true
59165916 inst .AdditionalPaths = additionalPaths
5917- // Create temp working directory (resolve symlinks for consistent path comparison on macOS)
5918- tempDir := filepath .Join (os .TempDir (), "agent-deck-sessions" , inst .ID )
5919- if mkErr := os .MkdirAll (tempDir , 0755 ); mkErr != nil {
5920- return sessionCreatedMsg {err : fmt .Errorf ("failed to create multi-repo temp dir: %w" , mkErr )}
5921- }
5922- if resolved , evalErr := filepath .EvalSymlinks (tempDir ); evalErr == nil {
5923- tempDir = resolved
5924- }
5925- inst .MultiRepoTempDir = tempDir
5926- // Update tmux session working directory to temp dir
5927- if inst .GetTmuxSession () != nil {
5928- inst .GetTmuxSession ().WorkDir = tempDir
5929- }
5917+ allPaths := inst .AllProjectPaths ()
59305918
5931- // For non-Claude agents, create symlinks in temp dir so they can access repos from cwd
5932- if ! session .IsClaudeCompatible (tool ) {
5933- allPaths := inst .AllProjectPaths ()
5934- dirnames := session .DeduplicateDirnames (allPaths )
5935- for i , p := range allPaths {
5936- _ = os .Symlink (p , filepath .Join (tempDir , dirnames [i ]))
5919+ if worktreeBranch != "" {
5920+ // Multi-repo + worktree: create a persistent parent dir with all worktrees inside.
5921+ // Layout: ~/.agent-deck/multi-repo-worktrees/<branch>-<id>/<repo-name>/
5922+ home , _ := os .UserHomeDir ()
5923+ sanitizedBranch := strings .ReplaceAll (worktreeBranch , "/" , "-" )
5924+ sanitizedBranch = strings .ReplaceAll (sanitizedBranch , " " , "-" )
5925+ parentDir := filepath .Join (home , ".agent-deck" , "multi-repo-worktrees" ,
5926+ fmt .Sprintf ("%s-%s" , sanitizedBranch , inst .ID [:8 ]))
5927+ if mkErr := os .MkdirAll (parentDir , 0o755 ); mkErr != nil {
5928+ return sessionCreatedMsg {err : fmt .Errorf ("failed to create multi-repo worktree dir: %w" , mkErr )}
59375929 }
5938- }
5930+ if resolved , evalErr := filepath .EvalSymlinks (parentDir ); evalErr == nil {
5931+ parentDir = resolved
5932+ }
5933+ inst .MultiRepoTempDir = parentDir
59395934
5940- // Multi-repo worktree: create per-repo worktrees when worktree is also enabled
5941- if worktreeBranch != "" {
5942- allPaths := inst .AllProjectPaths ()
5943- wtSettings := session .GetWorktreeSettings ()
5935+ // Create worktrees inside parentDir, named after each repo
5936+ dirnames := session .DeduplicateDirnames (allPaths )
59445937 var newProjectPath string
59455938 var newAdditionalPaths []string
59465939 for i , p := range allPaths {
5940+ wtPath := filepath .Join (parentDir , dirnames [i ])
59475941 if git .IsGitRepo (p ) {
59485942 repoRoot , rootErr := git .GetWorktreeBaseRoot (p )
59495943 if rootErr != nil {
59505944 uiLog .Warn ("multi_repo_worktree_skip" , slog .String ("path" , p ), slog .String ("error" , rootErr .Error ()))
5945+ // Copy path as-is into the parent dir via symlink
5946+ _ = os .Symlink (p , wtPath )
59515947 if i == 0 {
5952- newProjectPath = p
5953- } else {
5954- newAdditionalPaths = append (newAdditionalPaths , p )
5955- }
5956- continue
5957- }
5958- wtPath := git .WorktreePath (git.WorktreePathOptions {
5959- Branch : worktreeBranch ,
5960- Location : wtSettings .DefaultLocation ,
5961- RepoDir : repoRoot ,
5962- SessionID : git .GeneratePathID (),
5963- Template : wtSettings .Template (),
5964- })
5965- if err := os .MkdirAll (filepath .Dir (wtPath ), 0o755 ); err != nil {
5966- uiLog .Warn ("multi_repo_worktree_mkdir_fail" , slog .String ("error" , err .Error ()))
5967- if i == 0 {
5968- newProjectPath = p
5948+ newProjectPath = wtPath
59695949 } else {
5970- newAdditionalPaths = append (newAdditionalPaths , p )
5950+ newAdditionalPaths = append (newAdditionalPaths , wtPath )
59715951 }
59725952 continue
59735953 }
59745954 if err := git .CreateWorktree (repoRoot , wtPath , worktreeBranch ); err != nil {
59755955 uiLog .Warn ("multi_repo_worktree_create_fail" , slog .String ("path" , p ), slog .String ("error" , err .Error ()))
5956+ _ = os .Symlink (p , wtPath )
59765957 if i == 0 {
5977- newProjectPath = p
5958+ newProjectPath = wtPath
59785959 } else {
5979- newAdditionalPaths = append (newAdditionalPaths , p )
5960+ newAdditionalPaths = append (newAdditionalPaths , wtPath )
59805961 }
59815962 continue
59825963 }
@@ -5992,16 +5973,49 @@ func (h *Home) createSessionInGroupWithWorktreeAndOptions(
59925973 newAdditionalPaths = append (newAdditionalPaths , wtPath )
59935974 }
59945975 } else {
5995- // Non-git paths used as-is
5976+ // Non-git paths: symlink into parent dir
5977+ _ = os .Symlink (p , wtPath )
59965978 if i == 0 {
5997- newProjectPath = p
5979+ newProjectPath = wtPath
59985980 } else {
5999- newAdditionalPaths = append (newAdditionalPaths , p )
5981+ newAdditionalPaths = append (newAdditionalPaths , wtPath )
60005982 }
60015983 }
60025984 }
60035985 inst .ProjectPath = newProjectPath
60045986 inst .AdditionalPaths = newAdditionalPaths
5987+ } else {
5988+ // Multi-repo without worktree: create a persistent parent dir with symlinks.
5989+ home , _ := os .UserHomeDir ()
5990+ parentDir := filepath .Join (home , ".agent-deck" , "multi-repo-worktrees" , inst .ID [:8 ])
5991+ if mkErr := os .MkdirAll (parentDir , 0o755 ); mkErr != nil {
5992+ return sessionCreatedMsg {err : fmt .Errorf ("failed to create multi-repo dir: %w" , mkErr )}
5993+ }
5994+ if resolved , evalErr := filepath .EvalSymlinks (parentDir ); evalErr == nil {
5995+ parentDir = resolved
5996+ }
5997+ inst .MultiRepoTempDir = parentDir
5998+
5999+ // Create symlinks for all paths
6000+ dirnames := session .DeduplicateDirnames (allPaths )
6001+ var newProjectPath string
6002+ var newAdditionalPaths []string
6003+ for i , p := range allPaths {
6004+ linkPath := filepath .Join (parentDir , dirnames [i ])
6005+ _ = os .Symlink (p , linkPath )
6006+ if i == 0 {
6007+ newProjectPath = linkPath
6008+ } else {
6009+ newAdditionalPaths = append (newAdditionalPaths , linkPath )
6010+ }
6011+ }
6012+ inst .ProjectPath = newProjectPath
6013+ inst .AdditionalPaths = newAdditionalPaths
6014+ }
6015+
6016+ // Update tmux session working directory to the parent dir
6017+ if inst .GetTmuxSession () != nil {
6018+ inst .GetTmuxSession ().WorkDir = inst .MultiRepoTempDir
60056019 }
60066020 }
60076021
@@ -6238,25 +6252,35 @@ func (h *Home) forkSessionCmdWithOptions(
62386252 if len (source .MultiRepoWorktrees ) > 0 {
62396253 inst .MultiRepoWorktrees = append ([]session.MultiRepoWorktree {}, source .MultiRepoWorktrees ... )
62406254 }
6241- tempDir := filepath .Join (os .TempDir (), "agent-deck-sessions" , inst .ID )
6242- if mkErr := os .MkdirAll (tempDir , 0755 ); mkErr != nil {
6243- return sessionForkedMsg {err : fmt .Errorf ("failed to create multi-repo temp dir: %w" , mkErr ), sourceID : sourceID }
6255+ // Create a new persistent dir for the fork with symlinks to shared worktrees
6256+ home , _ := os .UserHomeDir ()
6257+ parentDir := filepath .Join (home , ".agent-deck" , "multi-repo-worktrees" , inst .ID [:8 ])
6258+ if mkErr := os .MkdirAll (parentDir , 0o755 ); mkErr != nil {
6259+ return sessionForkedMsg {err : fmt .Errorf ("failed to create multi-repo dir: %w" , mkErr ), sourceID : sourceID }
62446260 }
6245- if resolved , evalErr := filepath .EvalSymlinks (tempDir ); evalErr == nil {
6246- tempDir = resolved
6261+ if resolved , evalErr := filepath .EvalSymlinks (parentDir ); evalErr == nil {
6262+ parentDir = resolved
62476263 }
6248- inst .MultiRepoTempDir = tempDir
6264+ inst .MultiRepoTempDir = parentDir
62496265 if inst .GetTmuxSession () != nil {
6250- inst .GetTmuxSession ().WorkDir = tempDir
6251- }
6252- // Recreate symlinks for non-Claude agents
6253- if ! session .IsClaudeCompatible (inst .Tool ) {
6254- allPaths := inst .AllProjectPaths ()
6255- dirnames := session .DeduplicateDirnames (allPaths )
6256- for i , p := range allPaths {
6257- _ = os .Symlink (p , filepath .Join (tempDir , dirnames [i ]))
6266+ inst .GetTmuxSession ().WorkDir = parentDir
6267+ }
6268+ // Recreate symlinks/entries in new parent dir pointing to source worktree paths
6269+ allPaths := inst .AllProjectPaths ()
6270+ dirnames := session .DeduplicateDirnames (allPaths )
6271+ var newProjectPath string
6272+ var newAdditionalPaths []string
6273+ for i , p := range allPaths {
6274+ linkPath := filepath .Join (parentDir , dirnames [i ])
6275+ _ = os .Symlink (p , linkPath )
6276+ if i == 0 {
6277+ newProjectPath = linkPath
6278+ } else {
6279+ newAdditionalPaths = append (newAdditionalPaths , linkPath )
62586280 }
62596281 }
6282+ inst .ProjectPath = newProjectPath
6283+ inst .AdditionalPaths = newAdditionalPaths
62606284 }
62616285
62626286 if err := inst .Start (); err != nil {
0 commit comments