Bash tool inherits harness stdin by default — should close it for non-interactive children
The built-in Bash tool's tool_input schema exposes command, description, run_in_background, timeout, and dangerouslyDisableSandbox — but no stdin parameter. The model has no way to supply input bytes to a command.
Despite this, the spawned child appears to inherit stdin from the harness (a real tty when claude is launched interactively). Any child process that does read, prompts for input, or otherwise blocks on stdin will hang indefinitely — even though the model can never feed it.
Concrete case I hit repeatedly:
# dbi_shell inherits the terminal's stdin, hangs waiting for interactive
# input after processing -cmd flags
subprocess.run(["dbi_shell", "-cmd", "..."], capture_output=True)
The fix in user-land is per-call stdin=subprocess.DEVNULL, or a PreToolUse hook that rewrites every command to prepend exec </dev/null;. The hook works (verified locally) but seems like the kind of thing the tool itself should do, since:
- The model has no API to write to that stdin
- Any command that genuinely needs input is already broken from the tool's perspective
- Closing stdin causes interactive prompts to fail fast (EOF) instead of hanging the session
Proposed: wire the child's stdin to /dev/null by default in the Bash tool. If a future use case needs to pass input, expose an explicit stdin parameter — opt-in is safer than opt-out for an unreachable input channel.
Workaround (PreToolUse hook on Bash):
{
"type": "command",
"command": "jq -c '{hookSpecificOutput: {hookEventName: \"PreToolUse\", updatedInput: (.tool_input | .command = (\"exec </dev/null; \" + .command))}}'"
}This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗