Support suppressing hook status messages in TUI (suppressOutput is a no-op)

Resolved 💬 21 comments Opened Mar 23, 2026 by KibetBrian Closed Apr 11, 2026
💡 Likely answer: A maintainer (etraut-openai, contributor) responded on this thread — see the highlighted reply below.

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:

  1. suppressOutput: true in hook JSON output should suppress the TUI message (the plumbing is already there — just needs to be wired up)
  2. statusMessage: null (omitted) in hooks.json should suppress the "Running X hook" message in the TUI, matching the non-interactive CLI behavior
  3. 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

View original on GitHub ↗

21 Comments

s1korrrr · 3 months ago

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-output
Compare: https://github.com/openai/codex/compare/main...s1korrrr:codex:feat/hook-status-suppress-output
Commit: 7372fa494

What changed:

  • suppress HookStarted history rendering when status_message is missing or blank
  • suppress HookCompleted history rendering when the hook completed successfully and emitted no entries
  • apply the same logic in both codex-rs/tui and codex-rs/tui_app_server
  • add focused regression tests in both frontends

Validation:

  • cargo test -p codex-tui silent_hook_events_do_not_render_history
  • cargo test -p codex-tui-app-server silent_hook_events_do_not_render_history
  • just fix -p codex-tui
  • CARGO_INCREMENTAL=0 just fix -p codex-tui-app-server

I 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.

KibetBrian · 3 months ago

Reviewed the diff — clean and minimal. Omitting statusMessage from 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.

gusholcomb · 3 months ago

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:

  • honor suppressOutput from hook output
  • honor omitted / null statusMessage consistently across renderers
  • add a config option to disable hook status rendering entirely

The 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.

isCopyman · 3 months ago

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 hook and UserPromptSubmit 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.

yitoli-c · 3 months ago

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.

raine · 3 months ago

Suppressing should be the default, just copy the behavior from Claude. Hook messages are unobstrusive.

raine · 3 months ago

Not the greatest UX

<img width="500" alt="Image" src="https://github.com/user-attachments/assets/9a7f0c6f-c07b-4f38-b850-ff1445029e8c" />

yam-liu · 3 months ago

<img width="341" height="459" alt="Image" src="https://github.com/user-attachments/assets/e2fe3934-579a-4bef-8d2b-e79359cc54fe" /> 🙃

jstxn · 3 months ago

‼️ 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 a silent: true field in hooks.json that completely suppresses the noisy "Running X hook" / "X hook (completed)" banners

johntimothybailey · 3 months ago

Let's go @jstxn thank you for the fix!

jonnyasmar · 3 months ago

@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!

jstxn · 3 months ago

happy to help! @jonnyasmar

sk-ruban · 3 months ago

<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

etraut-openai contributor · 3 months ago

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.

oxysoft · 2 months ago

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.

oxysoft · 2 months ago

+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 suppressOutput flag in the TUI handlers would unblock everyone without breaking any existing config. Happy to PR it if a maintainer signals interest.

lukehinds · 2 months ago

It would be good to prioritize this, its a real mess on the busier hooks.

mathewhany · 1 month ago

This is still not fixed, suppress_output still has no effect. This shouldn’t be closed

serkanyersen · 1 month ago

same here. this issue persists

lukehinds · 1 month ago

what a mess, tried to make a PR but blocked - hopefully 5e8b73e and 0db6c56 fix this.

https://github.com/openai/codex/issues/25403

lukehinds · 1 month ago
what a mess, tried to make a PR but blocked - hopefully 5e8b73e and 0db6c56 fix this. #25403

verified that they don't - if this is the frontier of AI coding, are jobs are quite safe folks.