[BUG] Plugin hooks with heredocs >512 bytes deadlock on macOS when Homebrew bash is in PATH

Resolved 💬 3 comments Opened Mar 12, 2026 by lukelabonte Closed Mar 16, 2026

What's not working?

Claude Code v2.1.72 introduced a native bash module for hook execution that uses PATH-resolved bash. On macOS machines with Homebrew bash installed, #!/usr/bin/env bash resolves to bash 5.3.9, which uses pipes (not temp files) for heredoc stdin redirection. macOS pipe buffers are only 512 bytes.

Any plugin hook that feeds a heredoc >512 bytes to a command's stdin (command <<'DELIM' ... DELIM) deadlocks permanently:

  1. Bash creates a pipe (read_fd, write_fd)
  2. Bash writes heredoc content to write_fd
  3. After 512 bytes, the pipe buffer fills — write() blocks
  4. Bash hasn't forked the child process yet, so nobody reads from read_fd
  5. Permanent deadlock — the SessionStart hook never returns
  6. Plugin initialization blocks the prompt submission pipeline
  7. UI renders fully but all prompt input is silently ignored

Two known affected plugins (others likely exist):

  • superpowerscat <<EOF heredoc with ~5,200 bytes of escaped SKILL.md content
  • Axiompython3 - <<'PYTHON_SCRIPT' heredoc with ~2,684 bytes of Python

Each failed session launch leaves zombie hook processes that accumulate indefinitely (no timeout on the pipe deadlock).

What should happen instead?

Plugin hooks should execute successfully regardless of which bash version is in PATH. The native bash module should either:

  1. Force /bin/bash (system bash) for hook execution, or
  2. Add a timeout to hook execution so deadlocked hooks don't permanently block the session, or
  3. Document the limitation so plugin authors know to avoid heredocs >512 bytes on macOS

Steps to reproduce

  1. Install Homebrew bash: brew install bash
  2. Confirm it's the default: which bash/opt/homebrew/bin/bash
  3. Install a plugin with a large heredoc in a SessionStart hook (e.g., superpowers or Axiom)
  4. Start a new Claude Code session
  5. UI renders normally — welcome screen, model info, context bar all appear
  6. Type any message and press Enter → nothing happens, input is silently ignored
  7. Check for zombie processes: ps aux | grep session-start → stuck processes visible

Direct reproduction of the underlying mechanism:

# This hangs with Homebrew bash (heredoc > 512 bytes):
/opt/homebrew/bin/bash -c 'cat <<EOF
'"$(python3 -c "print('x' * 600)")"'
EOF'

# This works with system bash:
/bin/bash -c 'cat <<EOF
'"$(python3 -c "print('x' * 600)")"'
EOF'

Is this a regression? If so, what was the last working version?

Yes. This is a regression introduced in v2.1.72. The last working version was v2.1.71.

The v2.1.72 changelog states:

"Improved bash command parsing by switching to a native module — faster initialization and no memory leak"

This was the resolution of #3991 (request to respect Homebrew bash for hooks). Ironically, respecting Homebrew bash exposed the pipe buffer deadlock for plugins with large heredocs.

Claude Code version

2.1.72+ (tested through 2.1.74)

What platform are you on?

Anthropic API (direct)

What OS are you on?

macOS 26.3.1 (Darwin 25.3.0, Apple Silicon)

Terminal/shell

zsh (affects all terminals — tested Terminal.app, Ghostty, cmux)

Any additional context?

Scope: This affects any macOS machine with Homebrew bash where /opt/homebrew/bin precedes /bin in PATH. It does not affect:

  • Linux (64KB+ pipe buffer — heredocs never exceed it)
  • macOS machines using only system bash (/bin/bash 3.2.57 uses temp files)

Affected plugins:

User workarounds (temporary, must be re-applied after plugin updates):

  • Shebang fix (#!/bin/bash): Works for plugins whose hooks are invoked directly via shebang (e.g., Axiom). Does NOT work for plugins that use a wrapper calling exec bash <script> (e.g., superpowers).
  • Printf fix: Replace cat <<EOF heredoc output with printf. Works for all plugins regardless of invocation method.

Suggested fixes (any of these would work):

  1. Force /bin/bash for hook execution on macOS (safest, matches pre-v2.1.72 behavior)
  2. Add configurable hook execution timeout (prevents silent hangs from any cause)
  3. Use /bin/sh as the hook shell and let scripts specify their own interpreter via shebang
  4. Document the 512-byte heredoc limitation for plugin authors

View original on GitHub ↗

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