@@ -174,39 +174,10 @@ export class SSHRuntime implements Runtime {
174174 fullCommand = `timeout -s KILL ${ remoteTimeout } ${ fullCommand } ` ;
175175 }
176176
177- // Build SSH args
177+ // Build SSH args from shared base config
178178 // -T: Disable pseudo-terminal allocation (default)
179179 // -t: Force pseudo-terminal allocation (for interactive shells)
180- const sshArgs : string [ ] = [ options . forcePTY ? "-t" : "-T" ] ;
181-
182- // Add port if specified
183- if ( this . config . port ) {
184- sshArgs . push ( "-p" , this . config . port . toString ( ) ) ;
185- }
186-
187- // Add identity file if specified
188- if ( this . config . identityFile ) {
189- sshArgs . push ( "-i" , this . config . identityFile ) ;
190- // Disable strict host key checking for test environments
191- sshArgs . push ( "-o" , "StrictHostKeyChecking=no" ) ;
192- sshArgs . push ( "-o" , "UserKnownHostsFile=/dev/null" ) ;
193- sshArgs . push ( "-o" , "LogLevel=ERROR" ) ; // Suppress SSH warnings
194- }
195-
196- // Enable SSH connection multiplexing for better performance and to avoid
197- // exhausting connection limits when running many concurrent operations
198- // ControlMaster=auto: Create master connection if none exists, otherwise reuse
199- // ControlPath: Unix socket path for multiplexing
200- // ControlPersist=60: Keep master connection alive for 60s after last session
201- //
202- // Socket reuse is safe even with timeouts because:
203- // - Each SSH command gets its own channel within the multiplexed connection
204- // - SIGKILL on the client immediately closes that channel
205- // - Remote sshd terminates the command when the channel closes
206- // - Multiplexing only shares the TCP connection, not command lifetime
207- sshArgs . push ( "-o" , "ControlMaster=auto" ) ;
208- sshArgs . push ( "-o" , `ControlPath=${ this . controlPath } ` ) ;
209- sshArgs . push ( "-o" , "ControlPersist=60" ) ;
180+ const sshArgs : string [ ] = [ options . forcePTY ? "-t" : "-T" , ...this . buildSSHArgs ( ) ] ;
210181
211182 // Set comprehensive timeout options to ensure SSH respects the timeout
212183 // ConnectTimeout: Maximum time to wait for connection establishment (DNS, TCP handshake, SSH auth)
@@ -675,10 +646,10 @@ export class SSHRuntime implements Runtime {
675646 }
676647
677648 /**
678- * Build common SSH arguments based on runtime config
679- * @param includeHost - Whether to include the host in the args (for direct ssh commands)
649+ * Build base SSH args shared by all SSH operations.
650+ * Includes: port, identity file, LogLevel, ControlMaster options.
680651 */
681- private buildSSHArgs ( includeHost = false ) : string [ ] {
652+ private buildSSHArgs ( ) : string [ ] {
682653 const args : string [ ] = [ ] ;
683654
684655 // Add port if specified
@@ -692,19 +663,18 @@ export class SSHRuntime implements Runtime {
692663 // Disable strict host key checking for test environments
693664 args . push ( "-o" , "StrictHostKeyChecking=no" ) ;
694665 args . push ( "-o" , "UserKnownHostsFile=/dev/null" ) ;
695- args . push ( "-o" , "LogLevel=ERROR" ) ;
696666 }
697667
668+ // Suppress SSH warnings (e.g., ControlMaster messages) that would pollute command output
669+ // These go to stderr and get merged with stdout in bash tool results
670+ args . push ( "-o" , "LogLevel=ERROR" ) ;
671+
698672 // Add ControlMaster options for connection multiplexing
699- // This ensures git bundle transfers also reuse the master connection
673+ // This ensures all SSH operations reuse the master connection
700674 args . push ( "-o" , "ControlMaster=auto" ) ;
701675 args . push ( "-o" , `ControlPath=${ this . controlPath } ` ) ;
702676 args . push ( "-o" , "ControlPersist=60" ) ;
703677
704- if ( includeHost ) {
705- args . push ( this . config . host ) ;
706- }
707-
708678 return args ;
709679 }
710680
@@ -767,7 +737,7 @@ export class SSHRuntime implements Runtime {
767737 return ;
768738 }
769739
770- const sshArgs = this . buildSSHArgs ( true ) ;
740+ const sshArgs = [ ... this . buildSSHArgs ( ) , this . config . host ] ;
771741 const command = `cd ${ shescape . quote ( projectPath ) } && git bundle create - --all | ssh ${ sshArgs . join ( " " ) } "cat > ${ bundleTempPath } "` ;
772742
773743 log . debug ( `Creating bundle: ${ command } ` ) ;
0 commit comments