Bash tool skips its < /dev/null stdin close when the command text contains a space followed by <word, even inside quotes
Version: Claude Code 2.1.296 (macOS)
Summary
The Bash tool normally appends < /dev/null to a command so the child's stdin is at EOF. It skips this when it decides the command already redirects stdin. The check appears to scan the whole command string, including quoted arguments, so a quoted prompt that merely contains <branch> is treated as a redirect. The child then inherits whatever stdin the shell has.
In an interactive session that stdin is a character device and nothing happens. In a background session (claude --bg, Executor-style) fd 0 is an open unix socket, so any program that reads stdin until EOF waits forever.
Rule as we read it
(?:^|[\s;&|])<(?![<(])\s*\S+ applied to the full command text, quotes included.
Reproduction
In a background session's Bash tool:
ls -lL /dev/fd/0 # a b c-> first column starts withc(character device)ls -lL /dev/fd/0 # a <b c-> first column starts withs(socket)
The only difference is the <b in a comment/argument.
Real-world effect: codex exec "<prompt containing ' <branch>'>" (codex reads stdin to EOF when a prompt argument is also given) sat idle: ~0 CPU, no output, only "Reading additional input from stdin...". Interactive session, same prompt: answered in 13 s.
Evidence
Applying the rule above to 12 codex commands from two background sessions: the 5 that matched all hung, the 7 that did not match all completed. Length, quoting style, and foreground vs background were ruled out by counterexamples.
Expected
Only skip the < /dev/null when the command actually redirects stdin (parse the shell syntax), not when < appears inside a quoted string or comment.
Workaround we use
Avoid <word anywhere in the command text; put long prompts in a file and pass a short prompt that points to it.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗