diff --git a/crates/codux-terminal-pty/src/lib.rs b/crates/codux-terminal-pty/src/lib.rs index e5f31910..6cb16339 100644 --- a/crates/codux-terminal-pty/src/lib.rs +++ b/crates/codux-terminal-pty/src/lib.rs @@ -807,12 +807,24 @@ fn build_interactive_login_shell_command(shell: &str, command: Option<&str>) -> ) { builder.args(["-NoLogo", "-NoProfile", "-NoExit"]); builder.args(["-ExecutionPolicy", "Bypass"]); - // -NoProfile skips user profiles, so the Codux shell integration - // (OSC 133 marks) is dot-sourced explicitly when staged. - let hook_prefix = "if ($env:DMUX_PS_HOOK_SCRIPT -and (Test-Path -LiteralPath $env:DMUX_PS_HOOK_SCRIPT)) { . $env:DMUX_PS_HOOK_SCRIPT }; "; + // Keep -NoProfile so we control load order: user profiles first (starship, + // zoxide, etc.), then Codux OSC 133 hook which wraps prompt/ReadLine. + let startup_prefix = concat!( + "foreach ($p in @(", + "$PROFILE.AllUsersAllHosts, ", + "$PROFILE.AllUsersCurrentHost, ", + "$PROFILE.CurrentUserAllHosts, ", + "$PROFILE.CurrentUserCurrentHost", + ")) { ", + "if ($p -and (Test-Path -LiteralPath $p)) { . $p } ", + "}; ", + "if ($env:DMUX_PS_HOOK_SCRIPT -and (Test-Path -LiteralPath $env:DMUX_PS_HOOK_SCRIPT)) { ", + ". $env:DMUX_PS_HOOK_SCRIPT ", + "}; ", + ); let command = match command { - Some(command) => format!("{hook_prefix}{command}"), - None => hook_prefix.to_string(), + Some(command) => format!("{startup_prefix}{command}"), + None => startup_prefix.to_string(), }; builder.args(["-Command", &command]); return builder;