SessionStart hooks should complete before TUI renders
Problem
When a SessionStart hook performs real work (copying files, installing dependencies), the TUI banner, prompt, and status line render concurrently with the hook's execution. After the hook finishes, the prompt has scrolled away and there's no re-render — the user is left with no visible input prompt.
Reproduction
Add a SessionStart hook that takes a few seconds:
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "echo 'Setting up...' > /dev/tty && sleep 5 && echo 'Done' > /dev/tty"
}
]
}
]
}
}
Start Claude:
claude --worktree my-feature
What happens: The TUI renders immediately (banner, "Try how does api.py work?", status line, prompt). The hook output interleaves with it. After the hook finishes, the prompt is scrolled off-screen.
✻
▟█▙ Claude Code v2.1.50
▐▛███▜▌ Opus 4.6 · Claude Max
▝▜█████▛▘ ~/projects/my-project/.claude/worktrees/my-feature
❯ Try "how does api.py work?"
⏵⏵ accept edits on (shift+tab to cycle)
Setting up...
~/p/m/./w/my-feature ✱ Opus 4.6 § 0 tokens
⏵⏵ accept edits on (shift+tab to cycle)
Done
← no prompt visible, user doesn't know where to type
What should happen: The hook completes first, _then_ the TUI renders — so the prompt is the last thing the user sees.
Use case
This is the primary use case for SessionStart hooks with worktrees: copying .env files, installing dependencies (npm install, pip install), generating config. These operations take seconds to minutes. Without visible sequencing, the user stares at a garbled screen with no prompt.
Writing to /dev/tty is the only way to show progress from hooks (stdout becomes AI context, stderr is only visible in verbose mode). But even minimal /dev/tty output races with the TUI.
Suggested fix
Run all SessionStart hooks to completion before rendering the TUI (banner, status line, prompt). This matches the behavior of tools like worktrunk, which runs post-create hooks (blocking) before presenting the shell.
Alternatively, re-render the prompt after hooks complete.
Related
- #26559 — Same race condition on
/clear(hook output interleaves with welcome banner)
Environment
- Claude Code v2.1.50
- Linux (WSL2)
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗