@@ -263,6 +263,11 @@ program
263263 'Keep containers running after command exits' ,
264264 false
265265 )
266+ . option (
267+ '--tty' ,
268+ 'Allocate a pseudo-TTY for the container (required for interactive tools like Claude Code)' ,
269+ false
270+ )
266271 . option (
267272 '--work-dir <dir>' ,
268273 'Working directory for temporary files' ,
@@ -312,9 +317,34 @@ program
312317 console . error ( 'Example: awf --allow-domains github.com -- curl https://api.github.com' ) ;
313318 process . exit ( 1 ) ;
314319 }
315-
316- // Join arguments with proper shell escaping to preserve argument boundaries
317- const copilotCommand = joinShellArgs ( args ) ;
320+
321+ // Command argument handling:
322+ //
323+ // SINGLE ARGUMENT (complete shell command):
324+ // When a single argument is passed, it's treated as a complete shell
325+ // command string. This is CRITICAL for preserving shell variables ($HOME,
326+ // $(command), etc.) that must expand in the container, not on the host.
327+ //
328+ // Example: awf -- 'echo $HOME'
329+ // → args = ['echo $HOME'] (single element)
330+ // → Passed as-is: 'echo $HOME'
331+ // → Docker Compose: 'echo $$HOME' (escaped for YAML)
332+ // → Container shell: 'echo $HOME' (expands to container home)
333+ //
334+ // MULTIPLE ARGUMENTS (shell-parsed by user's shell):
335+ // When multiple arguments are passed, each is shell-escaped and joined.
336+ // This happens when the user doesn't quote the command.
337+ //
338+ // Example: awf -- curl -H "Auth: token" https://api.github.com
339+ // → args = ['curl', '-H', 'Auth: token', 'https://api.github.com']
340+ // → joinShellArgs(): curl -H 'Auth: token' https://api.github.com
341+ //
342+ // Why not use shell-quote library?
343+ // - shell-quote expands variables on the HOST ($HOME → /home/hostuser)
344+ // - We need variables to expand in CONTAINER ($HOME → /root or /home/runner)
345+ // - The $$$$ escaping pattern requires literal $ preservation
346+ //
347+ const copilotCommand = args . length === 1 ? args [ 0 ] : joinShellArgs ( args ) ;
318348 // Parse and validate options
319349 const logLevel = options . logLevel as LogLevel ;
320350 if ( ! [ 'debug' , 'info' , 'warn' , 'error' ] . includes ( logLevel ) ) {
@@ -381,6 +411,7 @@ program
381411 copilotCommand,
382412 logLevel,
383413 keepContainers : options . keepContainers ,
414+ tty : options . tty || false ,
384415 workDir : options . workDir ,
385416 buildLocal : options . buildLocal ,
386417 imageRegistry : options . imageRegistry ,
0 commit comments