[BUG] `claude -p` process doesn't terminate after agent session completes (macOS)
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 using claude -p as a subprocess within an orchestration pipeline, the process completes its agent session (reads files, writes output files, generates final response) but never exits. The parent process blocks indefinitely waiting for the subprocess to terminate.
This was observed during a real-world orchestration scenario: a script pipes a prompt into claude -p --model opus --allowedTools "Read,Write,Glob,Grep,Bash(ls *)" and captures the output. The Claude agent ran for some time, successfully completed all its work (confirmed by inspecting the Claude Code session), wrote output files via the Write tool, and produced a final summary response. However, the claude -p process never terminated, leaving the parent pipeline hung.
What Should Happen?
After the agent session completes and the final response is generated, claude -p should flush stdout and exit with code 0.
Actual Behavior
The agent session completes (visible in Claude Code session history), output files are written, a final response is generated, but:
- The process does not exit
- stdout is not closed
- The parent pipeline blocks indefinitely waiting for EOF/process exit
- Must be manually killed
Steps to Reproduce
- Create a prompt that instructs the agent to read multiple files, analyze them, and write output files using the Write tool
- Pipe the prompt into
claude -pwith tools enabled:
echo "Read /path/to/data.json, analyze the contents, then write a summary to /tmp/summary.json and /tmp/summary.md" | claude -p --model opus --allowedTools "Read,Write,Glob,Grep"
- Wait for the agent to complete its work (visible in
claudesession list or by checking if output files were written) - Observe that the process does not terminate despite the session being complete
The issue is more reliably triggered with:
- Longer sessions (many tool calls over extended time)
- Opus model (slower, longer sessions)
- Write tool usage in the agent's final actions
- Piped input (prompt via stdin rather than argument)
Claude Model
Not sure / Multiple models
Is this a regression?
Yes, this worked in a previous version
Last Working Version
unsure
Claude Code Version
2.1.19
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Context
This was discovered while running automated QA orchestration where my orchestration script spawns Claude agents as subprocesses via claude -p. The issue has been observed across multiple phases of the pipeline using both Sonnet and Opus models. The most recent instance involved an Opus session that ran for approximately one hour of tool calls and hung after the agent finished.
The agent's final actions in the session (confirmed via Claude Code session viewer):
Write(/path/to/trend-report.json) — 397 lines written successfully
Write(/path/to/trend-report.md) — 222 lines written successfully
"Both files are written. Here's a summary: ..." — final response generated
After this, the claude -p process remained alive indefinitely. The parent process was stuck waiting for process exit/stdout EOF.
Related Issues
- #20084 — Identical symptoms on Windows (process completes but doesn't terminate in
-pmode) - #9026 — Similar hang in
-pmode without TTY (closed, older version) - #16487 — Process tree cleanup issues with piped output on macOS
- #15918 — Zombie process with
--resumeand-p
Workaround
Marker file polling: Instead of waiting for claude -p to exit and reading stdout, instruct the agent to write a marker file as its final action, then poll for that file:
# Launch claude -p in the background
claude -p --model opus --allowedTools "Read,Write,Glob,Grep" < "$PROMPT_FILE" > /dev/null 2>&1 &
CLAUDE_PID=$!
# Poll for the marker file the agent was told to write as its last action
while ! test -f "$MARKER_FILE"; do
sleep 5
if ! kill -0 $CLAUDE_PID 2>/dev/null; then break; fi
done
# Give the agent a moment to flush any remaining writes, then kill the hung process
sleep 15
kill $CLAUDE_PID 2>/dev/null
wait $CLAUDE_PID 2>/dev/null
# Read output from the marker file instead of stdout
cat "$MARKER_FILE"
The prompt includes an instruction like: "When you have completed ALL your work, as your very last action, write the text 'done' to /path/to/marker-file."
This sidesteps the hang entirely — it doesn't rely on process exit or stdout EOF, using the filesystem as a completion signal instead. The tradeoff is you lose stdout output and must have the agent write its results to files.
7 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
This is related but it's not the same issue. I specifically called these out in the issue:
-pmode)-pmode without TTY (closed, older version)--resumeand-p+1
claude -p > file.txthangs indefinitely on node:20-slim as well.Confirming on Linux — with minimal repro and simpler workaround
Platform: Ubuntu 24.04, Claude Code 2.1.34, Anthropic API
Same issue here. Running
claude -pin an automation loop (ralph.shorchestrator) where output is piped toteefor logging. The process hangs indefinitely with zero output.Minimal reproduction
This confirms the root cause is TTY detection:
claude -pbehaves differently when stdout is a pipe vs. a terminal.Simpler workaround:
scriptas PTY wrapperInstead of marker file polling, wrapping
claude -pinscript -qefcprovides a pseudo-terminal so claude sees a TTY — works reliably with pipes:This preserves real-time streaming output through pipes (e.g.
| tee -a logfile.md) and the process exits normally.Version history
Worked in 2.1.23 (Jan 25–29), broken in 2.1.34 (Feb 7). Same script, same pipe pattern.
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
This has just continued to get more duplicates and validation it’s a real bug. Silly to close it.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.