Background agents (mobile/web bridge): hang indefinitely, auto-resurrect on SIGTERM, and edit a shared working directory unattended

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 0 comments · opened Jul 31, 2026

Background agents (mobile/web bridge): hang indefinitely, auto-resurrect on kill, and edit a shared working directory unattended

Environment

  • Claude Code 2.1.220 (native build, macOS app)
  • macOS 26.5.2, arm64
  • Model: opus[1m]
  • Working directory: a local project, not a git repository (no git checkout recovery path)
  • Background sessions were started from the Claude mobile app via the session bridge

(each transcript carries a bridge-session record with a cse_… id)

Summary

Four background agents and one interactive session were live in the same working
directory at the same time. I had no way to see or reach the background ones from the
machine they were running on, one of them hung for 40 minutes mid-task, and when its
process was killed the daemon silently restarted it and it kept editing my files.

Three separate problems, filed together because they compound each other.

---

Problem 1 — A background agent hangs after a tool result and is never surfaced

Session c099e939 ("Supplementierung: Soll-Definition & plan.py"), started 19:13:04.

Its last three transcript entries:

19:28:51  tool_use     TaskUpdate  task #3 -> completed
19:28:53  tool_use     Bash        "Final validation"
19:28:55  tool_result  "GRÜN — keine Fehler (15 Warnungen). alle vier Skripte grün"

After that: nothing for 40 minutes. The transcript's last record is a tool_result
with no following assistant message. The process sat at 0.0 % CPU, state S (sleeping),
having used only 1:27 of CPU across 1 h 30 m of wall clock — it accumulated roughly
10 seconds of CPU over the 40 idle minutes, consistent with an idle heartbeat or a
connection retry loop, not with work.

Expected: a stalled agent either times out, retries visibly, or is reported as failed.
Actual: it stays busy forever with no indication anywhere that it is stuck.

Problem 2 — SIGTERM to a background agent silently resurrects it

With the agent idle and the working tree in a verified-clean state, I sent a plain
SIGTERM (not -9) to its process:

kill 56345

The process exited. Three seconds later the daemon started it again:

20:09:40  claude --bg-pty-host … -- …/2.1.220 \
            --resume …/c099e939-….jsonl \
            --name "Supplementierung: Soll-Definition & plan.py" \
            --model opus[1m]

and injected this prompt automatically:

Continue from where you left off. Note: this session was automatically restarted after its process exited.

The agent replied "Alles intakt. Weiter mit den …" and resumed editing the project.
It re-claimed the same control socket (rv/c099e939.sock) and carried on with
permissionMode: auto, i.e. writing files without prompting.

Expected: killing a background agent's process stops that agent, or at minimum the
restart is surfaced to the user and requires confirmation.
Actual: an explicit user attempt to stop an agent is silently undone, and the agent
resumes making unattended writes. From the outside this is indistinguishable from the
kill having failed.

claude agents does list it correctly (status: busy), and is presumably the supported
way to stop it — but nothing in the kill path hints at that, and the restart happens
regardless of user intent.

Problem 3 — Bridged background agents are invisible and unreachable from the host

The agents were started from the Claude mobile app. On the machine actually running them:

  • They do not appear in the interactive session in any way.
  • The user could not open, inspect, or stop them from the phone either — the app had lost

its handle on them.

  • claude agents --json was the only thing that surfaced them, and only because I went

looking for it. claude --help mentions it exclusively in the --bg flag description.

State of this one project when I looked:

| Name | Status |
|---|---|
| Supplementierung: Soll-Definition & plan.py | busy (the hung one) |
| Supplementierung: Preis-Refresh | waiting — "input needed" |
| Supplementierung: Bedarfs-Modus + Medikationsfeld | waiting |
| Supplementierung: D3-Kandidaten via medizinfuchs | blocked |

Three agents had been sitting on an input prompt for hours that nobody could see or answer.

---

Why the combination is worse than the parts

Two sessions — one interactive, one background — were editing the same non-git directory
concurrently, both under permissionMode: auto. I watched a source file grow by 600 bytes
between two reads and briefly observed it in a non-runnable state
(NameError: name 'basis' is not defined) while a refactor was half applied.

Recovery would have depended on file-history-snapshot, but the entries recorded for those
writes had trackedFileBackups: {} — empty. With no git and no backups, a concurrent
overwrite would have been unrecoverable.

Suggested fixes

  1. Time out or fail an agent that has not progressed after a tool_result; surface stalled

agents in claude agents as something other than busy.

  1. Do not auto---resume an agent whose process received a SIGTERM. Distinguish a crash

from a deliberate termination, and make the restart visible when it does happen.

  1. Warn when a background agent's working directory overlaps a live interactive session,

especially outside a git repository.

  1. Populate trackedFileBackups for writes made by background agents.
  2. Make bridged agents reachable from the host session — and make claude agents

discoverable beyond a mention inside the --bg help text.

Reproduction

Not reliably reproduced on demand; the hang appeared spontaneously. The auto-restart
behaviour in Problem 2 is deterministic: kill the process of any running background agent
and observe the daemon respawn it with --resume within a few seconds.

View original on GitHub ↗