Background shells are killed on the next user message, and PowerShell background commands at end of turn (startsBackgroundWork / superseded run)

Author: unisyntax-devCreated Sep 14, 2026Updated Sep 14, 2026

Summary

Two gaps in the background-work hold from #1113, both separate from #1268 (which covers the Agent tool):

  1. PowerShell is not recognised by startsBackgroundWork(). On Windows, Claude Code's primary shell tool is PowerShell, not Bash. A PowerShell call with run_in_background: true is treated as "nothing outstanding", stdin is released on result, and the background command is killed at the end of the same turn.
  2. The next user message kills background work that is correctly held. queryClaudeSDK() starts a new query (a new claude --resume process) for every turn and immediately releases the previous run's held stdin (getSession(sessionKey())?.releaseInput?.()), and addSession() calls interrupt() on the superseded instance. The old CLI reads EOF, enters print wind-down and kills its background shells. So even Bash with run_in_background: true only survives until the user sends the next message.

Either way, the next turn opens with:

<status>stopped</status>
<summary>Background shell command didn't finish before the previous session ended</summary>

Reproduce

Gap 1 (PowerShell, Windows):

  1. Ask Claude to run, via the PowerShell tool with run_in_background: true, a loop that appends a timestamp to a log every 5 s for 3 minutes.
  2. Let the turn end. Don't send anything.
  3. The log stops growing within ~1 s of the turn's result.

Measured: turn ended ~23:46:20, last log line 23:46:22. For control, two loggers started from the same turn with Start-Process (hidden) and WMI Win32_Process.Create, which are outside the CLI's lifecycle, kept writing through the turn end and through the next message.

Gap 2 (any held background work):

  1. Ask Claude to start a long-running dev server with Bash and run_in_background: true (e.g. pnpm dev). The hold works: the process stays alive after the turn ends.
  2. Send any follow-up message.
  3. The dev server is gone, and the new turn opens with the stopped … previous session ended notification.

Seen in the transcripts: turn ended 23:45:25, follow-up sent 23:47:30, and stopped on pnpm dev right at the start of the follow-up turn. Across one machine's history, 46 such notifications in 12 sessions over one week, all background shells (dev servers, wait loops).

Cause

server/modules/providers/list/claude/claude-runtime.provider.js (1.37.3):

javascript
function startsBackgroundWork(sdkMessage) {
  ...
    if (block.name === 'Bash') {
      return block.input?.run_in_background === true;
    }
    return DEFERRED_WORK_TOOLS.has(block.name);   // no PowerShell arm
}
javascript
// queryClaudeSDK(): a new turn supersedes any earlier one still holding this session's process open
if (sessionKey()) {
    getSession(sessionKey())?.releaseInput?.();
}
javascript
// addSession(): superseding run
Promise.resolve().then(() => existing.instance.interrupt());
existing.releaseInput?.();

The comment above the release says held runs should not "stack up across a conversation", which is reasonable. But because each turn is a separate process, superseding the process also kills everything that turn left running in the background.

Suggested fix

  1. Mirror the Bash arm for PowerShell:
    javascript
    if (block.name === 'Bash' || block.name === 'PowerShell') {
      return block.input?.run_in_background === true;
    }
  2. While a run is heldForBackgroundWork, feed the next user message into that run's held prompt stream (it is already a streaming-input query) instead of starting a new query and releasing/interrupting the old one. This is the same direction #884 suggests: route the next turn to the live process for the sid. Background tasks then report back in the same process, and nothing is killed on the user's next message.

Environment

  • cloudcli 1.37.3, installed globally via npm (file verified byte-identical to the published tarball, no local patches)
  • Claude Code 2.1.270
  • Node v22.16.0, Windows 11 Pro (26200)

Related: #1113, #1268, #884