Hooks need a way to write escape sequences to the user's terminal
Context
In v2.1.132, hooks were intentionally cut off from terminal access to prevent corrupting interactive prompts. This was a good fix for the corruption bug, but it broke a legitimate use case: hooks that write ANSI escape sequences to change terminal appearance (e.g., background color theming based on Claude's state).
Problem
Stop, UserPromptSubmit, and SessionEnd hooks that write to /dev/tty now fail with:
/bin/sh: /dev/tty: Device not configured
The hooks in question are doing things like:
# Change terminal background on Stop (visual indicator Claude is idle)
printf '\033]11;#132b1a\007' > /dev/tty
# Reset terminal background on UserPromptSubmit / SessionEnd
printf '\033]111\007' > /dev/tty
These are non-destructive escape sequences that don't interfere with Claude's UI — they modify the terminal emulator's background color, not the content area.
Suggested fix
Expose the user's actual tty device path as an environment variable in the hook subprocess (e.g., CLAUDE_CODE_TTY=/dev/ttys003). This would let hooks that need terminal access opt in explicitly:
[ -n "$CLAUDE_CODE_TTY" ] && printf '\033]11;#132b1a\007' > "$CLAUDE_CODE_TTY"
This preserves the v2.1.132 fix (hooks don't get /dev/tty by default) while giving hook authors a way to reach the terminal when they need to.
Environment
- Claude Code 2.1.139
- macOS (Ghostty terminal)
- zsh
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗