Claude writes Monitor log watchers (`tail -F | grep | while … break`) that never exit, so the task shows "Running" up to 30 min after the build ends

Status Open
Reported on v2.1.288
Maintainer reply None cached
Activity 0 comments · opened Oct 13, 2026

Preflight Checklist

  • [x] I have searched existing issues for similar behavior reports
  • [x] This report does NOT contain sensitive information (API keys, passwords, etc.)

Type of Behavior Issue

Other unexpected behavior

What You Asked Claude to Do

Make UI changes in an iOS app (Swift/UIKit) and verify them with xcodebuild build and xcodebuild test, working in the Claude desktop app's Code tab.

What Claude Actually Did

Claude ran xcodebuild in the background, writing to a log that ends with an exit <code> line, then started a Monitor to stream errors and the end of the run:

tail -n +1 -F "$S/test.log" | grep -E --line-buffered "error:|: error|TEST SUCCEEDED|TEST FAILED|^exit " | while IFS= read -r l; do echo "$l" | cut -c1-300; case "$l" in exit*) break;; esac; done

break ends only the while loop. tail -F keeps following the finished log and grep keeps waiting on it. Neither writes again, so neither gets SIGPIPE, and the shell waits for every stage of the pipeline. The Monitor therefore runs until its timeout.

Observed: a test run finished in about 2 minutes (** TEST FAILED **, exit 65) and the session finished its reply a minute later, but the Background tasks panel kept showing the Monitor as "Running" for 29m 47s. The thread looked stuck. The same pattern (with tail -F or tail -f) appears in at least 6 sessions over 5 days in this project.

Expected Behavior

A watcher that ends when the run ends (for example, one that kills its tail before break), or no watcher at all: Bash run_in_background already notifies Claude when the command exits.

Files Affected

Permission Mode

I don't know / Not sure

Can You Reproduce This?

Sometimes (intermittent)

Steps to Reproduce

  1. Ask Claude to build or test a project whose build takes a minute or more.
  2. Claude starts the build in the background and a tail -F … | grep … | while … break Monitor on its log.
  3. After the build ends, the Monitor stays "Running" in Background tasks until its timeout.

Minimal shell demo of why it can't end:

log=$(mktemp); (sleep 1; echo 'exit 0' >> "$log") &
tail -n +1 -F "$log" | grep --line-buffered '^exit ' | while read -r l; do echo "$l"; break; done
# prints 'exit 0', then doesn't return until tail is killed

Claude Model

Opus

Relevant Conversation

Impact

Low - Minor inconvenience

Claude Code Version

2.1.288 (Claude Code), bundled with Claude desktop app 2.37337.1

Platform

Anthropic API

Additional Context

  • Claude desktop app (Code tab), macOS 26.5.2, Apple M1 Max, model Opus 5.5.
  • After a user-level rule told Claude to kill tail itself, the fixed watcher still hung: the built-in grep→ugrep shim holds back the last line of a live pipe when the pattern contains |, so the final exit line never reached the loop. That's a separate bug in the shim.
  • Related: #91450 (no signal when a followed log's writer dies), #95242 (orphaned tail -F after TaskStop).

View original on GitHub ↗