# Objective
When the agent's terminal tool runs a command with an unsupported shell
syntax (e.g. process substitution `<()` in dash), the shell prints an
error and then drops into interactive mode. It shows a `$` prompt and
hangs waiting for input, requiring the user to press Ctrl+D to continue.
This happens because the stdin redirect wraps the command in a subshell
`(...) </dev/null`, which only closes stdin for the inner command. The
outer shell still has its stdin connected to the PTY, so after a syntax
error it reads from the PTY and waits for more input.
## Solution
Replace the subshell wrapping with an `exec`-level redirect. Instead of:
```sh
sh -i -c '(command\n) </dev/null'
```
We now produce:
```sh
sh -i -c 'exec </dev/null; command'
```
`exec </dev/null;` closes stdin for the **entire shell process**. If the
command fails with a syntax error, the shell immediately gets EOF from
stdin and exits cleanly instead of prompting for more input.
The `-i` flag is preserved so that shells which support it still source
their interactive init files and enable job control.
This change applies to `ShellKind::Posix` (sh/bash/dash/zsh) and
`ShellKind::Fish` in both `ShellBuilder::build()` and
`ShellBuilder::build_no_quote()`.
## Testing
- Manually verified that `cat <(echo hi)` (process substitution in dash)
no longer hangs: the shell exits immediately with the syntax error
## Self-Review Checklist:
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable
---
Release Notes:
- Fixed agent terminal tool hanging with a `$` prompt when commands
encounter syntax errors or unsupported shell features like process
substitution