notify hook can corrupt TUI by inheriting stdout/stderr
Summary
When notify is configured, Codex spawns the notifier as a child process. If that notifier writes to stdout/stderr (e.g. Python traceback, logging, echo), it can show up in the same terminal and visibly corrupt the Ratatui TUI.
This is easy to hit when a notifier script fails (network/SSL error, missing env var, etc.) and prints a stack trace.
Repro
- Configure
notifyto something that writes to stderr, e.g.:
notify = ["bash", "-lc", "echo notify-stderr 1>&2"]
- Run the Codex TUI and complete a turn.
Observed
The notifier output appears in the terminal and can disrupt the TUI rendering.
Expected
The notifier should not be able to interfere with TUI output.
Root cause
The notifier is started via Command::spawn() and (by default) inherits stdin/stdout/stderr, so any notifier output goes to the same terminal.
Suggested fix
Start the notifier with stdio redirected away from the terminal (or captured to a log file):
- Default:
stdin/stdout/stderr = null - Optional: allow debugging via an explicit opt-in (env var or config), e.g.
CODEX_NOTIFY_INHERIT_STDIO=1ornotify_inherit_stdio = true.
Pseudo-change in codex-rs/core/src/user_notification.rs:
use std::process::Stdio;
...
command.stdin(Stdio::null()).stdout(Stdio::null()).stderr(Stdio::null());
Notes
Even if notify is documented as “best-effort”, the current default makes it very easy for notifier scripts to accidentally break the UX. Redirecting stdio by default seems like a safer baseline for a fullscreen TUI.
Recommended approach
For a fullscreen TUI, the safest default is to prevent the notify child process from ever writing to the terminal:
- Default: spawn notifier with stdin/stdout/stderr redirected to null (Stdio::null()), so tracebacks/logging can't corrupt the TUI.
- Debugging: provide an explicit opt-in to inherit stdio (env var like CODEX_NOTIFY_INHERIT_STDIO=1 or a config flag).
This keeps the hook fire-and-forget while making the UX robust even when notifier scripts fail.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗