Cron/loop jobs never fire while a background Bash task is running (stream-json clients only)
Summary
Scheduled jobs created with CronCreate (i.e. /loop <interval> …) are never delivered while a harness-tracked background Bash task is running, in clients that drive Claude over stream-json (VS Code extension, desktop app). The identical repro in a terminal CLI session delivers on cadence.
The job is not dropped — it stays listed and healthy in CronList the whole time, and ticks resume within seconds of the background task exiting. There is no error or warning, so an inert loop is indistinguishable from a working one.
This matters because the failing case is exactly the intended use case: arming a loop to watch a long-running job that was started in the background.
Repro
In a VS Code extension (or desktop app) session:
- Start a trivial background task through Claude's Bash tool (
run_in_background: true), so the harness tracks it:
````
run this in the background: for i in $(seq 1 84); do echo "bg $i $(date +%H:%M:%S)" >> /tmp/bg.log; sleep 5; done
- Arm a one-minute loop:
````
/loop 1m Run exactly this and nothing else: echo "$(date +%H:%M:%S) tick" >> /tmp/ticks.log — then reply with only that line. No other tool calls.
- Send no further messages for ~5 minutes (user messages also suppress ticks, which would confound the result).
cat /tmp/ticks.log
Expected: a tick roughly every minute.
Actual: no ticks at all until the background task exits. /tmp/ticks.log is not even created. CronList shows the job armed throughout.
Repeat the same steps in a terminal claude session for the contrast.
Observed
Same machine, same minute-granularity cron, same trivial sleep 5 background job launched the same way.
VS Code extension — background job alive 11:48:47 → 11:51:47:
11:49:10 cron armed
11:50:00 window — silent
11:51:00 window — silent
11:51:47 background job killed
11:52:21 tick <- first line in the file, 34s after the kill
Terminal CLI — background job alive 11:54:57 → still running past 11:58:22:
11:55:12 tick (manual first run by the /loop skill)
11:56:31 tick <- cron fire, background job alive
11:57:31 tick <- cron fire, background job alive
Also verified in the extension with a 4-minute background job and the session fully idle: 4 consecutive fire windows, zero ticks, ticks resumed after it exited. Load is not the factor — the background job is a sleep loop with negligible CPU and no disk activity.
Notes
ScheduleWakeupis affected identically, since it is implemented as a one-shot cron job (it appears inCronListasEvery day at HH:MM (one-shot)).- An actively running turn suppressing ticks is expected and documented ("jobs only fire while the REPL is idle"). The issue is that a background task counts as non-idle in stream-json clients but not in the terminal.
- The common factor across the failing clients appears to be the
stream-jsontransport (--input-format stream-json --output-format stream-json), so SDK/headless runs may be affected too. Not verified. - Suggested fix direction: either make background tasks not block delivery in stream-json mode (matching terminal behaviour), or document the divergence and surface it — e.g. have
CronListindicate that delivery is currently blocked.
Environment
- VS Code extension
anthropic.claude-code2.1.222 (linux-x64), affected - Desktop app, affected
- Terminal CLI on the same machine, not affected
- Linux x86_64
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗