PreToolUse hook "block" decisions are invisible to the user

Resolved 💬 3 comments Opened May 8, 2026 by christer-bergstrom Closed Jun 5, 2026

Problem

When a PreToolUse hook returns permissionDecision: "block", the blocked command is silently suppressed — the user sees nothing in the TUI. The block reason (including any ANSI formatting) is only visible to the model in the tool error result.

This means users have no way to know that a safety guard blocked a command, what was blocked, or why.

Current behavior

  1. Hook returns {"hookSpecificOutput": {"permissionDecision": "block", "permissionDecisionReason": "\033[31mnah blocked: this hides what will run.\033[0m"}}
  2. Claude receives the block reason as a tool error
  3. User sees nothing — no prompt, no message, no indication anything happened

Expected behavior

Block decisions should be displayed to the user in the TUI, similar to how "ask" decisions show a permission prompt. For example:

Hook PreToolUse:Bash blocked this command:
  az keyvault secret show --vault-name prod --name api-key
nah blocked: this hides what will run.

ANSI escape codes in the reason should be rendered (they already work correctly in "ask" prompts).

Why this matters

Safety guards like nah use "block" for hard-denied commands (e.g., credential exposure, obfuscated execution). Users should see when their guard catches something — both for trust in the tool and for awareness of what the model attempted.

Context

  • "ask" decisions with ANSI colors render correctly in the permission prompt (yellow text confirmed working)
  • "block" decisions produce ANSI output but it never reaches the user
  • Tested with nah 0.8.3 (main) + Claude Code 2.1.133

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗