SessionStart hook stderr not displaying in terminal

Resolved 💬 2 comments Opened Nov 28, 2025 by JonasSteur Closed Nov 28, 2025

Summary

SessionStart hook scripts that write to stderr do not display output in the Claude Code terminal, despite documentation stating that stderr should be shown to the user immediately.

Environment

  • Claude Code Version: 2.0.55
  • Platform: macOS (Darwin 25.1.0)
  • Hook Type: SessionStart

Expected Behavior

According to the Claude Code hook documentation:

  • Hook stdout should be sent to Claude's context (appears in system-reminder)
  • Hook stderr should be displayed immediately in the user's terminal

Actual Behavior

  • ✅ Hook stdout correctly appears in Claude's context (system-reminder)
  • ❌ Hook stderr does NOT display in the terminal at all
  • ✅ Hook executes successfully (confirmed in debug logs)
  • ✅ Manual execution of the hook script shows stderr correctly

Steps to Reproduce

  1. Create a SessionStart hook script that writes to stderr:

``bash
#!/bin/bash
echo "This should appear in terminal" >&2
echo "This goes to Claude context"
``

  1. Configure in ~/.claude/settings.json:

``json
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "/path/to/hook.sh",
"timeout": 5000
}
]
}
]
}
}
``

  1. Start a new Claude Code session
  1. Expected: "This should appear in terminal" displays immediately
  2. Actual: Nothing appears in terminal (but context message works via stdout)

Evidence

Debug Log

2025-11-28T20:17:58.259Z [DEBUG] Found 1 hook matchers in settings
2025-11-28T20:17:58.259Z [DEBUG] Matched 1 unique hooks for query "startup"
2025-11-28T20:17:58.598Z [DEBUG] Hook output does not start with {, treating as plain text

Manual Execution Works

Running the hook script manually correctly displays stderr:

$ echo '{}' | ~/.claude/hooks/session-start.sh 2>&1 > /dev/null
[Output appears correctly in terminal]

This confirms the script is valid and stderr output is being generated.

Workarounds Attempted

1. Direct /dev/tty write

if [ -w /dev/tty ]; then
    printf "%b\n" "$OUTPUT" > /dev/tty 2>/dev/null || true
fi

Result: Still no terminal output (though hook creates state files, confirming execution)

2. Standard stderr

echo "$OUTPUT" >&2

Result: No terminal output

Both /dev/tty and stderr are being suppressed, suggesting Claude Code is either:

  • Running hooks in a sandboxed environment without terminal access
  • Redirecting all output streams
  • Not displaying hook output until after UI initialization completes

Impact

  • Users cannot receive immediate visual feedback from SessionStart hooks
  • Context restoration notifications are invisible to users
  • Breaks the intended UX for startup hooks as described in documentation

Additional Context

The stdout pathway to Claude's context works perfectly. The issue is specifically with making stderr visible to the user in their terminal during SessionStart hooks.

---

Use Case: Attempting to display a session context restoration banner to users when Claude Code starts, similar to how tmux/vim show session restoration notifications.

View original on GitHub ↗

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