[BUG] Desktop (Windows): shell PTYs started on session warm are not stopped when the session is paused by idle timeout; preview lifecycle opens a second PTY per session

Status Open
Reported on v2.1.260
Maintainer reply None cached
Activity 0 comments · opened Sep 9, 2026

What's Wrong?

When a session is warmed, the app calls LocalSessions.startShellPty and spawns a powershell.exe (+ a headless conhost.exe) for the session's Terminal panel. When the session is later paused by the 900 s idle timeout ([CCD] Pausing session … (idle_timeout)), the CLI and its MCP servers exit but the PTY shell is left running.

Today 10 sessions were warmed at 11:51 and paused between 12:06 and 12:08. At 12:14 all 10 powershell.exe PTYs were still alive (parent = the app's NodeService utility process, ~70 MB each, ~700 MB total plus 10 conhosts). Most disappeared only around the 1800 s preview timeout; 3 of the 10 were still alive 40 minutes after launch, long after their sessions had been paused.

Additionally, when the user returns to an already-warm session, [WarmLifecycle:preview] Warming up session X fires and a second startShellPty is issued for the same session (seen for 4 sessions), so a session can hold two shells.

What Should Happen?

  • pauseSession(…, "idle_timeout") (and governor_evict) should also call stopShellPty for that session, or the PTY should be started lazily when the Terminal panel is actually opened, not at warm time.
  • Re-warming a session that already has a live PTY should reuse it rather than starting another.

Error Messages/Logs

%LOCALAPPDATA%\Claude\logs\main.log:

11:51:01 [CCD] Warming session local_c28c…
11:51:02 LocalSessions.startShellPty: sessionId=local_c28c…, cols=80, rows=24
11:51:29 [WarmLifecycle:preview] Warming up session local_c28c…
11:51:29 LocalSessions.startShellPty: sessionId=local_c28c…, cols=80, rows=24      <- second PTY, same session
...
12:07:42 [WarmLifecycle:session] Idle timeout reached, disconnecting local_c28c…
12:07:42 [CCD] Pausing session local_c28c… (idle_timeout)                         <- no stopShellPty follows

Process list at 12:14 (parent 26464 = Claude.exe --type=utility --utility-sub-type=node.mojom.NodeService):

PID    PPID   Name            WS_MB  Started   CommandLine
10704  26464  powershell.exe   70.0  11:51:15  C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe
10804  26464  powershell.exe   69.7  11:51:10  (same)
12220  26464  powershell.exe   69.8  11:52:24  (same)
12732  26464  powershell.exe   69.6  11:51:04  (same)
17928  26464  powershell.exe   69.6  11:51:29  (same)
20168  26464  powershell.exe   69.9  11:54:16  (same)
22864  26464  powershell.exe   69.8  11:52:52  (same)
25668  26464  powershell.exe   70.4  11:51:20  (same)
26944  26464  powershell.exe   69.6  11:51:21  (same)

Each has a matching conhost.exe --headless --width 80 --height 24 child (~9 MB).

Steps to Reproduce

  1. Windows 11, Claude Desktop (MSIX), Code tab.
  2. Click a few idle sessions in the sidebar so they warm; do not type anything.
  3. Wait > 15 minutes for Pausing session … (idle_timeout) in main.log.
  4. Get-CimInstance Win32_Process -Filter "Name='powershell.exe'" still shows one bare powershell.exe per warmed session, parented by the app's NodeService process.

Claude Code Version

Desktop app 1.49585.0.0 (MSIX); bundled Claude Code 2.1.260.

Platform

Claude.ai subscription (OAuth) via the desktop app.

Operating System

Windows 11 Pro 10.0.26200.

Terminal/Shell

Windows PowerShell 5.1 (the PTY the app spawns).

Additional Information

Related: focusing a session (including archived ones) eagerly warms the full CLI + MCP stack (filed separately); the two together are what made the machine crawl.

View original on GitHub ↗