fix: resolve BashTool hanging on background commands
BashTool hung indefinitely on background commands (sleep 5 &, node server.js &) due to file descriptor inheritance. await process.exited blocked because background processes inherited stdout/stderr pipes from the parent bash shell.
Bun.spawn()creates bash withstdout: "pipe", stderr: "pipe"- Bash executes
command &and exits - Background process inherits pipe descriptors
process.exitedwaits for all descriptors to close- Background process keeps descriptors open → infinite hang
Added background command detection with selective I/O redirection:
const isBackground = isBackgroundCommand(params.command)
stdout: isBackground ? "ignore" : "pipe",
stderr: isBackground ? "ignore" : "pipe",
Background detection handles:
- Simple:
sleep 5 & - Complex:
(cmd1; cmd2) &,nohup cmd &,cmd & disown - Edge cases: quoted strings, escaped ampersands
- Mixed commands treated as foreground to preserve output
Now:
- Background commands return quickly (vs infinite hang)
- 35 comprehensive tests covering unit, integration, and edge cases
- Full backward compatibility maintained
- No performance impact on foreground commands
⚠️ One weakness here is that the new isBackgroundCommand function is 83 lines long and tries to handle a lot of cases. This might be a bit much for an issue that doesn't seem to occur for a lot of developers (haven't seen an open issue about this). At the same time, this PR might be a segway to fixing other issues with BashTool I/O as well such as #652 (App becomes unresponsive when executing commands requiring sudo password).