From c90886955d63cf2e4d58273559666575d748eec5 Mon Sep 17 00:00:00 2001 From: T Date: Mon, 14 Sep 2026 22:24:42 -0400 Subject: [PATCH] fix(AI-CLI-if5u): resolve real tty device before backgrounding agent stdin commit 6f0127b redirected a backgrounded agent's stdin from the literal /dev/tty alias. On macOS, kqueue refuses to poll an fd opened through that alias path (ttyname_r resolves it to /dev/tty again rather than a real device) -- Bun-compiled claude then crashes with EINVAL on launch. Resolve the controlling terminal's actual device path via `tty` first and redirect from that instead, falling back to the literal /dev/tty when resolution fails. Root cause corroborated externally: oven-sh/bun#41504. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01PFi83LbqMTznL3DW2sVm9d --- .../bugs/ai-cli-if5u-kqueue-dev-tty-einval.md | 120 ++++++++++++++++++ src/ai_cli/session_script.py | 10 +- tests/test_session_launch_shell_resolution.py | 14 ++ 3 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 docs/bugs/ai-cli-if5u-kqueue-dev-tty-einval.md diff --git a/docs/bugs/ai-cli-if5u-kqueue-dev-tty-einval.md b/docs/bugs/ai-cli-if5u-kqueue-dev-tty-einval.md new file mode 100644 index 00000000..a59bf145 --- /dev/null +++ b/docs/bugs/ai-cli-if5u-kqueue-dev-tty-einval.md @@ -0,0 +1,120 @@ +--- +title: "Claude Code launch fails when stdin is reopened through /dev/tty" +category: bug +tags: [bug, session-launch, macos, terminal, kqueue] +status: fixed +severity: P1 +template_version: "bug-1.0.0" +--- + +# Claude Code launch fails when stdin is reopened through /dev/tty + +## Summary + +On macOS, `ai c 1` could repeatedly crash Claude Code with `EINVAL: invalid +argument, kqueue`. After three exits, the launcher's consecutive-failure circuit +breaker stopped retrying, so the requested session could not be launched or +resumed. + +## Environment and reproduction + +The failure was observed with Bun 1.4.3 on macOS arm64 after commit `6f0127b` +changed supervised agents to retain terminal stdin. Running `ai c 1` from a +registered repository printed the Bun crash and then the launcher's +three-consecutive-exits diagnostic. + +The implementation worker's sandbox cannot create tmux sockets or access a real +TTY. The live symptom and causal boundary were therefore confirmed externally; +the repository regression test covers the generated shell contract. + +## Root cause analysis + +The generated `run_agent` function backgrounded Claude Code with stdin reopened +from the literal controlling-terminal alias: + +```bash +"$@" /dev/null) + if [[ -n "$_agent_tty" && -c "$_agent_tty" && -r "$_agent_tty" ]]; then + "$@" <"$_agent_tty" & + else + "$@" subp ) +def test_given_terminal_stdin_when_agent_is_backgrounded_then_resolved_device_path_is_preferred(): + """The generated launcher must not hand agents a literal /dev/tty stdin fd.""" + body = _run_agent_body() + + resolve_tty = "_agent_tty=$(tty 2>/dev/null)" + resolved_redirect = '"$@" <"$_agent_tty" &' + literal_fallback = '"$@"