procr1337 8e18ab0cd7 util: Fix stdin redirect for ShellBuilder (#62078)
# Objective

This is a follow-up to my own PR #59270 which fixed the hang it targeted
(#55042) only partially and broke `ShellBuilder::build` for fish.

**The hang is only half fixed.** The agent's terminal tool wraps
commands as `sh -i -c 'exec </dev/null; <command>'`. The redirect sits
on the same line as the command, but POSIX shells parse an entire line
before executing any of it. So when `<command>` has a syntax error, the
whole line is discarded — including the `exec` that was supposed to
close stdin. Interactive `dash` then recovers from the error, finds
stdin still attached to the PTY, and sits at a `$` prompt until the user
presses Ctrl+D.

That means #59270 only helped when the redirect had already run, i.e.
multi-line commands whose error is on a later line. A single-line
command still hangs, including `cat <(echo hi)`, the example from that
PR's own description. Probably prompts or tool definitions changed since
that PR landed which now make it more likely again to run into this
issue, at least with Anthropic models.

**fish runs no command at all.** #59270 also applied the `exec
</dev/null; …` form to fish, replacing its `begin; …; end </dev/null`
wrapper. But fish's `exec` requires a command to replace the shell with,
so a bare `exec </dev/null` is a usage error: fish prints `exec`'s help
text, skips the rest of the command, and exits 0.

## Solution

For POSIX shells, put the redirect on its own line:

```sh
sh -i -c 'exec </dev/null
<command>'
```

That makes it a separate parse-and-execute unit, so it runs before the
command line is parsed. Any syntax error is then reported by a shell
that already has `/dev/null` on stdin, and it exits instead of
prompting.

For fish, go back to `begin; <command>; end </dev/null`. fish exits on a
parse error even when interactive, so it never needed the `exec` form to
begin with.

Only the `Posix` and `Fish` arms change; the other shells' redirects are
untouched.

Note this is still a targeted fix for `dash`. The underlying reason a
syntax error becomes an interactive prompt is that agent terminals are
built with `-i` at all — non-interactive `dash` exits cleanly even with
no redirect. Dropping `-i` would remove the whole class of hang, but it
would also stop sourcing users' interactive shell config in agent
terminals.

## Testing

`cargo test -p util --lib shell_builder` covers the changed command
assembly.

Reviewers can check the shell behavior directly on a PTY, without
building Zed:

```sh
# hangs at a `$` prompt until Ctrl+D
script -qec "sh -i -c 'exec </dev/null; echo hi ;;'" /dev/null

# exits immediately with just the syntax error
script -qec "sh -i -c 'exec </dev/null
echo hi ;;'" /dev/null
```

```sh
fish -i -c 'exec </dev/null; echo test'        # prints exec's help, no "test", exit 0
fish -i -c 'begin; echo test; end </dev/null'  # prints "test"
fish -i -c 'if true'                           # exit 127, no hang
```

macOS is unaffected in practice because `/bin/sh` there is bash, which
exits on a syntax error even with `-i`; Windows goes through the
`Cmd`/`PowerShell` arms, which this doesn't touch. A `zsh`-as-`/bin/sh`
setup is likewise unaffected.

## 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 commands hanging at a shell prompt after a syntax
error
2026-08-05 08:16:06 +00:00
2026-07-29 13:03:22 +00:00
2026-01-22 23:57:26 +05:30
2026-07-27 05:59:53 +00:00
2026-08-04 15:53:09 +00:00
WIP
2023-12-14 09:25:14 -07:00
2026-04-29 10:27:47 +00:00
2025-02-04 09:02:59 -05:00
2025-10-27 13:27:59 -04:00
2026-06-27 15:06:29 +00:00
2025-10-17 18:58:14 +00:00
2026-03-17 16:34:35 +00:00
2026-04-29 10:27:47 +00:00

Zed

Zed CI

Welcome to Zed, a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.


Installation

On macOS, Linux, and Windows you can download Zed directly or install Zed via your local package manager (macOS/Linux/Windows).

Other platforms are not yet available:

Developing Zed

Contributing

See CONTRIBUTING.md for ways you can contribute to Zed.

Also... we're hiring! Check out our jobs page for open roles.

Licensing

Zed source code is licensed primarily under GPL-3.0-or-later, with Apache-2.0 components where marked.

License information for third party dependencies must be correctly provided for CI to pass.

We use cargo-about to automatically comply with open source licenses. If CI is failing, check the following:

  • Is it showing a no license specified error for a crate you've created? If so, add publish = false under [package] in your crate's Cargo.toml.
  • Is the error failed to satisfy license requirements for a dependency? If so, first determine what license the project has and whether this system is sufficient to comply with this license's requirements. If you're unsure, ask a lawyer. Once you've verified that this system is acceptable add the license's SPDX identifier to the accepted array in script/licenses/zed-licenses.toml.
  • Is cargo-about unable to find the license for a dependency? If so, add a clarification field at the end of script/licenses/zed-licenses.toml, as specified in the cargo-about book.

Sponsorship

Zed is developed by Zed Industries, Inc., a for-profit company.

If you’d like to financially support the project, you can do so via GitHub Sponsors. Sponsorships go directly to Zed Industries and are used as general company revenue. There are no perks or entitlements associated with sponsorship.

S
Description
No description provided
Readme
411 MiB
0 Stars 1 Watchers 0 Forks
Languages
Rust 94.9%
JSON-with-Comments 2.7%
Python 0.8%
Inno Setup 0.3%
Tree-sitter Query 0.3%
Other 0.5%