Terminal hard-locks when Bash tool executes piped node | node with readFileSync('/dev/stdin')

Resolved 💬 3 comments Opened Feb 14, 2026 by flyingrobots Closed Feb 17, 2026

Description

Claude Code terminal hard-locks (no ctrl+c, no interrupt, must force-quit process) when the Bash tool executes commands that pipe one Node.js process into another where the reader uses readFileSync('/dev/stdin').

Repro

Any command in this shape via the Bash tool:

node some-cli.js --json 2>/dev/null | node -e "console.log(JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')))"

Locked 3/3 times during a single session. The command runs fine in a raw terminal and also works when wrapped in timeout 10 bash -c '...'.

Expected

Command executes normally and returns output.

Actual

Terminal freezes completely. No ctrl+c. No interrupt. Must force-quit.

Environment

  • macOS Darwin 25.2.0
  • Node.js >= 22
  • Claude Code (Opus 4.6)

Hypothesis

Claude Code's child process stdio management doesn't properly propagate pipe close/EOF between the two sides of A | B. The right side's readFileSync('/dev/stdin') blocks forever waiting for EOF. This locks the child bash process, which locks Claude Code, which locks the terminal.

Evidence: wrapping in timeout bash -c '...' works — likely because timeout creates an independent process group with clean pipe lifecycle management.

View original on GitHub ↗

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