claude -p with --output-format stream-json does not flush stdout when piped

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

Bug

When running claude -p --output-format stream-json and piping the output (e.g., | head, | grep, > file), stdout is block-buffered instead of line-buffered. This means JSON lines accumulate in the pipe buffer (~4-8KB) and don't appear until the buffer fills or the process exits.

This makes it impossible to reliably use claude -p with MCP tools from within scripts or other Claude Code sessions, since the output appears to hang indefinitely.

Reproduction

# This works (small output, flushes on exit):
claude -p "say hi" 2>&1

# This hangs with no output (stream-json piped):
claude -p --output-format stream-json --mcp-config ./mcp.json --dangerously-skip-permissions \
  'Call some_mcp_tool with param="value"' 2>&1 | head -20

# Same command without pipe works fine (TTY = line-buffered):
claude -p --output-format stream-json --mcp-config ./mcp.json --dangerously-skip-permissions \
  'Call some_mcp_tool with param="value"'

Expected behavior

When --output-format stream-json is specified, stdout should be flushed after every JSON line regardless of whether stdout is a TTY or a pipe. The entire purpose of streaming output is to consume it incrementally.

Environment

  • Claude Code 2.1.41
  • macOS (Darwin 25.2.0)

Workaround

None reliable. stdbuf -oL is not available on macOS by default. The practical workaround is to bypass the CLI entirely and interact with the underlying tool directly (e.g., writing to the MCP server's SQLite database).

Context

This came up when trying to use claude -p with --mcp-config to call LinkedIn MCP tools from within a parent Claude Code session. The nested claude -p process would run successfully (tools connected, API calls completed) but produce zero output to the pipe, making it appear completely stuck.

View original on GitHub ↗

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