SessionStart hook stderr not displaying in terminal
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
- 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"
- Configure in
~/.claude/settings.json:
``json``
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "/path/to/hook.sh",
"timeout": 5000
}
]
}
]
}
}
- Start a new Claude Code session
- Expected: "This should appear in terminal" displays immediately
- 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.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗