@@ -124,19 +124,32 @@ function sanitizePathSegment(segment: string | undefined, fallback = 'unknown')
124124 return cleaned || fallback ;
125125}
126126
127+ function shQuote ( arg : string ) {
128+ if ( arg === '' ) return "''";
129+ return `'${ arg . replace ( / ' / g, `'\\''` ) } '` ;
130+ }
131+
127132async function runTmux ( args : string [ ] , host ? : string ) {
128133 try {
129134 assertValidHost ( host ) ;
130135 const hostConfig = getHostProfile ( host ) ;
131136 const bin = hostConfig ?. tmuxBin || tmuxBinary ;
132137 const pathAdd = hostConfig ?. pathAdd ?? [ ] ;
133138 const basePath = buildPath ( process . env . PATH , [ ...tmuxFallbackPaths , ...pathAdd ] ) ;
134- const command = host ? 'ssh ' : bin ;
135- const commandArgs = host ? [ '-T' , host , 'env' , `PATH=${ basePath } ` , bin , ...args ] : args ;
136- const { stdout } = await execa ( command , commandArgs , {
137- env : host ? undefined : { ...process . env , PATH : basePath } ,
138- timeout : tmuxCommandTimeoutMs ,
139- } ) ;
139+ let stdout : string ;
140+
141+ if ( host ) {
142+ // Quote the entire tmux invocation so format strings (#{...}) are preserved by the remote shell.
143+ const tmuxCmd = [ 'env' , `PATH=${ basePath } ` , bin , ...args ] . map ( shQuote ) . join ( ' ' ) ;
144+ const sshArgs = [ '-T' , host , 'sh' , '-c' , tmuxCmd ] ;
145+ ( { stdout } = await execa ( 'ssh' , sshArgs , { timeout : tmuxCommandTimeoutMs } ) ) ;
146+ } else {
147+ ( { stdout } = await execa ( bin , args , {
148+ env : { ...process . env , PATH : basePath } ,
149+ timeout : tmuxCommandTimeoutMs ,
150+ } ) ) ;
151+ }
152+
140153 return stdout . trim ( ) ;
141154 } catch ( error ) {
142155 const err = error as { stderr ?: string ; stdout ?: string ; message : string } ;
0 commit comments