Claude Desktop scheduled tasks: completed sessions never exit — unbounded memory accumulation (~0.5–0.8 GB/hr)

Resolved 💬 2 comments Opened Jun 12, 2026 by nigel-design Closed Jun 15, 2026

Summary

Claude Desktop's local scheduled tasks ([CCDScheduledTasks]) spawn a new Claude Code session for every task fire, and completed sessions never exit. On a machine running frequent scheduled tasks this accumulates unboundedly (~0.5–0.8 GB resident per awake hour) until Claude Desktop is restarted, driving a 16 GB Mac into sustained memory-pressure WARN and heavy swap/compressor thrash.

Environment

  • macOS 26.5.1 (build 25F80), Apple M5, 16 GB RAM
  • Claude Desktop 1.12603.1
  • Claude Code (bundled runtime) 2.1.170
  • ~13 enabled local scheduled tasks; the most frequent fires every 10–15 min during the day, two others half-hourly on weekdays

What happens

Each scheduled fire is logged by Claude Desktop as [CCDScheduledTasks] Spawning new session for scheduled task <id> in ~/Library/Logs/Claude/main.log, and spawns a disclaimer wrapper (~600 KB) + a claude binary (100–250 MB RSS) parented to the Desktop process. The task completes in well under a minute, but the session process remains resident indefinitely, in state S at ~0% CPU.

Measured over one 5h18m Desktop uptime window (2026-06-10):

  • 27 sessions spawned, 27 still resident (100% survival; zero exits)
  • Spawn timestamps match the task schedule to the second (ps lstart vs lastRunAt vs main.log)
  • Total: 3.4 GB RSS + ~3.3 GB more in the compressor ≈ 5.7 GB footprint (36% of RAM) of idle, finished sessions
  • Each idle session retains a ~175 MB dirty WebKit/JS heap (footprint "WebKit malloc"), which can only be compressed/swapped, not paged to file
  • System effect: kernel memory pressure level 2 (WARN), ~67–170 MB truly free, compressor churning ~170 MB/s at idle, 75 GB written to swap over 31h uptime (≈⅓ of all disk writes)

Each retained session also keeps private copies of its MCP/plugin child processes (e.g. the pdf plugin's npm+node pair, ~21 MB per session), so the MCP fleet multiplies with the leak.

The session records in ~/.claude/sessions/<pid>.json register these scheduled runs as kind: "interactive", entrypoint: "claude-desktop", with no end/completed marker — the Desktop appears to treat each cron-style run as an open interactive session it keeps alive. No retention/cleanup setting was found in settings.json, settings.local.json, or the Desktop config.

Expected

Scheduled-task sessions should run and exit (or be reaped shortly after completion), like a cron job. At minimum, a retention setting or an idle-session reaper.

Repro

  1. Claude Desktop on macOS with local scheduled tasks enabled (ccdScheduledTasksEnabled: true)
  2. Create a scheduled task on a */10 cron
  3. Watch ps -axo rss,etime,command | grep claude-code grow by one ~100–250 MB process per fire; none exit until the Desktop app quits

Workaround in use

Nightly launchd-driven Claude Desktop restart in a window with no scheduled fires, with a relaunch check (the scheduler lives in-app, so a failed relaunch silently stops all automations). Restart reclaims ~5–7 GB.

View original on GitHub ↗

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