Support suppressing hook status messages in TUI (suppressOutput is a no-op)
Problem
When using Codex hooks (Stop, UserPromptSubmit), the TUI always renders ephemeral status messages:
• Running UserPromptSubmit hook
UserPromptSubmit hook (completed)
• Running Stop hook
Stop hook (completed)
These messages are not part of the conversation history — they don't persist in the JSONL session transcript. They're purely transient TUI artifacts. But there's no way to suppress them.
What we've tried
1. suppressOutput in hook JSON output
The hook output schema defines suppress_output: bool in HookUniversalOutputWire, but every event handler explicitly discards the value:
let _ = parsed.universal.suppress_output;
So outputting {"suppressOutput": true} from a hook script is parsed correctly but has zero effect.
2. Omitting statusMessage in hooks.json
The non-interactive CLI renderer (event_processor_with_human_output.rs) correctly suppresses hooks with status_message: None via should_print_hook_started. But the TUI renders HookStarted/HookCompleted notifications regardless — the suppression logic only exists in the non-interactive path.
3. Config options
No config.toml setting exists for this. hide_agent_reasoning, tui.animations, etc. don't apply to hook messages.
Expected behavior
At least one of these should work:
suppressOutput: truein hook JSON output should suppress the TUI message (the plumbing is already there — just needs to be wired up)statusMessage: null(omitted) inhooks.jsonshould suppress the "Running X hook" message in the TUI, matching the non-interactive CLI behavior- A config option like
tui.hide_hook_status = true
Use case
We embed Codex in a terminal inside a desktop app. Hooks are used for internal status signaling (task lifecycle) and have no user-facing relevance. The status messages create visual noise that we can't control without fragile PTY output stripping.
Environment
- Codex CLI (latest)
- macOS / Linux
features.codex_hooks = true
21 Comments
I reproduced this locally and prepared a tested fix on a public branch.
This implements one of the expected behaviors from the issue: if a hook has no
statusMessage, the TUI stops rendering the transient "Running X hook" / "X hook (completed)" history entries, matching the non-interactive path more closely.Fix on branch:
feat/hook-status-suppress-outputCompare: https://github.com/openai/codex/compare/main...s1korrrr:codex:feat/hook-status-suppress-output
Commit:
7372fa494What changed:
HookStartedhistory rendering whenstatus_messageis missing or blankHookCompletedhistory rendering when the hook completed successfully and emitted no entriescodex-rs/tuiandcodex-rs/tui_app_serverValidation:
cargo test -p codex-tui silent_hook_events_do_not_render_historycargo test -p codex-tui-app-server silent_hook_events_do_not_render_historyjust fix -p codex-tuiCARGO_INCREMENTAL=0 just fix -p codex-tui-app-serverI still can’t open an upstream PR directly because the repo is currently
collaborators_only, but if this matches the intended solution, I’d be happy to open an invited PR from that branch.Reviewed the diff — clean and minimal. Omitting
statusMessagefrom the hook config suppresses hook status messages in the TUI. This is exactly what we need. Thanks @s1korrrr — hope a maintainer can get this merged.This would help outside the TUI-specific case too. For embedder / terminal-wrapper setups, the hook status emissions are just transport noise and ideally should be either fully suppressible or controlled by a config switch.
A solution like one of these would cover the use case cleanly:
suppressOutputfrom hook outputstatusMessageconsistently across renderersThe main need is a reliable way to prevent hook lifecycle messages from being surfaced in the CLI console when hooks are being used for internal plumbing rather than user-facing status.
cc @eternal-openai since PR #13276 introduced the hooks engine.
We hit this as well when integrating Codex hooks into SessionDock, a VS Code session navigator.\n\nOur use case is not user-facing hook output; we use hooks only to track coarse session state (busy vs waiting for input). Right now the TUI always prints lines like
Running UserPromptSubmit hookandUserPromptSubmit hook (completed), which adds noticeable noise to normal conversation flow.\n\nIn practice there is no good workaround: if we disable hooks, we lose session state tracking; if we keep hooks enabled, the TUI gets extra status chatter on every turn. A real suppress/silent mode for hook lifecycle messages would make hooks much more usable for editor integrations and background state tracking.With
PostToolUse, there're probably more frequent messages than other hooks.Now almost half of my screen is filled with these hook status messages. Quite annoying.
I feel this is a UI bug hindering UX, not an "enhancement" request.
Suppressing should be the default, just copy the behavior from Claude. Hook messages are unobstrusive.
Not the greatest UX
<img width="500" alt="Image" src="https://github.com/user-attachments/assets/9a7f0c6f-c07b-4f38-b850-ff1445029e8c" />
<img width="341" height="459" alt="Image" src="https://github.com/user-attachments/assets/e2fe3934-579a-4bef-8d2b-e79359cc54fe" /> 🙃
‼️ FIXED HERE
---
Added
stripSystemReminders()to prevent hook metadata (like <system-reminder> tags containing"stop") from being misinterpreted as user intent by the keyword detector, and we patched the Codex CLI TUI to support asilent: truefield inhooks.jsonthat completely suppresses the noisy "Running X hook" / "X hook (completed)" bannersLet's go @jstxn thank you for the fix!
@jstxn How nice it is to come searching for a fix to an issue and find it was just fixed an hour ago 8) Not all heroes wear capes... but you're welcome to, my friend!
happy to help! @jonnyasmar
<img width="1218" height="562" alt="Image" src="https://github.com/user-attachments/assets/3c8d1519-41be-45ba-9466-67cf962f83cf" />
Would love to bring codex over for notchi but the codex app looks awful with the redundant hook messages
This PR should mitigate this issue. This change is included in the latest release of the CLI (0.120.0). Let us know what you think.
Indexed this hook ticket in the umbrella tracker: #21753
Goal: collect the scattered Codex hook requests and bugs into one parity matrix for Full Claude Code Hook Parity (29+), while preserving this issue as the detailed thread for its specific behavior.
+1, and this matters more than it might sound on the surface.
The current behavior treats every hook as something the user actively wants visible feedback about. But many legitimate use cases — lightweight policy checks, telemetry, formatters, linters, anything embedded in a larger workflow — exist precisely to run silently. Forcing a TUI status line for every one of them makes the TUI actively hostile to any hook that isn't user-facing.
What's puzzling is that the schema already defines
suppressOutput. The mechanism was designed for exactly this. The TUI event handlers then explicitly discard the value (let _ = parsed.universal.suppress_output;). That's not a missing feature — it's a feature that was wired up and then severed. It's hard to see the assumption under which that would be universally desirable; nothing about visible status text is obviously better than silence for non-interactive hooks.A change to honor the existing
suppressOutputflag in the TUI handlers would unblock everyone without breaking any existing config. Happy to PR it if a maintainer signals interest.It would be good to prioritize this, its a real mess on the busier hooks.
This is still not fixed, suppress_output still has no effect. This shouldn’t be closed
same here. this issue persists
what a mess, tried to make a PR but blocked - hopefully 5e8b73e and 0db6c56 fix this.
https://github.com/openai/codex/issues/25403
verified that they don't - if this is the frontier of AI coding, are jobs are quite safe folks.