1414 * with a temporary SSH config so each devbox uses its own key.
1515 */
1616
17- import { exec } from "child_process" ;
17+ import { execFile } from "child_process" ;
1818import { promisify } from "util" ;
19- import { writeFile , unlink , mkdir } from "fs/promises" ;
19+ import { writeFile , unlink } from "fs/promises" ;
2020import { join } from "path" ;
2121import { tmpdir } from "os" ;
22+ import { randomUUID } from "crypto" ;
2223import { getClient } from "../../utils/client.js" ;
2324import { output , outputError } from "../../utils/output.js" ;
2425import {
@@ -28,7 +29,7 @@ import {
2829 SSHKeyInfo ,
2930} from "../../utils/ssh.js" ;
3031
31- const execAsync = promisify ( exec ) ;
32+ const execFileAsync = promisify ( execFile ) ;
3233
3334export interface SCPOptions {
3435 scpOptions ?: string ;
@@ -232,10 +233,11 @@ export async function scpFiles(src: string, dst: string, options: SCPOptions) {
232233 [ srcRemote , dstRemote ] ,
233234 proxyCommand ,
234235 ) ;
235- const configDir = join ( tmpdir ( ) , "runloop-scp" ) ;
236- await mkdir ( configDir , { recursive : true } ) ;
237- const configPath = join ( configDir , `scp-${ Date . now ( ) } .conf` ) ;
238- await writeFile ( configPath , configContent , { mode : 0o600 } ) ;
236+ const configPath = join ( tmpdir ( ) , `rli-scp-${ randomUUID ( ) } .conf` ) ;
237+ const configHeader =
238+ "# Temporary SSH config generated by `rli devbox scp` for a dual-remote transfer.\n" +
239+ "# Safe to delete.\n\n" ;
240+ await writeFile ( configPath , configHeader + configContent , { mode : 0o600 } ) ;
239241
240242 try {
241243 scpCommand = buildDualRemoteSCPCommand ( {
@@ -248,7 +250,8 @@ export async function scpFiles(src: string, dst: string, options: SCPOptions) {
248250 scpOptions : options . scpOptions ,
249251 } ) ;
250252
251- await execAsync ( scpCommand . join ( " " ) ) ;
253+ const [ cmd , ...args ] = scpCommand ;
254+ await execFileAsync ( cmd , args ) ;
252255 } finally {
253256 // Clean up temp config
254257 await unlink ( configPath ) . catch ( ( ) => { } ) ;
@@ -267,7 +270,8 @@ export async function scpFiles(src: string, dst: string, options: SCPOptions) {
267270 scpOptions : options . scpOptions ,
268271 } ) ;
269272
270- await execAsync ( scpCommand . join ( " " ) ) ;
273+ const [ cmd , ...args ] = scpCommand ;
274+ await execFileAsync ( cmd , args ) ;
271275 }
272276
273277 // Default: just output the destination for easy scripting
0 commit comments