[BUG] Desktop app artifact-preview renderer balloons to 7.6 GB, driving the macOS memory pressure that makes the Claude Code daemon evict background sessions
Environment
- Claude desktop app: 1.18286.0 (macOS)
- Claude Code CLI: 2.1.199
- OS: macOS 26.5.1 (25F80), arm64, 16 GB RAM
- Heavy
claude agentsuser: ~10–15 concurrent background sessions, ~70 local sessions total on disk
Summary
Two Anthropic products form a self-inflicted feedback loop on the same machine:
- A desktop-app renderer ballooned to a 7.65 GB real footprint (mostly compressed by macOS, so it's invisible in
psRSS — onlytop -o mem/footprintshow it). Timeline evidence points at the claude.ai/code artifact HTML-preview window: the renderer spawned within a minute of[Preview] Created Claude page previewfor an artifact (a static HTML page of inline SVGs), then sat open ~4.7 h with the app's periodiccapturePreviewScreenshotIfChangedrunning against it. - That pushes
kern.memorystatus_vm_pressure_levelto 2 (warn). - The Claude Code daemon (
claude daemon) treats that as low memory (evictions correlate with pressure level ≥ 2 regardless of free bytes — see Evidence) and retires settled bg workers on every new spawn. - Net effect: background sessions "randomly disconnect" 40–75× per day. The daemon log shows 225 eviction events over 4 days, firing with 58–250 MB free.
- This also breaks mobile Remote Control: an evicted session drops off the roster and does not restart, so from the phone it just goes unreachable — the mobile app offers no way to revive it; the only workaround is a shell on the host (e.g. ssh) to resume it via
claude agents.
The daemon's eviction behavior is reasonable in isolation; the desktop app being the dominant source of the pressure is the bug. Users experience it as "my bg sessions keep dying," with no visible culprit because the renderer's RSS looks tiny.
Evidence
Renderer footprint (window sat idle, untouched for hours):
$ top -l 1 -o mem -stats pid,mem,command
PID MEM COMMAND
80601 7655M Claude Helper (R ← desktop app renderer, ~4h40 old
ps RSS for the same process read ~0–331 MB — macOS had compressed the heap (system compressor held ~28 GB of data in 7.2 GB at the time).
Renderer identity — the artifact preview window (~/Library/Logs/Claude/main.log): the ballooned renderer spawned at ~09:35 (from its etime); the only window creation in that interval is:
2026-07-03 09:34:31 [info] [Preview] Created Claude page context { serverId: 'html-preview-…', totalContexts: 1 }
2026-07-03 09:34:31 [info] [Preview] Created Claude page preview { serverId: 'html-preview-…' }
2026-07-03 09:34:31 [warn] [Preview] capturePreviewScreenshotIfChanged failed: {
The previewed artifact was a self-contained static HTML page (an icon-comparison grid of inline SVGs) — nothing that should grow, yet the renderer reached 7.65 GB and no [Preview] destroy event ever fired. For contrast, the app's main renderer (session sidebar, same uptime) stayed at ~660 MB.
Daemon evictions driven by that pressure (~/.claude/daemon.log):
[2026-07-03T11:58:21] [bg] bg: low memory (92MB free) — retiring settled workers before spawning 6cf7960f
[2026-07-03T12:01:53] [bg] bg: low memory (131MB free) — retiring settled workers before spawning 851b7308
225 occurrences over 4 days (75 on 06-30, 49 on 07-01, 61 on 07-02, 40 on 07-03).
Causality confirmed: killing renderer PID 80601 dropped kern.memorystatus_vm_pressure_level from 2 → 1 within seconds, and the evictions stopped.
The trigger tracks the macOS pressure level, not free bytes: evictions fired at free-RAM values anywhere from 58 MB to 1.3 GB (median ~150 MB), but correlate exactly with kern.memorystatus_vm_pressure_level >= 2 — including the instant recovery when the renderer died. This matches the memory-pressure reaping behavior described in the 2.1.193 release notes and #73440.
Expected behavior
- An artifact preview of a static HTML page should not grow without bound; the preview renderer should be bounded, and an idle preview window should be unloaded or its capture loop stopped.
- Ideally the daemon's low-memory threshold would be user-tunable and documented (like
CLAUDE_CODE_DISABLE_BG_SHELL_PRESSURE_REAPis for background shells) — but fixing the renderer leak removes the trigger.
Related issues (searched — none report this loop)
- #73440 — same memory-pressure trigger family, different victim: the memory-pressure reaping of background shell commands added in 2.1.193 (per the release notes) killing active
run_in_backgroundtasks. - #72719 — bg workers crash-loop under memory pressure, misreported as "exit 1 before init".
- #62048 — desktop app OOM on 8 GB M2 from the hardcoded 4 GB VM; a different desktop memory mechanism (the always-warm Cowork VM also contributes ~1.1 GB here).
- #73631 — daemon-side accumulation of stale "done" sessions.
None identify a desktop renderer as the pressure source, nor the RSS-vs-compressed-footprint blindspot that hides it.
Steps to reproduce
- On a 16 GB Mac, keep ~10 concurrent background sessions running (visible in
claude agents). - In the Claude desktop app, open a claude.ai/code artifact HTML preview and leave that window open for several hours.
- Watch
top -o mem: the preview renderer's footprint climbs into the GBs whilepsRSS stays small. - Watch
~/.claude/daemon.log: every bg spawn logsbg: low memory — retiring settled workers, and previously-settled bg sessions drop offclaude agents.
---
Edit: the initial version attributed the balloon to the main window mirroring local sessions; log-timeline analysis shows the ballooned renderer was the artifact HTML-preview window (the main renderer stayed at ~660 MB). Body corrected accordingly.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗