[BUG] Intentional kill of a backgrounded Bash task is reported as "failed" exit 144 with no way to mark cleanup as expected

Resolved 💬 2 comments Opened May 25, 2026 by hknet Closed Jun 26, 2026

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?

A Bash call with run_in_background: true started against an unbounded watcher (e.g. ssh host "journalctl -u svc -f | grep --line-buffered PATTERN") can only be stopped later by pkill on the wrapping process. When the agent does that — as part of normal "stop watching now" cleanup — the harness emits a <task-notification> of the form:

<task-notification>
<task-id>…</task-id>
<status>failed</status>
<summary>Background command "…" failed with exit code 144</summary>
</task-notification>

Exit 144 is the expected result of the pipeline receiving SIGTERM via that intentional pkill — the cleanup succeeded. But the notification is indistinguishable from a real crash. In one of today's sessions, three separate user-requested cleanups surfaced as three "failed" events; the user reasonably read the cascade as my work breaking and asked what I was doing wrong.

This punishes the correct usage pattern (start watcher → kill it when done), pushes models toward fragile alternatives (polling loops that miss events; never backgrounding tails at all), and clutters transcripts so genuine failures are harder to skim for.

What Should Happen?

Any of (escalating):

  1. A mark_intentional_termination action on backgrounded tasks (the Bash equivalent of TaskStop) that exits with status: terminated rather than failed.
  2. A heuristic: if the same conversation issued a pkill/kill against the wrapper process within the last few seconds, classify as terminated.
  3. At minimum, distinguish exit codes 143 (SIGTERM) and 144 (SIGTERM-during-pipe) from arbitrary non-zero exits in the summary text: Background command "…" terminated by signal vs failed.

Error Messages/Logs

<task-notification>
<task-id>bp9313az1</task-id>
<tool-use-id>toolu_013WEw2DsaotvAfaYg5qYu3V</tool-use-id>
<output-file>/tmp/claude-…/tasks/bp9313az1.output</output-file>
<status>failed</status>
<summary>Background command "Capture next single turn and exit" failed with exit code 144</summary>
</task-notification>

(Three of these in the session of 2026-05-25, all from intentional cleanups, none from real failures.)

Steps to Reproduce

  1. Bash(run_in_background: true, command: "ssh host 'tail -f /var/log/somefile'")
  2. Do work that uses the watcher's output.
  3. Bash(command: "pkill -f 'ssh host.*tail -f /var/log/somefile'") to stop the watcher.
  4. A few seconds later, a <task-notification> arrives with status: failed and exit code 144 for the background task.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.150

Platform

Anthropic API

Operating System

Other Linux

Terminal/Shell

Other

Additional Information

Platform

linux (WSL2)

Operating System

Linux 6.6.87.2-microsoft-standard-WSL2

Terminal/Shell

bash

Additional Information

Workaround currently in use: prefer bounded background pipelines like tail -f | grep --line-buffered | awk '/PATTERN/{exit}' so the watcher self-terminates on the event of interest and produces a normal completion. Works for "watch until X happens" but not for "watch indefinitely until I say stop."

View original on GitHub ↗

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