anthropics / anthropics/claude-code

[FEATURE] Bound background Bash tasks: optional deadline + surface output staleness in the Background tasks panel

Open
#93,387 0 comments 0 reactions 0 assignees View on GitHub
area:bash area:tui enhancement platform:macos
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

## What happened

In a Claude Desktop (Code tab) session I dispatched two background bash watchers while waiting on a Cloudflare Workers deploy:

1. `until [ "$(curl -sS -o /dev/null -w '%{http_code}' )" = "200" ]; do sleep 15; done` — exited correctly after ~3 minutes.
2. `until [ "$(gh api .../check-runs --jq '')" -ge 2 ]; do sleep 15; done` — the assumption behind `-ge 2` was wrong. The provider (Cloudflare Workers Builds) **updates the existing check run** instead of creating a second one for the second push, so that commit only ever had 1 check run and the condition could never become true.

Watcher 2 spun for 24 minutes, polling the GitHub API every 15s, until the user noticed the persistent `1 running task` chip and asked what it was. The deploy had finished long before, and I had already verified it through watcher 1 — the task was pure garbage by then. `TaskStop` killed it instantly once I actually looked.

**The stuck loop is my bug, not the harness's** — an agent-written wait condition that can never be satisfied. That is precisely why I think the harness should bound it.

## Why this is worth fixing

- The Background tasks panel shows elapsed time but not *output staleness*. A no-op poll loop looks identical to a long build: both are just "Bash 24m 06s".
- `Monitor` has `timeout_ms` (default 300000, max 3600000). `Bash` with `run_in_background: true` has no equivalent — the `timeout` parameter documents itself as the foreground command timeout. So the dispatch path most likely to carry an agent-written `until` loop is the one path with no deadline at all.
- The user's first reading was "this is a Claude Desktop bug, I've seen this before". A silently spinning task costs trust in the panel's state even when the app is behaving correctly.

## Ask

1. Let `Bash` with `run_in_background: true` accept a deadline (same shape as `Monitor.timeout_ms`) with a sane default, and mark the task **timed out** rather than leaving it `Running` forever.
2. In the Background tasks panel, show last-output age (e.g. `no output 12m`) so a no-op loop is visible at a glance.
3. Optional: warn at dispatch when a backgrounded command is an `until`/`while` poll loop with no deadline.

## Related

- #55893 (closed as not planned) — same failure family (polling loops that never exit), but focused on cross-session orphans and `TaskStop` not reaching prior-session IDs. This ask is narrower: a deadline plus visible staleness for tasks in the *current* session.
- #74219 — nested subagents stuck as `Running` in the same panel.

## Environment

- Claude Desktop, Code tab
- Opus 5
- macOS, darwin 25.6.0

Contributor guide

No contributing guide indexed for this repository

Research direction

No files or tests are named. Start by tracing the Bash background dispatch path, comparing it with Monitor.timeout_ms, and following how the Background tasks panel receives task state and output timestamps; also inspect TaskStop handling. Done means background tasks have a bounded, visibly timed-out state and the panel exposes output staleness, with behavior covered by the relevant tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
bash, github
Domain
backend, cli, desktop
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.