@@ -332,6 +332,13 @@ func DefaultTerminal() string {
332332 case "darwin" :
333333 return "Terminal.app"
334334 default :
335+ // Inside WSL, prefer Windows Terminal when wt.exe is available
336+ // since it's the terminal the user is actually sitting in.
337+ if isWSL () {
338+ if _ , err := exec .LookPath ("wt.exe" ); err == nil {
339+ return termWindowsTerminal
340+ }
341+ }
335342 if terms := detectLinuxTerminals (); len (terms ) > 0 {
336343 return terms [0 ].Name
337344 }
@@ -371,7 +378,7 @@ func LaunchSession(shell ShellInfo, sessionID string, cfg ResumeConfig) error {
371378 case "darwin" :
372379 return launchDarwinSession (shell , resumeCmd , cfg .Terminal , cwd , cfg .LaunchStyle == LaunchStyleWindow )
373380 default :
374- return launchLinuxSession (shell , resumeCmd , cfg .Terminal , cwd )
381+ return launchLinuxSession (shell , resumeCmd , cfg .Terminal , cwd , cfg . LaunchStyle , cfg . PaneDirection )
375382 }
376383}
377384
@@ -672,7 +679,12 @@ func escapeAppleScript(s string) string {
672679 return s
673680}
674681
675- func launchLinuxSession (shell ShellInfo , resumeCmd string , terminal string , cwd string ) error {
682+ func launchLinuxSession (shell ShellInfo , resumeCmd string , terminal string , cwd string , launchStyle string , paneDirection string ) error {
683+ // Inside WSL, route to Windows Terminal when configured.
684+ if terminal == termWindowsTerminal && isWSL () {
685+ return launchWSLWindowsTerminal (shell , resumeCmd , cwd , launchStyle , paneDirection )
686+ }
687+
676688 // Supported terminal emulators and their argument patterns.
677689 terminals := []struct {
678690 name string
@@ -705,6 +717,13 @@ func launchLinuxSession(shell ShellInfo, resumeCmd string, terminal string, cwd
705717 }
706718 }
707719
720+ // Auto-detect: try Windows Terminal first if running under WSL.
721+ if isWSL () {
722+ if _ , err := exec .LookPath ("wt.exe" ); err == nil {
723+ return launchWSLWindowsTerminal (shell , resumeCmd , cwd , launchStyle , paneDirection )
724+ }
725+ }
726+
708727 // Auto-detect: try terminals in order of popularity.
709728 for _ , t := range terminals {
710729 if p , err := exec .LookPath (t .name ); err == nil {
@@ -719,6 +738,76 @@ func launchLinuxSession(shell ShellInfo, resumeCmd string, terminal string, cwd
719738 return errors .New ("no supported terminal emulator found; tried alacritty, kitty, wezterm, gnome-terminal, konsole, xfce4-terminal, xterm" )
720739}
721740
741+ // launchWSLWindowsTerminal launches a session via wt.exe from within WSL.
742+ // It translates the working directory from a Linux path to a Windows path
743+ // using wslpath and constructs wt.exe arguments for the requested launch
744+ // style (tab, window, or pane).
745+ func launchWSLWindowsTerminal (shell ShellInfo , resumeCmd string , cwd string , launchStyle string , paneDirection string ) error {
746+ p , err := exec .LookPath ("wt.exe" )
747+ if err != nil {
748+ return fmt .Errorf ("wt.exe not found on PATH: %w" , err )
749+ }
750+
751+ // Translate cwd to a Windows path (empty string on failure).
752+ var winCwd string
753+ if cwd != "" {
754+ winCwd , _ = wslToWindowsPath (cwd )
755+ }
756+
757+ distro := os .Getenv ("WSL_DISTRO_NAME" )
758+ args := buildWSLWTArgs (shell , resumeCmd , winCwd , distro , launchStyle , paneDirection )
759+
760+ cmd := exec .Command (p , args ... )
761+ return cmd .Start ()
762+ }
763+
764+ // buildWSLWTArgs constructs the wt.exe argument list for launching a WSL
765+ // session inside Windows Terminal. It is separated from launchWSLWindowsTerminal
766+ // so it can be tested without requiring wt.exe or a WSL environment.
767+ func buildWSLWTArgs (shell ShellInfo , resumeCmd , winCwd , distro , launchStyle , paneDirection string ) []string {
768+ var args []string
769+ switch launchStyle {
770+ case LaunchStyleWindow :
771+ args = append (args , "-w" , "new" , "new-tab" )
772+ case LaunchStylePane :
773+ args = append (args , "-w" , "0" , "split-pane" )
774+ if paneDirection != "" && paneDirection != "auto" {
775+ args = append (args , "--direction" , paneDirection )
776+ }
777+ default :
778+ args = append (args , "-w" , "0" , "new-tab" )
779+ }
780+
781+ if winCwd != "" {
782+ args = append (args , "--startingDirectory" , winCwd )
783+ }
784+
785+ // wt.exe wsl.exe -d <distro> -- <shell> -c <resumeCmd>
786+ if distro != "" {
787+ args = append (args , "wsl.exe" , "-d" , distro , "--" , shell .Path , "-c" , resumeCmd )
788+ } else {
789+ args = append (args , "wsl.exe" , "--" , shell .Path , "-c" , resumeCmd )
790+ }
791+
792+ return args
793+ }
794+
795+ // wslToWindowsPath translates a Linux filesystem path to a Windows path
796+ // using the wslpath utility available inside WSL.
797+ func wslToWindowsPath (linuxPath string ) (string , error ) {
798+ cmd := exec .Command ("wslpath" , "-w" , linuxPath )
799+ out , err := cmd .Output ()
800+ if err != nil {
801+ // Include stderr from wslpath for better diagnostics.
802+ var exitErr * exec.ExitError
803+ if errors .As (err , & exitErr ) && len (exitErr .Stderr ) > 0 {
804+ return "" , fmt .Errorf ("wslpath: %s: %w" , strings .TrimSpace (string (exitErr .Stderr )), err )
805+ }
806+ return "" , fmt .Errorf ("wslpath: %w" , err )
807+ }
808+ return strings .TrimSpace (string (out )), nil
809+ }
810+
722811// ---------------------------------------------------------------------------
723812// Terminal detection
724813// ---------------------------------------------------------------------------
@@ -758,6 +847,15 @@ func detectDarwinTerminals() []TerminalInfo {
758847
759848func detectLinuxTerminals () []TerminalInfo {
760849 var terms []TerminalInfo
850+
851+ // Inside WSL, include Windows Terminal when wt.exe is available
852+ // via the WSL-Windows interop PATH.
853+ if isWSL () {
854+ if _ , err := exec .LookPath ("wt.exe" ); err == nil {
855+ terms = append (terms , TerminalInfo {Name : termWindowsTerminal })
856+ }
857+ }
858+
761859 candidates := []string {
762860 "alacritty" , "kitty" , "wezterm" ,
763861 "gnome-terminal" , "konsole" , "xfce4-terminal" , "xterm" ,
0 commit comments