[BUG] Claude Code memory leak causing repeated crashes with Opus 4.6
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?
To Reproduce:
(version 2.1.71 - 2.1.74 have all done the same)
- Open 4 Opus/Sonnet chats and use them for 2-3 hours swapping between them.
- Track the memory usage by these processes (track the PID)
- The memory usage will continue to grow until either the Claude (engine) crashes for all 4 at once or the system crashes.
Bug Description
I use largely Claude Code. Recently (last 3 weeks or so), I have started heavy use of Opus 4.6 (medium). It keeps crashing from a memory leak filling up available memory. It is leaving zombie processes that slowly eat up virtual and RAM memory it needs. I have written a prompt to clean it, but I have taken to rebooting often and documenting progress and logs in notepad because Claude is unstable and loses its progress when it crashes. It has crashed about 15 times in last 5 days, even with reboots, resets, memory cleans. here is recent good output from a cleanup command: ---
CLEANUP REPORT
Claude:
Status: normal
Private: 1748 MB / 4096 MB (ok)
Handles: 1417 (ok)
Action: none
Zombies: 0 found
Docker:
Status: not running (skipped)
Containers: n/a
Images: n/a
Volumes: n/a
Temp files: none (venv caches only, left intact)
Claude logs: 19.7 MB (under 20 MB threshold, no trim)
Memory: 17.2 GB free / 31.7 GB total (committed: 21.3 GB)
Disk recovered: 0 GB (system already clean)
Everything looks healthy. Run /cleanup again anytime.
Environment Info
Platform: win32
Terminal: windows-terminal
Version: 2.1.71
Feedback ID: 0e8459c7-44de-4ca2-8558-bcd6fb6edbf5
=========== Actual command used for /cleanup
System & Claude Cleanup
##NOTE: username actual replaced with [UserName]
Clean up Docker resources, zombie processes, Claude memory leaks, and reclaim disk/memory.
Windows PowerShell Command Pattern
CRITICAL: Never pass multi-line PowerShell via -Command "..." — bash will expand $variables
before PowerShell sees them, corrupting the script. Always use this pattern:
- Write the script to a temp
.ps1file using the Write tool - Execute with:
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "C:\...\script.ps1"
All multi-line PowerShell steps below must use this pattern.
Instructions
Run the following cleanup steps in order. Report results after each step.
Step 1: Claude Desktop Memory Leak Check
Write this script to C:\Users\[UserName]\AppData\Local\Temp\check_claude.ps1 then execute it:
$procs = Get-Process -Name 'claude' -ErrorAction SilentlyContinue
if ($procs) {
$main = $procs | Sort-Object PrivateMemorySize64 -Descending | Select-Object -First 1
$mainPrivMB = [math]::Round($main.PrivateMemorySize64 / 1MB)
$totalPrivMB = [math]::Round(($procs | Measure-Object PrivateMemorySize64 -Sum).Sum / 1MB)
$totalHandles = ($procs | Measure-Object HandleCount -Sum).Sum
Write-Host "CLAUDE MEMORY STATUS"
Write-Host " Processes: $($procs.Count)"
Write-Host " Main Private: $mainPrivMB MB $(if($mainPrivMB -gt 4096){'!! LEAKED'}else{'(ok)'})"
Write-Host " Total Private: $totalPrivMB MB"
Write-Host " Handles: $totalHandles $(if($totalHandles -gt 3000){'!! HANDLE LEAK'}else{'(ok)'})"
$procs | Sort-Object PrivateMemorySize64 -Descending |
Select-Object Id,
@{N='RAM_MB';E={[math]::Round($_.WorkingSet64/1MB)}},
@{N='Priv_MB';E={[math]::Round($_.PrivateMemorySize64/1MB)}},
HandleCount, Responding |
Format-Table -AutoSize
} else {
Write-Host "Claude not running"
}
Execute with:
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "C:\Users\[UserName]\AppData\Local\Temp\check_claude.ps1"
If main process private bytes > 4096 MB OR handles > 3000, tell the user:
- Memory leak detected — recommend running the full cleanup script
- Ask: "Run
claude-cleanup.ps1to kill and restart Claude? (This will close any open conversations)"
If user confirms, run:
powershell.exe -ExecutionPolicy Bypass -File "C:\Users\[UserName]\Documents\Claude\Scripts\claude-cleanup.ps1"
If memory is normal, report "Claude memory OK" and continue to next steps.
Step 2: Kill Zombie Python Processes
This is a single-line command — safe to use -Command:
powershell.exe -NoProfile -Command "Get-Process python*, Python* -ErrorAction SilentlyContinue | Select-Object Id, ProcessName, @{N='CPU';E={[math]::Round($_.CPU,1)}}, @{N='MemMB';E={[math]::Round($_.WorkingSet64/1MB)}}, Path | Format-Table -AutoSize"
Ask the user before killing any processes. Safe to kill:
- Orphaned pytest workers
- Stale uvicorn/FastAPI processes not in Docker
- JPype/COMSOL processes from crashed sessions
Do NOT kill:
- IDE Python language servers
- Docker-managed Python processes
- The user's active terminal session
Step 3: Docker Cleanup
Show current Docker disk usage:
docker system df
Then run cleanup commands:
docker container prune -f
docker image prune -f
docker builder prune -f
WARNING: Before pruning volumes, warn the user that this deletes MongoDB data.
Only prune volumes if the user confirms:
docker volume prune -f
For a full nuclear cleanup (user must confirm):
docker system prune -a --volumes -f
Step 4: Temp File Cleanup
List Python caches:
powershell.exe -NoProfile -Command "Get-ChildItem -Path 'D:\LocalGitRepos\OCD-Local' -Recurse -Directory -Filter '__pycache__' -ErrorAction SilentlyContinue | Select-Object -First 20 FullName | Format-Table -AutoSize"
Check COMSOL temp files (single-line, safe to use -Command):
powershell.exe -NoProfile -Command "Get-ChildItem -Path $env:TEMP -Filter 'comsol*' -ErrorAction SilentlyContinue | Select-Object Name, Length, LastWriteTime | Format-Table -AutoSize"
Step 5: Claude Log & Cache Cleanup
Write this script to C:\Users\[UserName]\AppData\Local\Temp\claude_logs.ps1 then execute it:
$logPath = "$env:APPDATA\Claude\logs"
Write-Host "CLAUDE LOG SIZES:"
if (Test-Path $logPath) {
$files = Get-ChildItem $logPath -File -ErrorAction SilentlyContinue
$files | Sort-Object Length -Desc |
Select-Object Name, @{N='MB';E={[math]::Round($_.Length/1MB,1)}} |
Format-Table -AutoSize
$total = [math]::Round(($files | Measure-Object Length -Sum).Sum / 1MB, 1)
Write-Host "Total logs: $total MB"
} else {
Write-Host "Log path not found: $logPath"
}
If total logs > 20 MB, write this trim script to C:\Users\[UserName]\AppData\Local\Temp\trim_logs.ps1:
$logPath = "$env:APPDATA\Claude\logs"
$before = [math]::Round((Get-ChildItem $logPath -File | Measure-Object Length -Sum).Sum / 1MB, 1)
Write-Host "Before: $before MB"
Get-ChildItem $logPath -File | Where-Object { $_.Length -gt 5MB } | ForEach-Object {
try {
$tail = Get-Content $_.FullName -Tail 200 -Encoding utf8 -ErrorAction Stop
$tail | Set-Content $_.FullName -Encoding utf8 -Force
Write-Host "Trimmed: $($_.Name)"
} catch {
Write-Host "Skipped (locked): $($_.Name)"
}
}
$after = [math]::Round((Get-ChildItem $logPath -File | Measure-Object Length -Sum).Sum / 1MB, 1)
Write-Host "After: $after MB"
Execute each script with:
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "C:\Users\[UserName]\AppData\Local\Temp\claude_logs.ps1"
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "C:\Users\[UserName]\AppData\Local\Temp\trim_logs.ps1"
Step 6: Memory Check
Write this script to C:\Users\[UserName]\AppData\Local\Temp\mem_check.ps1 then execute it:
$os = Get-CimInstance Win32_OperatingSystem
$totalGB = [math]::Round($os.TotalVisibleMemorySize / 1MB, 1)
$freeGB = [math]::Round($os.FreePhysicalMemory / 1MB, 1)
$commitGB = [math]::Round(($os.TotalVirtualMemorySize - $os.FreeVirtualMemory) / 1MB, 1)
$totalVirtGB = [math]::Round($os.TotalVirtualMemorySize / 1MB, 1)
Write-Host "SYSTEM MEMORY:"
Write-Host " Total: $totalGB GB"
Write-Host " Free: $freeGB GB"
Write-Host " Committed: $commitGB GB / $totalVirtGB GB"
Write-Host ""
Write-Host "TOP 15 BY MEMORY:"
Get-Process | Sort-Object WorkingSet64 -Desc | Select-Object -First 15 ProcessName,
@{N='MemMB';E={[math]::Round($_.WorkingSet64/1MB)}}, CPU |
Format-Table -AutoSize
Execute with:
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "C:\Users\[UserName]\AppData\Local\Temp\mem_check.ps1"
Response Format
CLEANUP REPORT
------------------------------
Claude:
Status: <normal / LEAKED / restarted>
Private: <main process MB> / 4096 MB
Handles: <count> (<status>)
Action: <none / restarted / user declined>
Zombies: <killed count> / <found count>
Docker:
Containers: <pruned count>
Images: <reclaimed size>
Build cache: <reclaimed size>
Volumes: <pruned or skipped>
Temp files: <cleaned count>
Claude logs: <before MB> -> <after MB>
Memory: <free GB> / <total GB> (committed: <X> GB)
------------------------------
Disk recovered: <total GB reclaimed>
Then say: "Cleanup complete. Run /cleanup again anytime."
What Should Happen?
Not leak zombie processes that crash system.
Error Messages/Logs
Steps to Reproduce
Step 2: Kill Zombie Python Processes
This is a single-line command — safe to use -Command:
powershell.exe -NoProfile -Command "Get-Process python*, Python* -ErrorAction SilentlyContinue | Select-Object Id, ProcessName, @{N='CPU';E={[math]::Round($_.CPU,1)}}, @{N='MemMB';E={[math]::Round($_.WorkingSet64/1MB)}}, Path | Format-Table -AutoSize"
Ask the user before killing any processes. Safe to kill:
- Orphaned pytest workers
- Stale uvicorn/FastAPI processes not in Docker
- JPype/COMSOL processes from crashed sessions
Do NOT kill:
- IDE Python language servers
- Docker-managed Python processes
- The user's active terminal session
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.71
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Windows Terminal
Additional Information
I used Opus occasionally and Sonnet 4.5 a ton and did not have this issue.
This issue has 12 comments on GitHub. Read the full discussion on GitHub ↗