Remote-SSH agent: background shell tool calls run 2–3 times; tool execution throttled to once a minute while the window is unfocused (3.18.25)

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Cursor 3.18.25 (commit 280eca2911f1774689696e5f1efa5a4f97a87af0, build 2026-08-31), macOS 26.6.2 client connected over Remote-SSH to an Ubuntu Linux x86_64 host. Agent mode with auto-run, subagents launched through the Task tool with run_in_background. Everything below comes from one day-long agent session; log excerpts are from the remote host.

Bug 1: one background shell tool call is executed 2–3 times.
A single Shell tool call in background mode spawns several processes. The exec log shows the same toolCallId reaching the approval gate three times and three agent.background_shell_started events with three different PIDs; the terminals/ folder gets three files with identical command and identical started_at:

23:26:01.494 Background shell: approval gate reached   toolCallId=toolu_01CNyJV1Fc6MB2uSGWZogRqJ   (x3, same ms)
23:27:01.529 Background shell: approval gate allowed   toolCallId=toolu_01CNyJV1Fc6MB2uSGWZogRqJ   (x3)
23:27:01.562 agent.background_shell_started shell_id=393655 pid=2474901 tool_call_id=toolu_01CNyJV1Fc6MB2uSGWZogRqJ
23:27:01.562 agent.background_shell_started shell_id=393656 pid=2474904 tool_call_id=toolu_01CNyJV1Fc6MB2uSGWZogRqJ
23:27:01.562 agent.background_shell_started shell_id=393657 pid=2474919 tool_call_id=toolu_01CNyJV1Fc6MB2uSGWZogRqJ

Over the day, of 142 distinct background commands 71 ran 3 times, 15 ran 2 times, one ran 5 times. Real consequences: a git merge --no-ff into master raced against its own duplicate (the tag ended up on the wrong commit), a 20-minute Unity test suite ran three times in parallel, and the agent ended up wrapping every command in flock -n to survive. Duplicated timers also wake the parent agent three times, and it spends turns on “stale notification, nothing new”.

Bug 2: when the Cursor window is not focused, tool execution is throttled to one dispatch per minute.
While the window is in the background (other app focused, or display asleep) with the SSH connection still alive:

  • every background command starts at exactly :01 of a minute (20:25:01, 20:28:01, 20:33:01 …); with the window focused, start times are random seconds;
  • the approval gate for auto-approved commands takes 60–180 s (approval gate reachedapproval gate allowed, median 60 s, p90 180 s over 136 calls); with the window focused it is 0 s;
  • foreground Shell calls get aborted: AbortError: This operation was aborted … at $cancelAgentExecProviderStream in remoteexthost.log, again at :02 of consecutive minutes, so the model sees “no exit status” and falls back to background mode plus reading the terminal file by hand;
  • the watchdog logs permissionsService.shouldBlockFileRead still not completed after 3000ms (196 times) and shouldBlockWrite … (90 times);
  • a background subagent finishing a step wakes the parent 5–27 minutes later.

It looks like Electron/Chromium background-timer throttling in the client window sits on the path of every tool call (approval gate, permission checks, exec stream), so a Remote-SSH agent only runs at full speed while the user is looking at it.

Related: client disconnect kills background subagents.
When the laptop slept (SSH reconnect flapping 03:36–05:03), one running subagent ended with Agent turn stopped after repeated resume attempts made no progress, and the next one launched by the parent never started (its transcript file was created empty at the reconnect timestamp). The parent then waited six hours for a worker that did not exist. Maybe expected with the current architecture, but with Remote-SSH the natural expectation is that the remote side keeps working. Possibly related: Multitask Mode background / forked subagents hang

Steps to Reproduce

  1. Remote-SSH to a Linux host, open a workspace, enable auto-run in Agent mode.
  2. Ask the agent to run a shell command in background mode (or launch a background subagent that does).
  3. On the remote host, compare ~/.cursor/projects/<workspace>/terminals/*.txt (identical command + started_at, different pid) and ~/.cursor-server/data/logs/<session>/exthost*/anysphere.cursor-agent-exec/Cursor Agent Exec*.log (the same toolCallId logged three times).
  4. Focus another application for a few minutes (or let the display sleep) and watch command start times align to :01 and the approval-gate wait grow to 1–3 minutes. Focus the window again: waits drop to 0 s.

Expected Behavior

One tool call → one execution. Tool execution speed should not depend on whether the Cursor window is focused or the display is awake; with Remote-SSH, ideally the remote side keeps running background work while the client is disconnected.

Operating System

MacOS
Linux

Version Information

Cursor IDE 3.18.25
Commit: 280eca2911f1774689696e5f1efa5a4f97a87af0
Date: 2026-08-31T23:08:02.261Z
Client OS: macOS 26.6.2 (Intel)
Remote: cursor-server (same commit) on Ubuntu Linux x86_64, kernel 6.8, connected via Remote-SSH

For AI issues: which model did you use?

Parent agent: Claude Fable 5.1 (300k context, thinking, max effort). Subagents: Claude Fable 5.1 (model: inherit) and gpt-5.6-sol-max; explore subagents on gpt-5.6-luna-max / gpt-5.6-terra-max (3 of 5 of those died with resource_exhausted).

For AI issues: add Request ID with privacy disabled

Privacy mode is enabled on this account, so no Request IDs with privacy disabled. Happy to share IDs privately.
Parent conversation (composer) id: 7aa03266-6c85-409b-ae10-31430e522e64
Affected subagent conversation id: 71c05adc-27a8-4cb5-9401-18fe38385aa6 (the triplicated toolCallId above belongs to it).

Additional Information

Numbers from one day (2026-09-02), remote host logs:

  • distinct background shell commands: 142; executed 3x: 71, 2x: 15, 5x: 1
  • approval gate wait (reached → allowed) for auto-approved commands: median 60 s, p90 180 s; 52 of 136 calls had 0 s wait, all in periods when the window was focused
  • permissionsService.shouldBlockFileRead still not completed after 3000ms: 196 warnings; shouldBlockWrite: 90
  • AbortError … $cancelAgentExecProviderStream on foreground shells: 10:46:02, 10:48:02, 10:49:02 … one per minute at :02 while unfocused
  • subagent completion → parent’s next command: 5–27 minutes (16 samples)

Workarounds we ended up with: flock -n around every mutating command, background mode + reading the terminal file instead of foreground Shell, and keeping the Cursor window in front. Logs available on request.

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey, thanks for the detailed report. The logs and numbers made this a lot easier to dig into.

Both behaviors aren’t intended, and it’s not something in your setup. The slowdown when the window isn’t active is background timer throttling from the OS or runtime. It affects every tool call step approval gate, permission checks, exec stream. This is a known class of issues we’re tracking. See similar threads: Agents hang when window is not in focus and Cursor agent shell loses output when window loses focus (macOS). The command duplication is related to the same thing. When starting a tool call gets delayed under throttling, the client retries the request, and the already running background command doesn’t get cancelled before the retry goes out. That’s how you end up with multiple PIDs for one toolCallId. I’ve passed both points to the team. I can’t share an ETA yet, I’ll post in the thread when there’s an update.

Until it’s fixed, a practical workaround is to keep the Cursor window visible on screen not minimized and not on a hidden desktop, and prevent the display from sleeping while subagents are running. Your flock -n approach is a reasonable safety net for now.

About the disconnect killing subagents. With the current Remote SSH architecture, that’s expected. The agent loop and exec depend on an active connection, so if SSH drops, background work won’t keep running on its own. That’s a separate issue we’re also tracking.

One more thing. It looks like your forum account might not be the one used for the session. If you DM me the email you use to sign in to Cursor, or share Request IDs privately, I can pass your session to the team for debugging.