Session spontaneously re-executed hours-old background Bash commands (raw '&') — original order, ~2.3min apart, truncating their logs

Status Open
Reported on v2.1.239
Maintainer reply None cached
Activity 2 comments · opened Aug 22, 2026

Summary

Four historical background Bash commands (long-running processes started with a trailing & inside Bash tool calls) were spontaneously re-executed hours later by an interactive Claude Code session, in their original order, ~2.3 minutes apart, with no user or model action requesting them. Each re-execution truncated the log file the original command had been writing (> logfile in the replayed command line), destroying evidence and initially masquerading as worker crashes.

We could not reproduce this on demand — this report is the forensic evidence from one occurrence, which we believe is enough to point at the responsible code path.

Environment

  • Claude Code 2.1.239, Linux (Ubuntu, kernel 7.0.0-29-generic), node v22.22.2
  • Interactive session inside tmux, running continuously for ~35 hours at the time of the event
  • The session had earlier launched four long-running codex exec … > logfile 2>&1 & style background commands via the Bash tool (raw &, not the Bash tool's run_in_background mode)

What happened

  • Aug 22, ~19:0x–20:0x local: four new bash process trees appeared, each re-running one of the session's four historical raw-& background command lines, in original launch order, spaced ~2.3 min apart.
  • Each replayed tree was launched with the session's own shell-snapshot preamble: bash -c 'source ~/.claude/shell-snapshots/snapshot-bash-<id>.sh; eval <historical command>' — i.e., the exact idiom Claude Code itself uses to spawn Bash tool commands, referencing this session's specific snapshot file.
  • The replays truncated the original commands' log files (the > redirections re-executed) and raced a git worktree the originals had used.
  • We noticed and killed the four replayed trees by PID; no further replays occurred.

Evidence that the origin is the session's own harness

  1. cgroup containment: all four replayed trees ran inside the same transient systemd scope (cgroup) as the session's tmux pane — the scope that contains the interactive claude process. An external tool would have run in its own cgroup. The trees were re-parented to the user systemd manager, i.e. their direct spawner was a process inside that pane's tree which exited after spawning.
  2. Launch idiom: the replays sourced this session's own shell snapshot file by exact path. That path is not present in the session transcript; only the harness composes launches this way.
  3. No process restart: the main claude process had been running uninterrupted since the previous morning (verified via ps lstart), so this was not a session restart re-running anything at startup — whatever replayed did so from inside the still-running process, which is why we suspect an internal background-shell-manager restart/recovery replaying a journal or task list of previously issued background commands.
  4. Ruled out: no cron/systemd timers matching the cadence were active (independently verified); no local tooling on this machine references shell snapshots (repo-wide grep); other agent sessions on the machine run in different panes/cgroups.

Impact

The replayed commands happened to be model-invocation workers, but the same mechanism re-executed arbitrary historical Bash command lines verbatim. If a session's journal of background commands can replay after hours, command lines with side effects (git push, deployments, deletions) are equally exposed. The log-truncation side effect also destroys the evidence of the original runs, which made this hard to diagnose (it initially presented as three separate worker crashes).

Workaround

Long-running background work started via the Bash tool's run_in_background mode was not observed to replay. We have moved all long-running work off raw & onto run_in_background as a guard.

What we could not determine

Anything about the internal trigger — whether an in-process shell-manager restarted and replayed state, what that state is, or what prompted it at that moment (~35h into the session). Happy to provide additional forensics (ps captures, exact timestamps, scope names) on request.

🤖 Generated with Claude Code

View original on GitHub ↗

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