Agent background shell for monitored loops dies before first sleep interval fires (/loop never ticks)

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

When an agent sets up a recurring task using the /loop skill pattern, the monitored background shell that drives the loop is terminated by Cursor before the first interval elapses, so the loop never fires and the agent is never woken.

The /loop skill works by starting a background shell like:

while true; do
sleep 3600
echo ‘AGENT_LOOP_TICK_ {“prompt”:“…”}’
done

launched in the background (block_until_ms: 0) with a notify_on_output watcher on the sentinel regex (^AGENT_LOOP_TICK_). Each time the sentinel prints, Cursor is supposed to wake the agent and feed it the payload prompt. This is the documented foundation for all time-based recurring agent work.

The problem: with a long interval (e.g. 1h) the background shell process exits on its own a few minutes after being armed – well before the first sleep 3600 completes – so the sentinel is never printed and the agent is never notified. The loop looks armed but silently never ticks.

A nohup/disown’d copy of the loop keeps sleeping, but by design it cannot wake the agent via notify_on_output, so it does not restore loop functionality.

Steps to Reproduce

  1. In Agent mode, set up an hourly /loop task (or directly start a background shell):
    while true; do sleep 3600; echo ‘AGENT_LOOP_TICK_demo {“prompt”:“do the check”}’; done
    started with block_until_ms: 0 and a notify_on_output watcher on ^AGENT_LOOP_TICK_demo.
  2. Immediately confirm the process is alive – the terminal file header shows a pid and running_for_ms.
  3. Wait, then check the terminal file again (or run kill -0 <pid>).

Observed: the terminal file gets a footer with ended_at / elapsed_ms ~4 minutes after start and exit_code: unknown; kill -0 <pid> reports the process is gone. No AGENT_LOOP_TICK sentinel was ever emitted. Re-arming reproduces the same early death.

Note: a short interval (e.g. sleep 1) fires sentinels normally – the failure shows up specifically when the interval is longer than the background shell’s short lifetime.

Expected Behavior

The monitored background shell should stay alive for the full interval, print the sentinel line at each tick, and wake the agent once per interval – so /loop-style recurring tasks (hourly monitoring, polling, scheduled checks) actually fire on schedule.

Operating System

MacOS

Version Information

IDE:
Version: 3.6.31
VS Code Extension API: 1.105.1
Commit: 81fcf2931d7687b4ff3f3017858d0c6dee7e2a60
Date: 2026-05-31T17:46:29.630Z
Layout: glass
Build Type: Stable
Release Track: Default
Electron: 39.8.1
Chromium: 142.0.7444.265
Node.js: 22.22.1
V8: 14.2.231.22-electron.0
xterm.js: 6.1.0-beta.220
OS: Darwin arm64 24.6.0

For AI issues: which model did you use?

Claude Opus 4.8 (Agent mode)

Additional Information

Impact: any /loop-style recurring agent task with an interval longer than the background shell’s lifetime (minutes) is effectively broken – the loop appears armed but never fires, making agent-driven monitoring/polling/scheduling unreliable.

This may be related to the broader class of background-terminal lifecycle issues already discussed on the forum (e.g. “Backgrounded terminal hangs in IDE”, “Agents hang when window is not in focus” / macOS App Nap throttling, “Terminal hangs due to background process”), but the failure mode here is different: the shell is not hanging, it is being terminated early, so long-interval monitored loops never get a chance to emit their sentinel.

Use case where this surfaced: using the /loop skill to run an hourly CloudWatch monitoring check during a production deploy. The initial run executed fine inline, but the hourly background loop never ticked because its shell kept dying within minutes.

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hi Sergey!

You’ve diagnosed it correctly. A background shell started for a loop isn’t guaranteed to outlive the chat once your turn ends and the session goes idle. With a short interval the sentinel fires (and re-wakes the agent) before that happens, so it looks healthy; with a long interval like 1h the shell gets torn down during the idle window before it ever ticks. It’s worth noting there’s no fixed timer killing it at ~4 minutes - it’s tied to the session/agent lifecycle, so the timing looks roughly consistent but isn’t a clean timeout you can tune around.

For genuinely long-interval recurring work like your hourly CloudWatch check during a deploy, the most reliable approach today is to decouple the scheduled work from waking the agent: run the recurring check as an independent job - a launchd/cron entry, or a standalone tmux/nohup script that appends results to a log file - and then have the agent read that log when you come back. That’s essentially what your nohup copy was already doing; the piece that can’t be guaranteed right now across a long idle window is the wake-on-output back into the chat.

I’m raising the local-IDE case with the team so it’s tracked properly. I’ll follow up here if there’s an update.

Yes, but the /loop command is shipped by default

Fair point — /loop being a built-in command is exactly why we’re treating this as a bug to fix, not something you should have to route around. The cron/launchd/tmux suggestion was only meant as an interim stopgap while this is open, not the intended way to use /loop.

I’ve logged it as a confirmed bug with the team - specifically the long-interval case where the background shell gets torn down during the idle window before it ticks. I’ll update this thread when there’s progress on the fix.