claude -p with --output-format stream-json does not flush stdout when piped
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.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗