`run_in_background` Bash call returns "completed" immediately when the script backgrounds its own children, and a follow-up `ps` can miss the still-running children
Summary
When a Bash tool call is issued with run_in_background: true and the command itself spawns detached
children (nohup <cmd> > log 2>&1 &), the harness reports the background task as completed as soon as
the parent shell exits, even though the children keep running. A follow-up Bash call issued right after the
completion notification, checking ps aux | grep <cmd>, showed no matching processes, so the model
concluded the launch had failed and relaunched the same workers. The original children were in fact alive
(a later ps aux showed two processes for the same --worker-id), and both generations wrote to the same
output file concurrently, producing ~1.8x duplicate rows.
Two separable issues:
- Completion semantics: "completed" for a
run_in_backgroundcall means "the shell exited", not
"the work finished". Nothing in the notification distinguishes the two when the command detaches children.
- Process visibility right after the notification: the immediate
pscheck returned nothing for
processes that were demonstrably alive a few seconds later. I could not determine whether this is a timing
artefact of how the harness tears down the background shell's process group or a real visibility issue,
but it is what led to the double launch.
Environment
- Claude Code 2.1.2xx (observed 2026-08-20; still the same behaviour on 2.1.260), macOS arm64, zsh
permissions.defaultMode: "auto"
Minimal reproduction
- Call the Bash tool with
run_in_background: trueand the command
nohup sh -c 'for i in $(seq 1 60); do echo tick $i >> /tmp/bg_probe.log; sleep 1; done' > /dev/null 2>&1 &.
- Observe: the background task notification arrives within ~1 s and says the command completed with exit code 0.
- Immediately call Bash (foreground) with
ps aux | grep -v grep | grep 'seq 1 60'.
In the observed sessions this sometimes printed nothing.
- Wait ~5 s and run the same
psagain — the process is listed, and/tmp/bg_probe.logkeeps growing
for 60 s after the "completed" notification.
Expected
- Either the completion notification should say that child processes were left running (e.g. by reporting the
number of live descendants at exit), or the docs should state explicitly that run_in_background completion
is shell-exit only and that detaching children inside such a call is unsupported.
- A
psexecuted after the notification should reflect the true process state; if there is an intentional
teardown window, documenting it would prevent the "it didn't start" misdiagnosis.
Notes
- No transcript is attached (it contains unrelated proprietary content); the reproduction above is self-contained.
- Workaround adopted on our side: never nest
nohup … &inside arun_in_backgroundcall, and re-checkps
after a few seconds before assuming a background launch failed.