SessionStart hooks should complete before TUI renders

Resolved 💬 6 comments Opened Feb 21, 2026 by tfriedel Closed Mar 24, 2026

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)

View original on GitHub ↗

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