[BUG] SessionStart hook with external command freezes REPL on Windows

Resolved 💬 2 comments Opened Feb 6, 2026 by hsuanliao Closed Feb 8, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When a plugin defines a SessionStart hook with type: "command" that spawns an external process (either node or bash), the REPL becomes completely unresponsive on Windows after the second startup.

  • The UI renders correctly (input box, model name visible)
  • Keyboard input is completely ignored
  • Ctrl+C has no effect — must force-kill the terminal
  • The hook itself executes successfully (debug log shows "success")
  • Only happens on 2nd+ launch (when hasTrustDialogAccepted: true in ~/.claude.json)
  • First launch (with trust dialog) always works fine

What Should Happen?

SessionStart hooks with type: "command" should not affect terminal input handling. The REPL should remain fully responsive after hook execution completes.

Error Messages/Logs

No errors in debug log. Hook completes successfully:

  2026-02-06T18:16:53.578Z [DEBUG] Hook SessionStart:startup (SessionStart) success:
  Skills synced to C:\Dev\Project\...\references
  2026-02-06T18:16:53.672Z [DEBUG] [REPL:mount] REPL mounted, disabled=false

  All initialization completes normally, but REPL is frozen after mount.

Steps to Reproduce

  1. Create a plugin with a SessionStart hook in hooks/hooks.json:

```json
{
"hooks": {
"SessionStart": [{
"matcher": "startup",
"hooks": [{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/example.js\""
}]
}]
}
}
Where example.js is any simple script (e.g., console.log("hello"); process.exit(0);)

  1. Enable the plugin via .claude/settings.json with extraKnownMarketplaces
  2. Run claude in the project directory — first launch works (trust dialog shown)
  3. Exit Claude, open a new terminal, run claude again — REPL freezes
  4. Workaround: remove project entry from ~/.claude.json or empty the hooks

Diagnostic results:
┌─────────────────┬─────────────┬────────┐
│ Hook │ MCP Servers │ Result │
├─────────────────┼─────────────┼────────┤
│ node command │ None │ Frozen │
├─────────────────┼─────────────┼────────┤
│ bash command │ None │ Frozen │
├─────────────────┼─────────────┼────────┤
│ None (hooks {}) │ None │ Works │
├─────────────────┼─────────────┼────────┤
│ None (hooks {}) │ 4 servers │ Works │
└─────────────────┴─────────────┴────────┘

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.34

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

Root cause hypothesis: The child process spawned by the SessionStart hook corrupts the terminal's raw mode state on Windows. Both node and bash commands trigger this. The issue only manifests when
hasTrustDialogAccepted: true (2nd+ launch), suggesting the hook runs at a different point in the startup sequence when the trust dialog is skipped, which triggers the terminal state corruption.

Workaround: Empty the hooks in hooks.json: { "hooks": {} }

View original on GitHub ↗

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