@@ -310,7 +310,8 @@ private async Task ExecuteInProcessAsync(AgenticsRunnerRegistration registration
310310 var serverUri = new Uri ( registration . Server ) ;
311311 var agenticServer = $ "{ serverUri . Host } :{ serverUri . Port } ";
312312
313- // 6. Create isolated HOME for this vibecast instance so control socket doesn't conflict
313+ // 6. Create isolated VIBECAST_HOME for this instance so control socket/sessions don't conflict
314+ // We use VIBECAST_HOME (not HOME) so Claude Code's settings/hooks still resolve from real HOME
314315 var vibecastHome = Path . Combine ( Path . GetTempPath ( ) , $ "vibecast-job-{ job . Id } ") ;
315316 Directory . CreateDirectory ( vibecastHome ) ;
316317
@@ -337,7 +338,10 @@ private async Task ExecuteInProcessAsync(AgenticsRunnerRegistration registration
337338 startPsi . ArgumentList . Add ( "50" ) ;
338339 startPsi . ArgumentList . Add ( "bash" ) ;
339340 startPsi . ArgumentList . Add ( "-c" ) ;
340- startPsi . ArgumentList . Add ( $ "cd { jobWorkTree } && HOME={ vibecastHome } AGENTIC_SERVER={ agenticServer } AGENTICS_PROJECT={ registration . Owner } /{ registration . Project } { vibecastBin } ") ;
341+ // Reset HOME to the real user home (runner overrides HOME for its own config isolation)
342+ // so that Claude Code finds its settings in ~/.claude/
343+ var realHome = await GetRealHomeDirectoryAsync ( ct ) ;
344+ startPsi . ArgumentList . Add ( $ "cd { jobWorkTree } && HOME={ realHome } VIBECAST_HOME={ vibecastHome } VIBECAST_BIN={ vibecastBin } AGENTIC_SERVER={ agenticServer } AGENTICS_PROJECT={ registration . Owner } /{ registration . Project } { vibecastBin } ") ;
341345
342346 var startProc = Process . Start ( startPsi ) ;
343347 if ( startProc != null )
@@ -853,6 +857,33 @@ private async Task CleanupAllActiveJobsAsync()
853857 catch { return null ; }
854858 }
855859
860+ private static async Task < string > GetRealHomeDirectoryAsync ( CancellationToken ct )
861+ {
862+ // On Linux, HOME may be overridden by the runner. Get the real home from getent passwd.
863+ if ( OperatingSystem . IsLinux ( ) || OperatingSystem . IsMacOS ( ) )
864+ {
865+ try
866+ {
867+ var psi = new ProcessStartInfo ( "sh" , $ "-c \" getent passwd $(whoami) | cut -d: -f6\" ")
868+ {
869+ RedirectStandardOutput = true ,
870+ RedirectStandardError = true ,
871+ } ;
872+ var proc = Process . Start ( psi ) ;
873+ if ( proc != null )
874+ {
875+ var output = await proc . StandardOutput . ReadToEndAsync ( ct ) ;
876+ await proc . WaitForExitAsync ( ct ) ;
877+ var home = output . Trim ( ) ;
878+ if ( proc . ExitCode == 0 && ! string . IsNullOrEmpty ( home ) )
879+ return home ;
880+ }
881+ }
882+ catch { /* fallback below */ }
883+ }
884+ return Environment . GetFolderPath ( Environment . SpecialFolder . UserProfile ) ;
885+ }
886+
856887 private static async Task < string ? > GetGitDirForWorktreeAsync ( string worktreePath , CancellationToken ct )
857888 {
858889 try
0 commit comments