[BUG] Claude Desktop (macOS): instances quit silently — clean beforeQuit, no crash report, not memory, active window always survives

Status Open
Reported on v2.1.219
Maintainer reply None cached
Activity 3 comments · opened Jul 25, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

NOTE: This is a Claude Desktop bug, not Claude Code CLI. Filing here per the guidance that Desktop issues belong in this repo with the external label.

I run multiple Claude Desktop windows as my normal workflow (3-4 at a time). Windows quit themselves with no error, no crash dialog and no warning — the window simply disappears.

The consistent pattern: it is almost always a window I am NOT actively typing in. The window with focus survives; idle ones die. 17 quit events in a single day.

Environment:

  • Claude Desktop 1.24012.9
  • macOS 26.5 (25F71)
  • MacBook Pro M3 Pro, 18GB RAM

Instance lifetimes are inconsistent, so it does not appear to be a fixed timer:

launched 17:47  ->  quit 17:51   (~3.5 min)
launched 18:00  ->  quit 18:03   (~2.5 min)
launched 18:04  ->  quit 18:20   (~16 min)

What Should Happen?

Instances should stay open until the user closes them.

If the app is deliberately terminating an instance, the reason should be logged. At present main.log records a full graceful shutdown with no preceding entry indicating any trigger, which makes this impossible to diagnose or work around.

Error Messages/Logs

Every quit is a clean, deliberate shutdown — not a crash:

18:23:54 [info] Successfully run onQuitCleanup: cowork-vm-shutdown
18:23:54 [info] Successully ran all onQuitCleanup handlers, marking readyForQuit
18:23:54 [info] beforeQuit: handler fired, going down
18:23:54 [info] beforeQuit: handler is ready for quit, so quitting
18:23:54 [info] [EventLogging] Flushing 1 events
18:23:54 [info] willQuit: handler fired, going down
18:23:54 [info] willQuit: handler is ready for quit, so quitting

All cleanup handlers run, exit code 0. Nothing is logged in the 20+ seconds beforehand — no error, no warning, no trigger. Silence, then shutdown.

Memory reading from the app's own telemetry at the last quit:
tree_rss_sum=1286MB  sys_free=... sys_free_raw=1784MB

1.7GB genuinely free, zero swap in use.

Also seen with multiple instances open:
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 listeners added to [EventEmitter]
  ...claude.settings_$_AppPreferences
  ...claude.web_$_AutoUpdater_$_updaterState
  ...claude.web_$_LocalAgentModeSessions

Steps to Reproduce

  1. Open Claude Desktop normally
  2. Open additional instances from Terminal: open -n -a Claude (repeat for 3-4 total)
  3. Work in one window and leave the others idle
  4. Within a few minutes one or more idle windows quits itself, with no warning or error shown
  5. Check ~/Library/Logs/Claude/main.log — a clean beforeQuit / willQuit / onQuitCleanup sequence with exit code 0
  6. Check ~/Library/Logs/DiagnosticReports — no crash report and no jetsam report exists
  7. Check ~/Library/Application Support/Claude/Crashpad/pending — empty

Happens on a fresh boot with several GB free and zero swap in use.

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

Claude Desktop 1.24012.9 (CCD 2.1.219) — not Claude Code CLI

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

What I ruled out

  • Not a crash. Zero entries in ~/Library/Logs/DiagnosticReports. Crashpad pending folder empty.
  • Not an OOM kill. No jetsam reports. Last quit occurred with 1.7GB free and zero swap.
  • Not general memory pressure. Removed ~2GB of other apps and rebooted after 33 days uptime. Swap went to zero, wired memory dropped from 2.97GB to 1.76GB. Quits continued.
  • Not a stale bridge session. Found bridge-state.json pinning a dead remoteSessionId, retrying and failing 68 times in 45 minutes (Transport permanently closed code=4090, AcknowledgeWork: Conflict (409): Work item must be in QUEUED state). Deleting the file took transport failures to zero and instances survived noticeably longer — but quits still occur.
  • Not user-initiated. Individual windows die while others stay open, so a global quit action cannot explain it.
  • Not a modified install. Single Claude.app, signed by Anthropic (TeamIdentifier Q6L2SF6YDW).

Related observations

  • [WarmLifecycle:cowork] Initialized (arm=always) fires on every launch. The Cowork VM starts whether or not Cowork is used, sits at 1.1-1.9GB and grows through the day. There is no user-facing way to disable it on an individual plan — the only toggle is org-level (Team/Enterprise).
  • trigger=stall fires on every newly launched instance.
  • All instances write to a single shared main.log, which makes attributing a quit to a specific instance impossible.

Requests

  1. Log the reason an instance quits — there is currently nothing actionable.
  2. Provide a way to disable the Cowork VM on individual plans for users who don't use Cowork.
  3. Clarify whether multiple instances are a supported configuration.

Possibly related but not a duplicate: #23092 (SessionIdleManager 300s idle quit). I checked — SessionIdleManager, lam_vm_shutdown_completed and was_killed do not appear anywhere in my logs, and my instance lifetimes are inconsistent rather than a fixed 300s. Likely a different mechanism.

Happy to provide the full main.log on request.

View original on GitHub ↗

3 Comments

Maizeak · 1 month ago

Additional context on the regression question.

This began after Cowork was integrated into the main desktop app. Before that I ran 3-4 instances routinely as my standard workflow with no instability at all. I can't pin an exact version number, but the change in behaviour tracks with that integration rather than with any change on my machine.

claude-main.log

Two things that may help narrow it down:

The Cowork VM is armed on every launch regardless of use. [WarmLifecycle:cowork] Initialized (arm=always) appears at every startup. I have never opened Cowork in these sessions. The VM process sits at 1.1-1.9GB and grows over the course of a day. With no way to disable it on an individual plan, every extra instance carries that cost whether the feature is wanted or not.

Instances that stay focused survive indefinitely. One instance in my logs ran for over three hours without issue while others launched alongside it died within minutes. That asymmetry seems like the most useful clue — whatever terminates them appears to discriminate by activity or focus, but nothing in main.log records the decision.

Happy to run any diagnostic that would help, or to provide the full log for the day (13:03-18:30, 17 quit events).

Maizeak · 1 month ago

Useful for anyone else debugging this: DESKTOP_LOG_LEVEL=debug unlocks far more diagnostic output

From index.chunk-CnWKsyE_.js:

const u1e = process.env.DESKTOP_LOG_LEVEL ?? (app.isPackaged ? "info" : "debug")

Launching the binary directly with the variable set turns on debug logging in packaged builds:

DESKTOP_LOG_LEVEL=debug /Applications/Claude.app/Contents/MacOS/Claude

This adds several hundred debug lines to main.log, including a full dump of every GrowthBook feature gate with its resolved state (466 gates in my case, in the form [growthbook] <id>: on=true|false value=... source=...). That makes it possible to check whether a given feature is actually enabled for your account rather than guessing.

A candidate I was able to rule out with it:

app.asar contains a stealth auto-update scheduler (scheduleRestartWhenIdle, class with const w7e=600*1e3) whose logic matches this bug's symptom closely — idleBlocker() returns "window focused" and reportWindowFocus() cancels the countdown, so a focused window would never be restarted while blurred ones would be quit and reinstalled after 10 minutes. There is also a [stealth-relaunch] path that saves navigation history to a marker file before app.quit().

It is gated behind 3691521536. With debug logging on, my dump shows:

[growthbook]   3691521536: on=false value=false source=defaultValue

So stealth update is not the cause here — at least not for my account. Recording it so nobody else spends time on the same lead.

Suggestion for the app: whatever terminates an instance should log the reason at info level. main.log currently records a complete beforeQuitonQuitCleanupwillQuit sequence with no preceding entry explaining the trigger, which makes this effectively undiagnosable from the outside. A single line naming the caller would have resolved this in seconds.

I now have an instance running with DESKTOP_LOG_LEVEL=debug and will post the debug output from the next quit.

Maizeak · 1 month ago

Update after 24 hours of monitoring — this looks like singleton contention between instances, not resources. Reproducible at exactly the third instance.

I ran a monitor overnight sampling every 2 minutes. New findings:

Memory is conclusively ruled out

Two instances ran continuously for 13h50m and 13h43m overnight. During that window sys_free_raw repeatedly dipped as low as 70MB (samples at 0.07GB, 0.10GB, 0.11GB, 0.13GB). Neither instance quit. If low memory triggered these quits, they would have died many times over.

The failure is deterministic at the third instance

Two instances: stable indefinitely. Launch a third and something quits within ~10 seconds:

09:52:41  Starting app        (3rd instance)
09:52:51  beforeQuit          <- 10s later
09:53:51  beforeQuit
09:53:52  Starting app
09:59:02  beforeQuit
10:00:03  beforeQuit + Starting app

Memory at those quits: sys_free_raw=766MB and sys_free_raw=272MB. Not exhaustion.

What the third instance's startup actually does

This is the part that looks like the bug. During the third instance's initialisation:

[Restore] Skipping local_5577450a-745d-4da2-b583-c77e3dd08990 — live session already in memory
[Restore] Skipping local_61c62b5c-b03f-4e70-b9f1-ee24d00e7aa7 — live session already in memory
[Restore] Skipping local_4b985e03-f4d8-4c89-aaa0-b599ebe6f42b — live session already in memory
   ... ~25 further sessions skipped, same reason ...
[warn] [ScheduledTasks] Already initialized
[info] [LocalAgentModeSessionManager] Scheduled tasks service initialized
[info] [WarmLifecycle:cowork] Destroyed          <- during another instance's launch
[info] [ScheduledTasks] Reset

So a newly launching instance:

  1. Finds ~25 local agent sessions already live and declines to restore them
  2. Hits [ScheduledTasks] Already initialized — a shared service it cannot claim
  3. Destroys the Cowork warm VM and resets ScheduledTasks, which the already-running instances are using

Then, seconds later, an instance quits.

Together with the previously reported MaxListenersExceededWarning: 11 listeners on AppPreferences, AutoUpdater updaterState and LocalAgentModeSessions, and the fact that all instances write to one shared main.log, the picture is that session state, scheduled tasks and the Cowork VM are effectively process-global singletons. Two instances tolerate sharing them. A third cannot initialise without tearing down state the others depend on, and one of them exits.

This would explain why the quit is always graceful with no logged reason — from the quitting instance's perspective nothing failed. It would also explain why this began when Cowork was integrated, since the shared VM and the session manager arrived with it.

Useful diagnostic for anyone reproducing this

DESKTOP_LOG_LEVEL is read at startup and overrides the packaged default of info:

const u1e = process.env.DESKTOP_LOG_LEVEL ?? (app.isPackaged ? "info" : "debug")
DESKTOP_LOG_LEVEL=debug /Applications/Claude.app/Contents/MacOS/Claude

That adds several hundred debug lines including a full dump of every GrowthBook gate with its resolved state (466 in my case), which is how I eliminated one candidate: app.asar contains a stealth restart scheduler (scheduleRestartWhenIdle, 600s idle timeout, cancels on window focus) that matches the symptom well, but its gate reads on=false for my account, so it is not the cause here.

Also ruled out since the original report

  • Automatic Termination / TAL — the _kLSApplicationWouldBeTerminatedByTALKey=1 events occur after the quit begins, so they are a consequence of teardown, not the trigger.
  • Third-party software — removing an antivirus suite entirely made no difference; quits continued for 55 minutes afterwards.
  • Version mismatch between instances — only the first launch of the day ran an older build.

Suggested fix direction

Either make ScheduledTasks, LocalAgentModeSessionManager and the Cowork warm VM safe for N instances, or have a launching instance detect existing instances and skip re-initialising shared services rather than resetting them. Failing that, a clear statement that multiple instances are unsupported would at least let users stop at two deliberately.

Happy to provide the overnight monitor log or run any further diagnostic.