Claude Code Memory Leak - Process Grows to 120+ GB RAM and Gets OOM Killed

Open 💬 96 comments Opened Aug 1, 2025 by chatgpt-copypasta

Claude Code Memory Leak - Process Grows to 120+ GB RAM and Gets OOM Killed

Description

Claude Code has a severe memory leak that causes the process to grow to over 120GB of RAM before being killed by the Linux OOM killer. This happens consistently during extended coding sessions, approximately every 30-60 minutes of active use.

Environment

  • Claude Code Version: 1.0.53
  • OS: Ubuntu 24.04
  • Kernel: Linux 6.14.11
  • Total System RAM: 128GB
  • Installation Method: Direct installation in home directory

Steps to Reproduce

  1. Start Claude Code in interactive mode
  2. Use it for an extended coding session (30-60 minutes)
  3. Perform typical operations: file reading, editing, searching, running bash commands
  4. Monitor memory usage with ps aux | grep claude
  5. Process will gradually consume all available RAM until OOM killed

Expected Behavior

Claude Code should maintain stable memory usage throughout the session, not exceeding a reasonable amount (e.g., 1-2GB for typical usage).

Actual Behavior

The claude process memory usage grows unbounded until it consumes all available system RAM (120+ GB) and triggers the OOM killer.

Evidence

OOM Kill Log Entries (from dmesg):

Killed process 1983785 (claude) total-vm:234427056kB, anon-rss:124857720kB, file-rss:0kB, shmem-rss:0kB, UID:XXXX pgtables:267248kB oom_score_adj:0
Killed process 1991601 (claude) total-vm:234453364kB, anon-rss:125118596kB, file-rss:596kB, shmem-rss:0kB, UID:XXXX pgtables:267880kB oom_score_adj:0
Killed process 1997049 (claude) total-vm:234463420kB, anon-rss:125275392kB, file-rss:5856kB, shmem-rss:0kB, UID:XXXX pgtables:269168kB oom_score_adj:0
Killed process 2001723 (claude) total-vm:234420884kB, anon-rss:119597028kB, file-rss:3748kB, shmem-rss:0kB, UID:XXXX pgtables:257104kB oom_score_adj:0
Killed process 2009167 (claude) total-vm:234464008kB, anon-rss:120216960kB, file-rss:372kB, shmem-rss:0kB, UID:XXXX pgtables:252260kB oom_score_adj:0

Key observations:

  • total-vm consistently around 234GB (virtual memory)
  • anon-rss (actual RAM used) between 119-125GB
  • Multiple OOM kills in the same session indicate this is a recurring issue
  • Memory consumption appears to be primarily anonymous pages (anon-rss), not file-backed

Impact

This memory leak makes Claude Code unusable for extended coding sessions as it:

  1. Causes system-wide memory exhaustion
  2. Triggers OOM killer which terminates other processes
  3. Loses session context when Claude is killed
  4. Requires frequent restarts, disrupting workflow

Additional Information

  • The memory growth appears gradual over time, not sudden
  • The issue persists across multiple sessions
  • After OOM kill and restart, memory usage starts low (~400MB) and grows again

Potential Debugging Steps

To help diagnose this issue, the following information might be useful:

  1. Memory profiling of the claude process
  2. Heap snapshots at various points during execution
  3. Tracking of any unbounded data structures (conversation history, file caches, etc.)

Workaround

Currently, the only workaround is to periodically restart Claude Code before memory exhaustion occurs, which is highly disruptive to workflow.

---

Priority: High - This makes the tool unusable for its intended purpose of extended coding assistance

View original on GitHub ↗

96 Comments

github-actions[bot] · 11 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/3643
  2. https://github.com/anthropics/claude-code/issues/1009
  3. https://github.com/anthropics/claude-code/issues/2938

If your issue is a duplicate, please close it and 👍 the existing issue instead.

🤖 Generated with Claude Code

fsjn · 11 months ago

does this was fixed? seems to be i had that too once, the IDE showed the notification e.g. out of memory.

0bLoM · 11 months ago

I'm still having this issue regardless of where I run it. It's making CC hard to use, as it crashes machine after a while

almirsarajcic · 11 months ago

I've been having this since I started using subagents (since version ~1.0.70).
Can't use more than 2 Claude Code instances because I ONLY have 32 GB of RAM.

tg201005 · 11 months ago

me too..

0bLoM · 11 months ago

I've solevd this by commiting to memory that CC should terminate any processes it's done using. I have stopped having issues.

tg201005 · 11 months ago
I've solevd this by commiting to memory that CC should terminate any processes it's done using. I have stopped having issues.

thanks, bro. Can you explain more? Do you use CC hooks?

akhilnchauhan · 10 months ago

I am still seeing this on 1.0.98 where I've got 4 processes each taking about 2.5GB RAM

psicilia5179 · 9 months ago

Environment

  • Claude Code Version: 2.0.1 (Claude Code)
  • Claude Model: claude-sonnet-4-5-20250929
  • Platform: Linux 6.14.0-15-generic
  • RAM: 15GB
  • Swap: None

Issue Description

Claude Code process experiencing rapid memory growth leading to OOM kills. Monitoring shows memory jumps from stable baseline to crash threshold within minutes.

Memory Growth Pattern (from monitoring)

2025-10-11 18:46:48 PID:3174091 RSS:204MB VSZ:32120MB ← stable 2025-10-11 18:47:48 PID:3174091 RSS:1554MB VSZ:33467MB ← 7x jump in 60s 2025-10-11 18:48:48 PID:3174091 RSS:3967MB VSZ:35869MB ← nearly doubled 2025-10-11 18:49:48 PID:3174091 RSS:4301MB VSZ:36201MB ← crash threshold [Process killed by OOM]

Historical OOM Kills

10+ kills over 2 days (Oct 3-5):

  • Processes growing from 1.3GB → 4.3GB RSS before kill
  • Virtual memory: 33GB → 37GB range

Sample kern.log Entry

2025-10-05T14:12:52 kernel: Out of memory: Killed process 1418229 (claude) total-vm:36857676kB, anon-rss:4102880kB, file-rss:3048kB, shmem-rss:0kB, UID:1001 pgtables:119712kB oom_score_adj:0

Impact

System unusable for extended Claude Code sessions. Process requires restart every 30-60 minutes to prevent OOM.

Monitoring Setup

Created automated monitoring script logging memory every 60s to track growth patterns.

clemlesne · 8 months ago

I got a record 34 GB yesterday on my Mac M1 Max 32 GB!

leidig54 · 8 months ago

<img width="478" height="118" alt="Image" src="https://github.com/user-attachments/assets/b1e674ab-7b6b-4acc-b0e1-e55181f65f3f" />

97gb here :)

marccardinal · 8 months ago

<img width="824" height="62" alt="Image" src="https://github.com/user-attachments/assets/86c64c8c-14e5-4172-bf48-6a2f7b30bb56" />

on v2.0.27

edfactor · 8 months ago

Yesterday my claude instance got up to 107GB after a few hours of very intensive work and took down my whole machine.

bogomazov · 8 months ago

Consistently getting 130GB+

and sometimes VS Code just crashes UI

!Image

Only 2 VS Code windows are running simultaneously...

UPD. I think it was audio and ntfy hooks (asked CC to optimize them and remove ntfy)

lanmower · 8 months ago

<img width="1070" height="40" alt="Image" src="https://github.com/user-attachments/assets/0bd4228d-0b9c-42b6-a315-3d39eafdbb8c" />
Related?

lanmower · 8 months ago

My CC shows that on every startup right away

github-actions[bot] · 7 months ago

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

senkenn · 7 months ago

up

rolanday · 7 months ago

Here because i've seen it 128GB RAM and recently started getting "Your system has run out of application memory" -- it's claude code. 120GB+ !!

josefguenther · 6 months ago

On Mac it spins up dozens and dozens of claude instances each with ~250mb memory usage. I'm using the VS Code extension, and it seems to partially help to close tabs and re-open them, but only partially. It's really really annoying and leads to the system eventually filling swap to the point it's unusable and I have to reboot.

positonic · 6 months ago

This is killing my machine also with over 100 gb of memory being used by zombie processes. I agree it makes it usable....

lovrozagar · 6 months ago

up

davidbenhaim · 6 months ago

please fix <3

cybersader · 6 months ago

Can't tell if it's CC or WSL in my case

NathnC · 6 months ago

happens to me via powershell but not on wsl

dpankros · 6 months ago

This just started to hit me yesterday and today (7-Jan 26 and 8-Jan 26). Currently one command (with sub-agents) has 5 processes with 48GB, 40GB, 40GB, 31GB and 10GB used on by 64GB Mac. Using iTerm2, if it matters.

serefarikan · 6 months ago

For me, the problem emerges when I'm using agents. I have a command that starts an agent a number of times and claude ram usage goes from ~500MB to 25GB. The memory explosion happens during a random turn, i.e. the same agent runs for five times, no problem, then it blows the memory on 6th and claude code prints out Aborted() then it gets into a hung state. Sometimes it happens only at the second, third run of the same agent. You get the idea. This is claude code running under a docker container, backed by WSL2 on Windows 10 professional.

If I run the command that is run by the agent (the one that is run repeatedly by the original, root command) manually, then I have no problems. So this is what's failing:
Command X -> [Agent -> Command Y] (1..* times)

and this is what's working without any problems :
Human user -> Command Y (1..* times)

luison · 6 months ago

Similar here, just on a quite simple session in Debian 12

2026-01-15T10:15:29.621397+01:00 d22-bak kernel: [ 4274.306390] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=unattended-upgrades.service,mems_allowed=0,global_oom,task_memcg=/user.slice/user-1000.slice/session-1.scope,task=claude,pid=6910,uid=0
2026-01-15T10:15:29.621398+01:00 d22-bak kernel: [ 4274.307076] Out of memory: Killed process 6910 (claude) total-vm:60651380kB, anon-rss:31224120kB, file-rss:2432kB, shmem-rss:0kB, UID:0 pgtables:71052kB oom_score_adj:0
2026-01-15T10:15:31.225465+01:00 d22-bak kernel: [ 4276.586764] oom_reaper: reaped process 6910 (claude), now anon-rss:0kB, file-rss:232kB, shmem-rss:0kB

luison · 5 months ago

In my case, the memory issue (on the latest occasion) was caused by Claude Code attempting to read block device files directly (/dev/sda5, /dev/sdb5 - 1.8TB partitions) using the Read tool, instead of using appropriate commands like lsblk or lvs.

Environment:

  • Native Linux CLI version (NOT Node.js version) (I reinstalled this hoping to reduce memory leaks!)
  • Platform: Linux 6.8.12-18-pve (Proxmox host)
  • Version: 2.1.14
  • 31GB RAM available

What happened:
The process attempted to read 1.8TB block devices as regular files, causing:
[ERROR] Error: ENOMEM: not enough memory, read '/dev/sda5'
[ERROR] Error: ENOMEM: not enough memory, read '/dev/sdb5'

Process state:

  • State: D (disk sleep) - blocked waiting for I/O
  • VmSize: peaked at 135GB (attempting to allocate 1.8TB)
  • VmRSS: 15.5GB
  • CPU: 48.5% constant
  • Multiple streaming stalls (155.8s gaps)

Workaround applied:
Added deny rules to /.claude/settings.local.json to prevent Read tool from accessing block devices:

  {
    "permissions": {
      "deny": [
        "Read(file_path:/dev/sd*)",
        "Read(file_path:/dev/md*)",
        "Read(file_path:/dev/mapper/*)",
        "Read(file_path:/dev/dm-*)",
        "Read(file_path:/dev/vg*)",
        "Read(file_path:/dev/lv*)"
      ]
    }
  }

Suggestion:
The Read tool should validate that file paths don't point to block devices before attempting to read them, or at least fail gracefully instead of trying to allocate terabytes of memory.

vphantom · 5 months ago

Wow. Why would Claude Code go up the file system beyond the current directory at all to begin with?

luison · 5 months ago

My lucky day today...

Similar issue but different root cause - GC Infinite Loop Freeze:

Environment:

  • Native Linux CLI version
  • Platform: Linux 6.8.12-18-pve (Proxmox host)
  • Version: 2.1.14
  • 128GB RAM available (no memory pressure)

What happened:
After executing an I/O intensive command (rsync), the Claude Code process entered an infinite Garbage Collection loop and became completely
unresponsive. The rsync command completed successfully, but the process never returned to a responsive state.

Process state:

  • State: R (running) but frozen, not waiting for I/O
  • CPU: 50-55% constant, all in user mode
  • 8 HeapHelper threads consuming CPU
  • 36+ minutes accumulated CPU time
  • Memory: stable at ~1.8GB RSS (NOT a memory leak)
  • No disk I/O activity during freeze
  • Process never recovers, must be killed

Root cause analysis:
The issue appears to be a Garbage Collector implementation bug where:

  1. Large objects created during I/O operations
  2. GC attempts to collect them after operation completes
  3. GC enters infinite loop (HeapHelper threads spin continuously)
  4. Process never exits GC cycle and returns to normal operation

This is NOT I/O blocking (state D) and NOT a memory leak - it's a GC infinite loop that freezes the session completely.

Workaround:
Only option is to kill the process: kill <pid> and restart session. No way to recover the frozen session.

Suggestion:
The Garbage Collector should have timeout mechanisms or better handling of large object collection to prevent infinite loops that freeze the entire session.

nponeccop · 5 months ago
Related?

No. 71G is VIRT and it's relatively useless to diagnose problems. On Linux you look at RSS and its modern alternatives such as RSan and the memory use reported by cgroups (e.g. through systemd-cgtop)

alex20465 · 5 months ago

Same issue here, ram just grows.

yulonglin · 5 months ago

This has been such an annoying issue. Even closed Claude Code sessions remain idle in the background, taking up memory and slowing things to a crawl over time 😕

In case anyone finds it helpful, this is the current patch I'm using! With 3 tiers depending on how much you want to automate it:

Simplest, straightforward:

  • kill idle sessions only (⚠️ defined as those not in the foreground, so tmux sessions are killed too): ps aux | awk '($11 ~ /\/claude$/ || $11 == "claude") {print $2}' | while read pid; do [[ $(ps -p "$pid" -o stat= 2>/dev/null) != *"+"* ]] && echo "$pid"; done | xargs -r kill 2>/dev/null
  • kill ALL sessions: ps aux | awk '($11 ~ /\/claude$/ || $11 == "claude") {print $2}' | xargs kill 2>/dev/null

Alternatively a script with various features you can call from the command line or Apple Shortcuts (kill only idle processes, kill all, list all processes, kill all except current session you're running script from, etc.): https://github.com/yulonglin/dotfiles/blob/main/custom_bins/clear-claude-code

And lastly if you want to clear idle Claude Code sessions in the background periodically (macOS or Linux): https://github.com/yulonglin/dotfiles/blob/main/scripts/cleanup/setup_claude_cleanup.sh

infactai · 5 months ago

Problem for me, is even if I kill them. When I bring them back via --resume, CPU goes pinned 100% again. So it kinda kills the whole session long term.

Really annoying when you're working on important things and need to keep a high mem/high cpu session alive to finish the work.

gzaal · 5 months ago

_Known Causes of Memory Leaks in 2.1.x
Persistent Conversation History: The application accumulates conversation data in ~/.claude/projects/ without a cleanup mechanism, causing it to load massive files into memory on startup or resume._

Cleaning this folder helped solve it for me.

yulonglin · 5 months ago
Persistent Conversation History: The application accumulates conversation data in ~/.claude/projects/ without a cleanup mechanism, causing it to load massive files into memory on startup or resume. Cleaning this folder helped solve it for me.

You might want to create new Claude Code sessions as opposed to just relying on compacting. For example, you could ask Claude to summarise or write down in some docs what was done this session, and start afresh another session. Afaik fresh Claude Code sessions shouldn't be affected by ~/.claude/projects, as it's just disk space

gzaal · 5 months ago
> Persistent Conversation History: The application accumulates conversation data in ~/.claude/projects/ without a cleanup mechanism, causing it to load massive files into memory on startup or resume. > Cleaning this folder helped solve it for me. You might want to create new Claude Code sessions as opposed to just relying on compacting. For example, you could ask Claude to summarise or write down in some docs what was done this session, and start afresh another session. Afaik fresh Claude Code sessions shouldn't be affected by ~/.claude/projects, as it's just disk space

this was not compacting related, I had done a full reboot, start a fresh session and then still direct memory bloat. After deleting a large portion of these files, which had grown to over 8GB, the problem was solved.

stamstergios · 5 months ago

Confirming exploding ram usage in Linux Ubuntu x64 KVM. Completely Unusable. Acquired via VSCode extension. Rolled back to 2.1.20 and works correctly. At least until 2.1.25 did not work at all presenting leak issue

CharlesFoxTP · 5 months ago

+1 having the same issue

notCorwin · 5 months ago

macOS as well

nponeccop · 5 months ago

The leak happens randomly. I think it is related to it reading large config files. I asked Claude to read a large file and it started to leak.

When it's leaky due to changed configs, claude install leaks too

notCorwin · 5 months ago

<img width="746" height="784" alt="Image" src="https://github.com/user-attachments/assets/70613cf2-3588-4de4-b413-3a3047857b0f" />

The programs written by Claude are running in the terminal, but it forgot to close them. It is also possible that the timeout settings were set too long, preventing them from being closed in a timely manner.

I've already restarted my MacBook three or four times today because the memory usage exceeded 120GB.

SQLServerIO · 5 months ago

Yeah, this is still an issue in version 2.1.34. Nothing like getting OOM with 128GB of RAM and a 128GB swap file, which I turned on just to try to catch this and give me time to kill it.

nponeccop · 5 months ago

I use ulimit and docker ram limit (which works though a different kernel facility of control groups). You can use a method specific to your OS. 4GB ought to be enough for everyone.

_Known Causes of Memory Leaks in 2.1.x Persistent Conversation History: The application accumulates conversation data in ~/.claude/projects/ without a cleanup mechanism, causing it to load massive files into memory on startup or resume._ Cleaning this folder helped solve it for me.

Yes but this folder is much less than 128GB when the leak starts. And it contains the knowledge Claude accumulated over time so starting from scratch is a bad option although it's better than nothing.

fangzhouli · 5 months ago

Seems still to be an issue. I am on Windows and opening the Ubuntu terminal via WSL, and I can see VmmemWSL jumps to 100% and gets killed.

TheNewJavaman · 5 months ago

In my case, claude was keeping the output of a large build script in ram. By asking it to run the build script in the background and periodically check on it, the log is saved to disk, and claude no longer crashes

nponeccop · 5 months ago

@TheNewJavaman How large was the log? I doubt any of the reporters have logs worth dozens of GBs of the leak. The memory efficiency of log storage may be abysmal. In that case, it would be a clear performance bug.

damusix · 5 months ago

Crazy how it just leaks when you leave it open for a long time. I had one process get to 13GB. The team should really look into this.

saikpr · 5 months ago

Claude Code installer crashes with OOM on systems with <4GB RAM

Environment

  • OS: Linux (Ubuntu-based)
  • RAM: 3.8GB total, 3.4GB available
  • Swap: 0GB
  • Install command: curl -fsSL https://claude.ai/install.sh | bash

Issue

Installation fails with process killed at line 142 of install script:

bash: line 142: 13239 Killed  "$binary_path" install ${TARGET:+"$TARGET"}

Root Cause

The claude binary attempts to allocate excessive memory during installation:

Out of memory: Killed process 13239 (claude-2.1.37-l) 
total-vm:88205300kB, anon-rss:3650172kB

The installer tries to allocate ~88GB virtual memory and ~3.6GB RAM, exceeding available system resources.

Expected Behavior

Installation should complete on systems with 4GB RAM without requiring swap space or excessive memory allocation.

TheNewJavaman · 5 months ago
@TheNewJavaman How large was the log? I doubt any of the reporters have logs worth dozens of GBs of the leak. The memory efficiency of log storage may be abysmal. In that case, it would be a clear performance bug.

The logs can be several GB, and in this scenario, Claude had to run the build script several times. Should I open a new issue?

TheNewJavaman · 5 months ago

@nponeccop

nponeccop · 5 months ago

I don't work for Antropic I was just wondering. This bug says "has repro" so they are working on it and your bug may or may not be a duplicate. It's safer to leave it here until they resolve this issue

marcindulak · 5 months ago
I don't work for Antropic I was just wondering. This bug says "has repro" so they are working on it and your bug may or may not be a duplicate. It's safer to leave it here until they resolve this issue

There is no Assignee on this isssue, and Anthropic has not commented on it, so we cannot assume anyone is "working on it".
It may even be that this issue will soon get closed with "60 days of inactivity" https://github.com/anthropics/claude-code/issues/16497.

NeutralKaon · 5 months ago

My turn to report this issue:

[832133.651221] Isolated Web Co invoked oom-killer: gfp_mask=0x140cca(GFP_HIGHUSER_MOVABLE|__GFP_COMP), order=0, oom_score_adj=100
[832133.651232] CPU: 5 PID: 351691 Comm: Isolated Web Co Tainted: P           OE      6.8.0-90-generic #91-Ubuntu
[832133.651236] Hardware name: System manufacturer System Product Name/TUF GAMING X570-PLUS, BIOS 5031 01/13/2025
[832133.651238] Call Trace:
[832133.651241]  <TASK>
[832133.651247]  dump_stack_lvl+0x76/0xa0
[832133.651254]  dump_stack+0x10/0x20
[832133.651258]  dump_header+0x49/0x210
[832133.651264]  oom_kill_process+0x118/0x280
[832133.651267]  ? srso_return_thunk+0x5/0x5f
[832133.651272]  ? oom_evaluate_task+0x143/0x1e0
[832133.651276]  out_of_memory+0x103/0x350
[832133.651280]  __alloc_pages_may_oom+0x10c/0x1d0
[832133.651288]  __alloc_pages_slowpath.constprop.0+0x420/0x9f0
[832133.651296]  __alloc_pages+0x31f/0x350
[832133.651303]  alloc_pages_mpol+0x91/0x210
[832133.651309]  alloc_pages+0x5b/0xd0
[832133.651313]  folio_alloc+0x15/0x40
[832133.651317]  filemap_alloc_folio+0xf4/0x100
[832133.651322]  __filemap_get_folio+0x199/0x2e0
[832133.651328]  filemap_fault+0x15c/0x8e0
[832133.651337]  __do_fault+0x3d/0x190
[832133.651341]  do_read_fault+0x133/0x200
[832133.651346]  do_fault+0xf0/0x260
[832133.651350]  handle_pte_fault+0x114/0x1d0
[832133.651355]  __handle_mm_fault+0x654/0x800
[832133.651365]  handle_mm_fault+0x18a/0x380
[832133.651371]  do_user_addr_fault+0x169/0x670
[832133.651377]  exc_page_fault+0x83/0x1b0
[832133.651383]  asm_exc_page_fault+0x27/0x30
[832133.651387] RIP: 0033:0x721d9cc2ad10
[832133.651424] Code: Unable to access opcode bytes at 0x721d9cc2ace6.
[832133.651426] RSP: 002b:00007ffe1c739da8 EFLAGS: 00010206
[832133.651429] RAX: 0000721d9cc2ad10 RBX: 0000721d9e14e230 RCX: d8cc61d97a4a5300
[832133.651431] RDX: 0000000000000000 RSI: 0000000000000002 RDI: 0000721d8b245420
[832133.651433] RBP: 00007ffe1c739e30 R08: 0000000000000002 R09: 000000007fffffff
[832133.651435] R10: 0000721d9e14e230 R11: 0000721d8b245420 R12: 000000007fffffff
[832133.651437] R13: 0000000000000002 R14: 0000721d99434f50 R15: 0000721d8b245420
[832133.651443]  </TASK>
[832133.651445] Mem-Info:
[832133.651448] active_anon:11143712 inactive_anon:10743856 isolated_anon:0
                 active_file:555 inactive_file:805 isolated_file:0
                 unevictable:36285 dirty:94 writeback:0
                 slab_reclaimable:92099 slab_unreclaimable:438225
                 mapped:419145 shmem:557651 pagetables:97250
                 sec_pagetables:0 bounce:0
                 kernel_misc_reclaimable:0
                 free:157689 free_pcp:6 free_cma:0
[832133.651454] Node 0 active_anon:44574848kB inactive_anon:42975424kB active_file:2220kB inactive_file:3220kB unevictable:145140kB isolated(anon):0kB isolated(file):0kB mapped:1676580kB dirty:376kB writeback:0kB shmem:2230604kB shmem_thp:0kB shmem_pmdmapped:0kB anon_thp:0kB writeback_tmp:0kB kernel_stack:72992kB pagetables:389000kB sec_pagetables:0kB all_unreclaimable? no
[832133.651460] Node 0 DMA free:11260kB boost:0kB min:8kB low:20kB high:32kB reserved_highatomic:0KB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB writepending:0kB present:15996kB managed:15360kB mlocked:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
[832133.651466] lowmem_reserve[]: 0 1023 94290 94290 94290
[832133.651473] Node 0 DMA32 free:373436kB boost:0kB min:732kB low:1776kB high:2820kB reserved_highatomic:0KB active_anon:159556kB inactive_anon:451976kB active_file:8kB inactive_file:16kB unevictable:864kB writepending:0kB present:3310312kB managed:1145908kB mlocked:864kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
[832133.651480] lowmem_reserve[]: 0 0 93267 93267 93267
[832133.651487] Node 0 Normal free:246060kB boost:20480kB min:87320kB low:182824kB high:278328kB reserved_highatomic:174080KB active_anon:44415304kB inactive_anon:42523436kB active_file:2496kB inactive_file:4528kB unevictable:144276kB writepending:376kB present:97242624kB managed:95514808kB mlocked:144276kB bounce:0kB free_pcp:24kB local_pcp:0kB free_cma:0kB
[832133.651493] lowmem_reserve[]: 0 0 0 0 0
[832133.651499] Node 0 DMA: 1*4kB (U) 1*8kB (U) 1*16kB (U) 1*32kB (U) 1*64kB (U) 1*128kB (U) 1*256kB (U) 1*512kB (U) 0*1024kB 1*2048kB (M) 2*4096kB (M) = 11260kB
[832133.651525] Node 0 DMA32: 332*4kB (ME) 229*8kB (ME) 231*16kB (ME) 248*32kB (UME) 182*64kB (ME) 215*128kB (UME) 158*256kB (UME) 113*512kB (UME) 70*1024kB (UME) 37*2048kB (U) 18*4096kB (UM) = 373448kB
[832133.651551] Node 0 Normal: 28035*4kB (UME) 8680*8kB (UME) 4144*16kB (UME) 14*32kB (UM) 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 248332kB
[832133.651571] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[832133.651574] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[832133.651576] 563792 total pagecache pages
[832133.651577] 0 pages in swap cache
[832133.651579] Free swap  = 0kB
[832133.651580] Total swap = 0kB
[832133.651582] 25142233 pages RAM
[832133.651583] 0 pages HighMem/MovableOnly
[832133.651584] 973214 pages reserved
[832133.651586] 0 pages hwpoisoned
[832133.651587] Tasks state (memory values in pages):

<...> 

[832133.653353] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=user.slice,mems_allowed=0,global_oom,task_memcg=/user.slice/user-1000.slice/user@1000.service/app.slice/tmux-spawn-ee958dc7-c340-42b6-8996-13285159d515.scope,task=claude,pid=4081818,uid=1000
[832133.653508] Out of memory: Killed process 4081818 (claude) total-vm:134929540kB, anon-rss:59993328kB, file-rss:2872kB, shmem-rss:0kB, UID:1000 pgtables:131576kB oom_score_adj:200
[832135.339005] systemd-journald[985]: Under memory pressure, flushing caches.
[832138.450393] oom_reaper: reaped process 4081818 (claude), now anon-rss:0kB, file-rss:336kB, shmem-rss:0kB

I have 96 GB of ram -- and this was mallocing 135 GB (and had 80 resident). Quite nuts.

QuintinWillison · 5 months ago

I've just had a long chat with Claude Opus 4.6 about this (Web, because my Claude Code environment is currently inoperable). Most of my Claude use is via Code, so if this isn't fixed soon (rather than just via a "sticky plaster" like more RAM or "give it swap") then it's no longer worth paying for, presumably time to try Codex... Claude(Web)'s Summary...

Claude Code v2.1.39 — OOM Kill on Launch in Memory-Constrained Linux VM

Summary

Claude Code v2.1.39 is killed by the Linux OOM killer within approximately 90 seconds of launch, before any user input is processed. The process allocates ~70GB of virtual memory and consumes ~3.6GB of physical RSS during what appears to be initialisation/indexing, exhausting all available RAM in a 4GB VM with no swap.

This is consistent with the memory regression introduced around v2.1.8 and reported across multiple issues, but notably this environment previously ran Claude Code without issue for months on the same 4GB/2-CPU allocation. The regression appeared with recent version updates.

Environment

| Component | Detail |
|-----------|--------|
| Claude Code version | 2.1.39 |
| Host OS | macOS (Apple Silicon M2 Pro Mac mini, 32GB RAM) |
| Virtualisation | Lima using Apple's Virtualization.framework (vz) |
| Guest OS | Ubuntu 22.04 Server (arm64/aarch64) |
| Kernel | 5.15.0-170-generic #180-Ubuntu |
| VM CPUs | 2 |
| VM RAM | 4 GiB |
| Swap | None (Lima default — no swap configured) |
| Model configured | opusplan (ANTHROPIC_DEFAULT_OPUS_MODEL=claude-opus-4-6) |
| Default permission mode | plan |
| MCP Servers | GitHub (multiple instances, read-only PAT) |

Reproduction

  1. limactl shell claude
  2. cd /Users/Quintinwillison/code/QuintinWillison/plan-viewer/
  3. claude
  4. Wait ~30–90 seconds. The REPL renders, displays "Welcome back", shows model info (Sonnet 4.5 — Claude Max), then prints Killed and drops back to the bash prompt.

No user input is required — the kill happens during or immediately after initialisation. The plan-viewer repository is a small project; this is not a large monorepo.

100% reproducible. Two consecutive OOM kills were captured in a single session.

OOM Kill Evidence

Kill #1 — 14:57:40 UTC

claude invoked oom-killer: gfp_mask=0x1100dca(GFP_HIGHUSER_MOVABLE|__GFP_ZERO), order=0, oom_score_adj=0

Out of memory: Killed process 30629 (claude)
  total-vm:73892288kB  (~70.4 GB virtual)
  anon-rss:3721464kB   (~3.55 GB physical)
  file-rss:0kB
  shmem-rss:0kB
  pgtables:7720kB
  oom_score_adj:0

Kill #2 — 15:00:20 UTC (second launch attempt)

claude invoked oom-killer: gfp_mask=0x1100dca(GFP_HIGHUSER_MOVABLE|__GFP_ZERO), order=0, oom_score_adj=0

Out of memory: Killed process 1774 (claude)
  total-vm:73892280kB  (~70.4 GB virtual)
  anon-rss:3717588kB   (~3.55 GB physical)
  file-rss:1036kB
  shmem-rss:0kB
  pgtables:7736kB
  oom_score_adj:0

System Memory State at Kill

From the kernel's Mem-Info dump at the time of the second kill:

active_anon:249 inactive_anon:957463
Free swap  = 0kB
Total swap = 0kB
1048576 pages RAM (= 4 GiB)

The process table at kill time shows claude as overwhelmingly the largest consumer:

[  pid  ]   uid  tgid total_vm      rss pgtables_bytes swapents oom_score_adj name
[   1774]   504  1774 18473070   929656  7921664        0             0 claude

929,656 pages × 4KB = ~3.55 GB RSS — the claude process alone consumed approximately 89% of total physical RAM.

Key Observations

  1. Identical virtual memory footprint across both kills: total-vm is consistently ~73.9 GB across both OOM events, suggesting a deterministic allocation pattern rather than a random leak.
  1. No swap available: Lima's default Ubuntu image on Virtualization.framework does not configure swap. This means the OOM killer fires as soon as physical RAM is exhausted with zero grace period.
  1. Previously worked fine: This same Lima configuration (4 GiB RAM, 2 CPUs) successfully ran Claude Code for months on older versions (~1 month ago). The regression correlates with version updates in the 2.1.x series.
  1. Kill occurs pre-interaction: The TUI renders, shows the welcome screen, but the process is killed before the user can type anything. This points to initialisation/indexing as the memory-intensive phase.
  1. Small project: The target repository (plan-viewer) is a small codebase, not a monorepo with hundreds of thousands of files.

Configuration Files

Lima VM Definition (lima.yaml)

images:
  - location: "https://cloud-images.ubuntu.com/releases/22.04/release/ubuntu-22.04-server-cloudimg-arm64.img"
    arch: "aarch64"

cpus: 2
memory: "4GiB"

mounts:
  - location: "~/ClaudeState"
    writable: true
  - location: "~/.lima"
    writable: false
  - location: "~/code/CPC-Systems"
    writable: false
  - location: "~/code/QuintinWillison/plan-viewer"
    writable: false

Claude Code Settings (settings.json)

{
  "permissions": {
    "allow": [
      "Write(/home/lima.linux/.claude/plans/**)",
      "Edit",
      "Read(/**)",
      "Bash(xargs cat:*)",
      "Bash(find:*)",
      "Bash(ls:*)",
      "Bash(grep:*)",
      "Bash(awk:*)",
      "Bash(git:*)",
      "Bash(cat:*)",
      "Bash(sed:*)",
      "Bash(python:*)",
      "Bash(python3:*)",
      "Bash(claude --version)",
      "WebFetch(domain:raildata.org.uk)",
      "WebSearch"
    ],
    "deny": [
      "Write(/Users/Quintinwillison/**)",
      "Bash(dotnet:*)",
      "Bash(npm:*)",
      "Bash(node:*)"
    ],
    "defaultMode": "plan"
  },
  "model": "opusplan",
  "env": {
    "ANTHROPIC_DEFAULT_OPUS_MODEL": "claude-opus-4-6"
  }
}

Impact

Claude Code is completely unusable in this environment without workarounds (increasing VM RAM, adding swap, or pinning to an older version). For users running Claude Code in memory-constrained Linux VMs — which is a reasonable deployment given Claude Code's own documentation suggesting modest resource needs — this is a blocker.

QuintinWillison · 5 months ago

And then, like magic, Claude Code upgraded itself to version 2.1.41 and the issue has disappeared. What on earth is going on over there? This feels less like "bleeding edge" and more like "chaos" to me. Or was it a server-side issue causing client-side OOMs?

SQLServerIO · 5 months ago

Like magic indeed. I've got five sessions running, and things are holding rock steady. I looked through the release notes and didn't see anything that addressed this directly. I guess Claude doesn't like commenting on Claude issues.

vphantom · 5 months ago
I guess Claude doesn't like commenting on Claude issues.

Nor closing them if they're resolved. 😬 This repo is up to 5K now. Amazingly my high CPU loop (idle after typing /) is also gone, so I guess that update had some major improvements.

sopleb · 5 months ago

I too am having this issue, it seems to only be background tasks that are causing it.

[235796.983812] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=user.slice,mems_allowed=0,global_oom,task_memcg=/user.slice/user-1000.slice/user@1000.service/app.slice/app-org.wezfurlong.wezterm@a1d78a6cdc514f568b81f31ce90fc37c.service,task=claude,pid=1152221,uid=1000
[235796.983846] Out of memory: Killed process 1152221 (claude) total-vm:174609136kB, anon-rss:99636060kB, file-rss:3720kB, shmem-rss:2928kB, UID:1000 pgtables:197984kB oom_score_adj:200
[235799.373360] oom_reaper: reaped process 1152221 (claude), now anon-rss:0kB, file-rss:3448kB, shmem-rss:816kB
[236603.360301] [1236638]  1000 1236638 44821639 26095122 26094183      270       669 210268160      128           200 claude
[236603.360327] oom-kill:constraint=CONSTRAINT_NONE,nodemask=(null),cpuset=user.slice,mems_allowed=0,global_oom,task_memcg=/user.slice/user-1000.slice/user@1000.service/app.slice/app-org.wezfurlong.wezterm@22947b4270dd4d3fae380eb54d2f9468.service,task=claude,pid=1236638,uid=1000
[236603.360405] Out of memory: Killed process 1236638 (claude) total-vm:179286556kB, anon-rss:104376732kB, file-rss:1080kB, shmem-rss:2676kB, UID:1000 pgtables:205340kB oom_score_adj:200
[236607.344247] oom_reaper: reaped process 1236638 (claude), now anon-rss:1620kB, file-rss:1080kB, shmem-rss:0kB```

asem89 · 5 months ago

Detailed analysis from aarch64 Linux (Hetzner VPS)

Environment: Claude Code v2.1.42, Node.js v22.19.0, aarch64 (ARM64), Ubuntu 24.04, 32 GB RAM

Symptom: Single Claude Code session reached 29.9 GB RSS in ~18 minutes of active use (multi-step coding task with MCP tool calls). Killed by systemd tmux cgroup scope (tmux-spawn-*.scope). Hit twice on the same box — first at 16 GB, then after upgrade to 32 GB.

Key findings from /proc/<pid>/smaps_rollup and /proc/<pid>/status:

| Metric | Value |
|--------|-------|
| VmPeak | 129.2 GB |
| VmRSS at kill | 29.9 GB |
| Anonymous (heap+buffers) | ~21 GB outside V8 |
| V8 pointer cage | 54 GB rw-p mapping (mostly 0 KB RSS) |
| --max-old-space-size | 8192 (baked into SEA binary) |
| Processes in cgroup | 13 (identical to idle session) |

Root cause analysis:

  1. NOT subagent/process multiplication — the killed cgroup had exactly 13 processes, same count as an idle Claude Code session. This is a single-process memory growth issue.
  1. --max-old-space-size=8192 only caps V8 old generation heap, not total process RSS. Memory allocated via Node.js Buffers, ArrayBuffers, native C++ addons, libuv, and stream pipelines is unbounded.
  1. The 54 GB rw-p anonymous mapping is V8's pointer cage reservation (virtual, not physical). The real problem is the ~21 GB of non-V8-heap physical memory.
  1. On aarch64/Linux, there's also the concern from Node.js issue about --max-old-space-size not being properly respected (related to V8's memory cage behavior on ARM64).

What works as mitigation:

systemd cgroup MemoryMax is the only reliable hard cap. Example for tmux scopes:

# Find your tmux scope
systemctl --user list-units 'tmux-spawn-*.scope' --no-legend | awk '{print $1}'

# Apply 4 GB hard limit
systemd-run --user --scope -p MemoryMax=4G -p MemorySwapMax=0 -- claude

Or for existing sessions:

systemctl --user set-property tmux-spawn-XXXXX.scope MemoryMax=4G MemorySwapMax=0

This forces the OOM killer to target the Claude process before it takes down the entire box. V8's GC _should_ respond to memory pressure signals from cgroup, but the non-V8 allocations won't.

Bottom line: --max-old-space-size is necessary but insufficient. Claude Code needs either (a) a built-in cgroup/ulimit wrapper, or (b) explicit tracking and limits on non-V8-heap allocations (Buffers, streams, native addons).

AIntelligentTech · 4 months ago

macOS M2 Pro (32GB) — 13 concurrent sessions, v2.1.44, stable under memory compressor

Adding a data point from a heavy concurrent-session macOS setup that's currently stable, with findings that may help others — particularly the correct environment variable for the current Bun/JSC build.

Environment

  • OS: macOS Tahoe 26.2 (build 25C56, Darwin 25.2.0)
  • Hardware: Apple M2 Pro, 12 cores, 32GB unified memory, 1TB NVMe SSD
  • Claude Code: v2.1.44 (native Bun/JSC compiled binary)
  • Sessions: 13 concurrent Claude Code processes (tmux)
  • Uptime: 21 hours since last reboot

Per-session RSS (all 13 sessions)

PID: 63455   RSS: 771 MB
PID: 19779   RSS: 606 MB
PID: 98605   RSS: 548 MB
PID: 33214   RSS: 508 MB
PID: 79089   RSS: 503 MB
PID: 34365   RSS: 456 MB
PID: 11708   RSS: 417 MB
PID: 72712   RSS: 401 MB
PID: 24320   RSS: 394 MB
PID: 78334   RSS: 347 MB
PID: 79040   RSS: 323 MB
PID: 62737   RSS: 317 MB
PID: 32671   RSS: 314 MB
────────────────────────────
Total:        5,905 MB (~5.8 GB)

Swap used: only 233 MB of 1 GB total. Memory pressure: green.

macOS memory compressor achieves a 2.4x compression ratio (storing ~6.3 GB of logical data in 2.6 GB of physical compressor pages). Cumulative swap activity: 2.3M swapouts / 1.4M swapins over 21h — steady but not pathological.

Key finding: BUN_JSC_forceRAMSize is the correct env var, not NODE_OPTIONS

Current Claude Code (v2.1.44) ships as a compiled Bun binary using JavaScriptCore (JSC), not V8. I confirmed this via binary inspection — the compiled binary contains BUN_JSC_ env var parsing code, --smol flag strings, and Bun FFI signatures.

The NODE_OPTIONS="--max-old-space-size=8192" workaround that's been widely suggested in this thread and others has no effect on the Bun build. The JSC equivalent is:

# Tell JSC the machine has 16GB — triggers aggressive GC at ~80% (~12.8GB)
export BUN_JSC_forceRAMSize=17179869184  # 16GB in bytes

This constrains JSC's perception of available RAM, causing garbage collection to run more aggressively before memory grows to dangerous levels. Without it, JSC on a 32GB machine won't meaningfully GC until ~25.6 GB — by which point you're deep into swap or OOM territory.

The value should be tuned based on your RAM and concurrent session count. On a 32GB machine running up to 5 sessions, 16 GB is a reasonable setting — JSC triggers hard GC at ~12.8 GB per process, well before the 34 GB+ runaway leaks reported in this thread. Lower values (e.g., 8 GB) trigger GC earlier but add more CPU overhead during normal operation.

What helped stabilise our setup

  • v2.1.33 fixed subagent OOM crashes — our sessions got dramatically more stable after this update, consistent with reports that v2.1.41/42 improved things further
  • Proper session lifecycle — always /exit before closing terminals to avoid orphaned processes (#17391). Ctrl+C leaves subagent processes running
  • BUN_JSC_forceRAMSize set as above
  • Active session management — monitoring session count and killing idle sessions proactively

Why macOS reports may be rarer

macOS users are likely more resilient to this leak because the memory compressor provides ~2.4x headroom that Linux doesn't have. On our 32GB M2 Pro, 13 sessions averaging ~450 MB each = ~5.9 GB RSS, which the compressor handles without meaningful swap pressure. Linux users on equivalent RAM hit OOM much sooner with no transparent compression layer. This may explain the Linux-heavy distribution of reports in this thread.

SSD wear note

For anyone concerned about swap impact on Apple Silicon SSDs: our 1TB NVMe shows 269 TB lifetime writes at 11% wear (SMART data). Apple's SSDs are rated for 600+ TBW. The swap churn from multiple Claude sessions is measurable but not alarming for SSD endurance, even with daily heavy use.

AIntelligentTech · 4 months ago

Follow-up: Correction and better workarounds

After further testing, I need to correct part of my earlier comment.

BUN_JSC_forceRAMSize: honest reassessment

I ran controlled stress tests allocating JS strings (which model the actual Claude Code leak pattern — conversation context and tool output retention):

# With BUN_JSC_forceRAMSize=256MB:
Iter 90: JSC heap=450MB, RSS=477MB

# Without BUN_JSC_forceRAMSize:
Iter 90: JSC heap=360MB, RSS=477MB

RSS was identical in both cases. The env var did not reduce actual memory consumption. This is because large JS strings in Bun/JSC are backed by native memory (mimalloc), not the JSC garbage-collected heap. Since Claude Code's memory growth comes primarily from retained strings (conversation context, subprocess output, tool results), BUN_JSC_forceRAMSize likely has limited practical effect on this specific leak.

The 80% GC threshold is real (verified in WebKit source: criticalGCMemoryThreshold = 0.80), but it only governs JSC heap objects, not native string backing stores.

I'm leaving the original comment for context, but don't expect BUN_JSC_forceRAMSize to solve the memory leak. It may provide marginal benefit for JSC-managed objects but won't address the primary leak vector.

Better workarounds (verified in v2.1.44 binary)

I found these in the Claude Code source (confirmed via binary inspection):

1. CLAUDE_AUTOCOMPACT_PCT_OVERRIDE — probably the most effective

export CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=50

This triggers context compaction at 50% of the context window instead of the default ~83.5%. Since the documented root cause of gradual memory growth is conversation context accumulation (one user in #18011 reported a 35 MB session file with 1,467 JSONL entries before crash), compacting earlier directly reduces the retained object graph. Verified in binary source — the function reads process.env.CLAUDE_AUTOCOMPACT_PCT_OVERRIDE, parses it as a percentage, and adjusts the compaction threshold.

2. Session restarts between major tasks

The only guaranteed fix. The leak is cumulative — each subprocess call, tool result, and context compaction cycle adds retained data that GC cannot reclaim. Restarting resets everything.

3. Active session management

Kill idle sessions. Each idle session still runs MCP polling and background operations that accumulate memory. On my setup, reducing from 13 to 5 sessions drops total RSS from ~5.9 GB to ~2.3 GB.

Note for npm/Node.js users

My earlier comments focused on the native Bun binary. If you installed Claude Code via npm and see V8 stack traces in your crashes, BUN_JSC_forceRAMSize does nothing for you. Use NODE_OPTIONS="--max-old-space-size=8192" instead, which is the V8 equivalent. The CLAUDE_AUTOCOMPACT_PCT_OVERRIDE workaround works for both installation methods.

AIntelligentTech · 4 months ago

Correction to my previous correction: Do NOT lower autocompact threshold

Retracting the CLAUDE_AUTOCOMPACT_PCT_OVERRIDE=50 recommendation from my previous comment. In practice, lowering the compaction threshold significantly degrades session quality — Claude loses conversation context earlier, which impacts its ability to track complex multi-step tasks, remember prior decisions, and maintain coherence across long sessions.

The default ~83.5% threshold exists for good reason. Compacting earlier trades memory for intelligence, which is the wrong tradeoff for most users.

What actually works (honest assessment)

After testing multiple approaches, the verified mitigations for this leak are all operational, not configuration-based:

  1. Kill idle sessions — each idle session leaks memory through MCP polling and background operations. On my 13-session setup, reducing to 5 dropped total RSS from ~5.9 GB to ~2.3 GB. This is the single biggest lever.
  1. Restart sessions between major tasks — the only guaranteed reset. The leak is cumulative and no env var prevents it.
  1. Always /exit before closing terminals — Ctrl+C leaves orphaned subagent processes that balloon to 34 GB+ (#17391).
  1. Monitor and manage proactively — track session count and per-session RSS. Kill the largest/oldest sessions first.

What doesn't work

  • BUN_JSC_forceRAMSize — GC hint only, no effect on RSS in stress tests (see my previous correction)
  • CLAUDE_AUTOCOMPACT_PCT_OVERRIDE — reduces memory but destroys session quality
  • NODE_OPTIONS — irrelevant on the native Bun binary

The real fix

This needs to be addressed architecturally by Anthropic. The core issue — unbounded retention of subprocess stdout/stderr and conversation context in native memory — has no user-side workaround that doesn't sacrifice functionality. The data in this thread (61+ reports across every platform) makes the case clearly.

What users can contribute: per-session RSS data, reproduction cases, and version-specific regression/improvement reports help narrow the scope. The v2.1.41/42 improvements reported by several commenters suggest progress is being made, even if undocumented.

junaidtitan · 4 months ago

For what it's worth, a big contributor to the RAM growth is bloated session JSONL files — sessions with recursive grep outputs, progress tick duplication, and large tool outputs can easily hit hundreds of MB. I've been running cozempic as a guard daemon that continuously prunes session bloat, which keeps file sizes manageable and noticeably reduces the memory pressure. Not a fix for the underlying leak, but it helps keep sessions from becoming the trigger.

theQuert · 4 months ago

If you're looking for an automated workaround while waiting for an official fix, I open-sourced a three-layer cleanup solution:

  1. Stop hook — auto-cleans orphan subagents/MCP servers when a Claude Code session ends
  2. proc-janitor daemon — background daemon that auto-kills orphaned processes (PPID=1) every 30s with a grace period
  3. Shell functionsclaude-ram (check RAM breakdown) and claude-cleanup (manual kill)

Repo: https://github.com/theQuert/claude-code-cleanup

One-command install: ./install.sh

In practice, I found 21 orphan processes (subagents + MCP servers + claude-mem workers) consuming ~4 GB that were cleaned up instantly. The daemon runs via brew services so it auto-starts on boot.

theQuert · 4 months ago

This issue has been a major pain point for me too. On macOS, after a day of Claude Code sessions I regularly see 7+ GB eaten by orphaned subagents and MCP servers (PPID=1, no controlling TTY).

I built cc-reaper to deal with this systematically:

  • Stop hook — auto-kills orphan processes when a session ends (uses awk '$7 == "??"' to target only true orphans without a TTY)
  • proc-janitor daemon — catches processes orphaned by crashes/force-closes (30s scan interval, 60s grace period)
  • claude-ram — quick RAM breakdown by category (CLI sessions / subagents / MCP servers)
  • claude-cleanup — manual kill for immediate relief

Typical orphan breakdown I've measured:

| Process | RAM each |
|---------|----------|
| claude --output-format stream-json (subagent) | 180–300 MB |
| MCP servers (supabase, context7, etc.) | 40–110 MB |
| chroma-mcp --client-type persistent | ~350 MB |
| worker-service.cjs --daemon | ~100 MB |

One-line install:

git clone https://github.com/theQuert/cc-reaper && cd cc-reaper && bash install.sh

Not a root cause fix, but it keeps things manageable until process lifecycle is handled properly upstream. Hope this helps anyone else drowning in orphaned processes.

nponeccop · 4 months ago

@theQuert I wonder if you can use PGID to reliably track the children

cesarvarela · 4 months ago

getting this

<img width="382" height="47" alt="Image" src="https://github.com/user-attachments/assets/e7321cfa-3f19-4c93-9569-0f847acc9296" />

and then this

<img width="927" height="61" alt="Image" src="https://github.com/user-attachments/assets/ab731616-26e4-4c9a-bd1b-de6eac2b80f8" />

theQuert · 4 months ago

@nponeccop Great suggestion! I investigated PGID behavior on a live system and confirmed that Claude Code sessions are indeed process group leaders (PGID = session PID), and all spawned MCP servers, subagents, and their children inherit this PGID.

This means a single kill -- -$PGID reliably cleans up everything — including third-party MCP servers that pattern matching might miss.

I've implemented PGID-based cleanup as the primary detection method across all three layers in v0.4.0:

  • Stop hook: Uses the session's inherited PGID to kill all group members (except self and parent CLI) on session end
  • claude-cleanup: Finds orphaned process groups where the PGID leader has PPID=1, kills entire groups at once
  • LaunchAgent monitor: PGID-first scanning with pattern-based fallback

Pattern-based detection is kept as a fallback for edge cases where processes escape their group via setsid().

Verified on macOS with multiple concurrent sessions — each session's children (MCP servers, subagents, npm exec processes) all share the parent's PGID consistently.

theQuert · 4 months ago

@cesarvarela If you're looking for an automated solution, cc-reaper can handle this — it's a three-layer cleanup tool specifically for orphaned Claude Code processes:

git clone https://github.com/theQuert/cc-reaper.git
cd cc-reaper && ./install.sh

It sets up a Stop hook (auto-cleanup on session end), a background daemon (catches crashes), and shell commands like claude-cleanup (instant kill) and claude-ram (RAM usage breakdown). Uses PGID-based process group detection so it catches all children reliably.

rublev · 4 months ago
@cesarvarela If you're looking for an automated solution, cc-reaper can handle this — it's a three-layer cleanup tool specifically for orphaned Claude Code processes: git clone https://github.com/theQuert/cc-reaper.git cd cc-reaper && ./install.sh It sets up a Stop hook (auto-cleanup on session end), a background daemon (catches crashes), and shell commands like claude-cleanup (instant kill) and claude-ram (RAM usage breakdown). Uses PGID-based process group detection so it catches all children reliably.

This is awesome! Thank you.

EduardoGNQ · 4 months ago
getting this <img alt="Image" width="382" height="47" src="https://private-user-images.githubusercontent.com/1172479/560643474-e7321cfa-3f19-4c93-9569-0f847acc9296.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzMyNTgyMTAsIm5iZiI6MTc3MzI1NzkxMCwicGF0aCI6Ii8xMTcyNDc5LzU2MDY0MzQ3NC1lNzMyMWNmYS0zZjE5LTRjOTMtOTU2OS0wZjg0N2FjYzkyOTYucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDMxMSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAzMTFUMTkzODMwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9OTQwYTU3MDQwYzAxZWUzNmQ1MTNlNTcwY2FjNWNmNjA0NTk3MThlNjY0MDJlYTljYTMxNTg1ZTY0MDU3ZDM1MSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.M40UO_xf6Zya4fAIm_NtxZEOveK6g_Y89IBWoZ6DJMU"> and then this <img alt="Image" width="927" height="61" src="https://private-user-images.githubusercontent.com/1172479/560643516-ab731616-26e4-4c9a-bd1b-de6eac2b80f8.png?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzMyNTgyMTAsIm5iZiI6MTc3MzI1NzkxMCwicGF0aCI6Ii8xMTcyNDc5LzU2MDY0MzUxNi1hYjczMTYxNi0yNmU0LTRjOWEtYmQxYi1kZTZlYWMyYjgwZjgucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDMxMSUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjAzMTFUMTkzODMwWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NWJmYjVhZDRkOGYwMDUxOWM0OGU5ZTcxNjgyMmFhMTk1NzMzZjg0NzU3ODA2OTVlMWZjYWU2N2I2OTdkNjA2NCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.ybvnoXOakfTtbeW9PRpUNNiIvbiaeQ_0yQslPFtBU6w">

I have the same issue but I am on Windows 11

saif97 · 4 months ago

Same here. I ran Opus on the /heapdump got the below results. Since the project isn't opensource can't validate any of this. Hopefully it helps out.

  Memory Leak: Streaming Response ArrayBuffers Not Released (v2.1.73)

  Environment

  - Claude Code version: 2.1.73
  - Node.js version: v24.3.0
  - Platform: darwin (macOS, Darwin 25.2.0)
  - Trigger: Manual heap dump after noticing high memory usage

  Observed Behavior

  After only 102 seconds of uptime, the Claude Code process consumed 2.43 GB of heap memory with a measured growth rate of ~42 GB/hour (~12.4 MB/s). The process would hit the V8 heap limit
  (8 GB) within minutes of sustained use.

  Memory Snapshot Summary

  Heap Used:      2,430,693,660 bytes (2.43 GB)
  Heap Total:        49,500,160 bytes (49 MB)   ← V8 managed heap is tiny
  External:       2,390,817,004 bytes (2.39 GB) ← nearly all memory is external
  ArrayBuffers:   1,874,908,627 bytes (1.87 GB)
  RSS:            1,261,174,784 bytes (1.26 GB)
  Growth Rate:    ~12.4 MB/s (42,481 MB/hour)

  Heap Snapshot Analysis

  1. 7,073 Identical 256KB ArrayBuffers (1.77 GB)

  The dominant allocation is 7,073 ArrayBuffer objects each exactly 262,288 bytes (256 KB). These account for 1.77 GB — 73% of total heap usage.

  These are consistent with streaming HTTP response chunks from the Anthropic API that are being consumed but never released by the garbage collector.

  ArrayBuffer size distribution:
    262,288 bytes (256 KB) × 7,073 = 1,855,163,024 bytes (1.77 GB)
    16,777,360 bytes (16 MB)  × 1   =    16,777,360 bytes (16 MB)
    Other small buffers       × 25  =        69,203 bytes (~67 KB)
    ─────────────────────────────────────────────────────
    Total: 7,099 ArrayBuffers        = 1,872,009,587 bytes (1.79 GB)

  At the observed growth rate, this means roughly 270 new 256KB chunks are retained per second without being freed.

  2. Two Retained Response Objects (380 MB)

  Two native Response objects are retained in memory, each consuming 190,413,414 bytes (~190 MB). A third Response object is correctly small (352 bytes), suggesting it was properly
  consumed.

  The two large Response objects are retained through the following chain:

  JSLexicalEnvironment (closure captures: response, stream, src, self)
    └── IncomingMessage (size: 97 bytes)
          └── [property: FetchAPI] → Response (190 MB)

  Both large Response objects share the same retention pattern — closures (JSLexicalEnvironment) capture variables named response, stream, src, and self, which prevent the IncomingMessage →
   Response chain from being garbage collected.

  3. Blob Accumulation (10 MB)

  7 Blob objects totaling ~10 MB are also retained, with sizes ranging from 439 KB to 3.4 MB. These are minor compared to the ArrayBuffer leak but may share the same root cause.

  Memory by V8 Node Type

       Total Size      Count  Type
    1,876,548,014     62,480  object        ← ArrayBuffers are "object" type
      391,104,332         50  native        ← Response + Blob objects
       27,839,147    130,410  code          ← closures/compiled code (normal)
        6,012,140    171,576  closure       ← normal
        4,613,936     25,513  hidden
        4,139,271     79,365  string
        3,667,376     32,722  object shape

  Probable Root Cause

  The streaming HTTP client (likely fetch() used to call the Anthropic API) is:

  1. Not releasing ArrayBuffer chunks after they are consumed from the response stream. The 256KB chunk size is consistent with a default read buffer size in the HTTP/fetch streaming
  implementation. After each chunk is read and processed, the buffer should become eligible for GC, but something is retaining references.
  2. Closure-captured variables (response, stream, src, self) are preventing GC of completed Response bodies. The IncomingMessage objects hold a FetchAPI property pointing to the full
  Response, and closures in the streaming pipeline keep the IncomingMessage alive.

  This suggests the issue is in the streaming response consumption code — possibly a pattern like:

  const response = await fetch(url);
  const stream = response.body;
  // Closures below capture `response` and `stream`, preventing GC
  // even after the stream is fully consumed

  Steps to Reproduce

  1. Start Claude Code v2.1.73
  2. Have a conversation that generates moderate-length responses
  3. Observe RSS/heap growth via Activity Monitor or process.memoryUsage()
  4. After ~2 minutes, memory usage exceeds 2 GB

  Suggested Fix

  - Ensure Response references are nulled out or not captured in long-lived closures after the response body stream is fully consumed
  - Investigate whether the streaming chunk ArrayBuffers are being held in a queue, event listener, or concatenation array that is never cleared
  - Consider using response.body.cancel() or explicitly dereferencing the stream after consumption

WERDXZ · 4 months ago

same here, 2 minutes and it grew to 7 gigs of ram usage

theQuert · 4 months ago

@rublev Glad it helps! Let me know if you run into any edge cases.

@EduardoGNQ cc-reaper currently targets macOS (uses launchd, ps -eo pgid, etc.), but the core detection logic (PGID-based group cleanup + pattern fallback) should be portable. If there's interest in Windows/WSL support, PRs or even just "here's what breaks on my setup" reports are very welcome — tracking this as a potential expansion: https://github.com/theQuert/cc-reaper/issues

@saif97 This heapdump analysis is incredibly valuable — the 7,073 × 256KB ArrayBuffer retention pattern and the closure-captured Response objects pinpoint the upstream root cause much more precisely than anything I've seen in this thread. This kind of data makes a strong case for Anthropic to fix the streaming consumption path.

From the cc-reaper side, this actually validates why process-level cleanup matters as a stopgap: if each session leaks at ~42 GB/hr, killing idle/orphaned sessions early is the only user-side lever that actually reclaims memory. cc-reaper's claude-guard function (auto-reaper for idle sessions) + the stop hook + proc-janitor daemon together address exactly this — preventing leaked sessions from accumulating to the point where the system becomes unusable.

If you'd like to contribute your heapdump methodology or findings to the repo (even as a docs reference), that would be a great addition for users trying to understand why their RAM is disappearing.

@WERDXZ 7 GB in 2 minutes is brutal. If you're on macOS, cc-reaper can at least keep things from spiraling — the background daemon scans every 30s and kills orphaned process groups automatically:

git clone https://github.com/theQuert/cc-reaper && cd cc-reaper && bash install.sh

After install, run claude-ram to see your current breakdown by category (sessions / subagents / MCP servers / orphans).

---

For anyone following this thread: cc-reaper is actively maintained and we welcome contributions — whether it's new platform support, better detection heuristics, or upstream analysis like @saif97's heapdump work. Repo: https://github.com/theQuert/cc-reaper

WERDXZ · 4 months ago
@WERDXZ 7 GB in 2 minutes is brutal. If you're on macOS, cc-reaper can at least keep things from spiraling — the background daemon scans every 30s and kills orphaned process groups automatically:

Unfortunately I'm on linux... @theQuert I'll be trying to debug this if I have time

nponeccop · 4 months ago

@WERDXZ PGID works on Linux as well. But on Linux there are cgroups and there are a few advices (e.g. https://github.com/anthropics/claude-code/issues/4953#issuecomment-4049174081 ) on how both limit the memory usage and kill it with all children

m13v · 4 months ago

for macOS users hitting this - the heap command is useful for tracking what's actually growing:

heap <PID> > /tmp/heap1.txt

wait 10-15 minutes

heap <PID> > /tmp/heap2.txt

diff by type+size to find what's accumulating

we run multiple Claude Code agents in parallel via launchd (4 scheduled workflows, each spawning a claude process) and ran into similar growth patterns. Instruments is too expensive for high-allocation processes - heap snapshots with a time gap between them show you exactly which object types are accumulating without the overhead.

for the OOM kill specifically, on Linux cgroups are the right containment. on macOS we ended up just monitoring with a background daemon that checks RSS every 30s and kills orphaned process groups when they cross a threshold

m13v · 4 months ago

we run 4 parallel Claude agents via launchd on macOS. the scheduling setup: https://github.com/m13v/social-autoposter/tree/main/launchd - each plist triggers a shell script that spawns a claude process with --max-turns. the multi-agent orchestration: https://github.com/m13v/tmux-background-agents

josefguenther · 4 months ago

Pretty incredible that this bug has been there for over 6 months without being fixed. Team? You there?

By the way the tag platform:linux is totally inaccurate. I'm on macOS and have this bug as well.

theQuert · 4 months ago

@m13v Great heap profiling tip! Running 4 parallel Claude agents via launchd is exactly the scenario where orphan processes pile up fast. cc-reaper has a claude-guard function designed for this — it monitors all sessions' RSS in real-time and auto-kills any that exceed a configurable threshold (default 4GB) using PGID group kills, so all child processes (subagents, MCP servers) get cleaned up together. Since you're already using launchd for scheduling, the proc-janitor daemon layer should fit right into your workflow.

theQuert · 4 months ago

@josefguenther Agree this has been painful for way too long, and you're right — it's definitely not Linux-only. While waiting for an official fix, cc-reaper provides automated defense on macOS with three layers: a stop hook (cleans up when sessions end), a background daemon (scans every 30s for orphan processes), and claude-guard (auto-reaper that kills bloated sessions exceeding an RSS threshold). One-line install, pure shell — no extra runtime needed.

theQuert · 4 months ago

@WERDXZ For Linux, the core shell functions in cc-reaper (claude-cleanup, claude-guard, claude-ram) work cross-platform since they rely on standard ps and PGID-based kills. The macOS-specific part is the launchd daemon layer — a Linux systemd unit would be a straightforward addition. If you're interested, feel free to open an issue at https://github.com/theQuert/cc-reaper and we can work on systemd integration together.

yurukusa · 3 months ago

A session cleanup hook can help prevent memory accumulation:

COUNTER="/tmp/cc-memcheck-counter"
COUNT=$(cat "$COUNTER" 2>/dev/null || echo 0)
COUNT=$((COUNT + 1))
echo "$COUNT" > "$COUNTER"
[ $((COUNT % 10)) -ne 0 ] && exit 0
CC_PID=$(pgrep -f 'claude' | head -1)
[ -z "$CC_PID" ] && exit 0
RSS_KB=$(ps -o rss= -p "$CC_PID" 2>/dev/null | tr -d ' ')
[ -z "$RSS_KB" ] && exit 0
RSS_MB=$((RSS_KB / 1024))
if [ $RSS_MB -gt 8000 ]; then
    echo "🔴 CRITICAL: Claude Code using ${RSS_MB}MB RAM. Consider /compact or restart." >&2
elif [ $RSS_MB -gt 4000 ]; then
    echo "🟡 WARNING: Claude Code using ${RSS_MB}MB RAM." >&2
fi
find /tmp -name 'claude-*-cwd' -mmin +60 -delete 2>/dev/null
find /tmp -name 'cc-*.json' -mmin +120 -delete 2>/dev/null
exit 0

A Notification hook can also clean up on session start:

find /tmp -name 'claude-*' -mmin +120 -delete 2>/dev/null
find /tmp -name 'cc-*' -mmin +120 -delete 2>/dev/null
RSS=$(ps -o rss= -p $$ 2>/dev/null | tr -d ' ')
echo "Session started. Cleaned stale temp files." >&2
exit 0

These hooks won't fix the core memory leak (which is in the Claude Code process itself), but they can:

  1. Alert you before it gets critical
  2. Clean up accumulated temp files that contribute to memory pressure
  3. Give you time to /compact or restart before OOM kills the process
junaidtitan · 3 months ago

The 120+ GB RAM usage comes from Claude Code parsing massive JSONL session files. Sessions accumulate progress ticks, file-history snapshots, duplicate system-reminders, and base64 image blocks that balloon file size.

Cozempic v1.4.1 keeps session files lean with a guard daemon that auto-prunes via 17 strategies. The image-strip strategy alone removes old base64 screenshots (keeps last 20%). progress-collapse eliminates thousands of progress tick messages. compact-summary-collapse removes everything before the last compaction boundary (85-95% savings).

pip install cozempic && cozempic init

The guard auto-starts on every session via the SessionStart hook — just install and forget. Would be curious if anyone here sees memory usage drop after running it on their bloated sessions.

marcindulak · 2 months ago

High virtual memory ~~usage~~ size happens even on a fresh installation, it's enough to start claude and let it wait.
In the past (https://github.com/anthropics/claude-code/issues/12987#issuecomment-3969148746) also high resident memory was used by a fresh claude instance, so the above hypothesis The 120+ GB RAM usage comes from Claude Code parsing massive JSONL session files is not covering all cases.

The screenshot below is from Almalinux 9 virtual machine and 2.1.118 (Claude Code) with a fresh installation of claude, and without any model work done, only claude started in a terminal, without claude /login.

<img width="1047" height="258" alt="Image" src="https://github.com/user-attachments/assets/489a91da-ff2c-48fe-ac0d-61772f5f8a9d" />

tajmiri · 1 month ago

Cross-reference: filed #60534 with the same symptom on v2.1.143 on WSL2 (Ubuntu 24.04). RSS grew from ~900 MB to 12.6 GB in ~12 minutes of normal interactive use; exiting and restarting fully releases the memory. Also seen: claude update itself consumed 14.8 GB before being killed and left a 0-byte versions/2.1.144. Adding here for visibility — same root cause likely.

fuomag9 · 1 month ago

Same issue here

nponeccop · 1 month ago
High virtual memory usage happens even on a fresh installation

@marcindulak VIRT is not "virtual memory usage". High VIRT in top on a 64-bit system is high address space reservation and it's not a sign of any memory problem, so this report is invalid.

marcindulak · 1 month ago

OK, updated my comment from "virtual memory usage" to "virtual memory size", and added a mention of resident memory too. My point was that since the high (resident) memory size was high even during the fresh claude installation, 3rd party tools that remove local claude session files are not covering all cases, and there is still something unusual about claude's high memory usage. By a fresh installation I mean installing claude with curl -fsSL https://claude.ai/install.sh | bash on a new virtual machine, no claude login yet, and it's not claude update, there is nothing under ~/.claude.

I should had posted instead this image https://github.com/anthropics/claude-code/issues/12987#issuecomment-3969148746 that includes high resident memory during a fresh claude installation, but that was the situation in February 2026 for me. This high memory usage during claude installation still continues today (with 2.1.159 (Claude Code)), I believe partly randomly, only sometimes the virtual machine freezes during the claude installation. It's not even clear the problem is resident memory, but maybe a network or disk usage caused by the claude installation.

<img width="1178" height="294" alt="Image" src="https://github.com/user-attachments/assets/65137f1b-703d-449e-aa38-273cc02df560" />

laozidabo · 1 month ago

Correction to my previous comment: The crash log I shared was AI-generated and contained an incorrect timeline. The actual situation is much worse than "8 hours idle":

Real Timeline (from kernel journal)

Claude Code crashes within minutes of launch, not after hours of idle time. On June 9 alone, it was OOM-killed 8 times in one afternoon:

14:27:39  Killed (PID 13485)
14:56:07  Killed (PID 22679)  — 29 min gap
14:59:36  Killed (PID 24827)  — 3 min gap
15:00:51  Killed (PID 25941)  — 1 min gap
15:17:11  Killed (PID 30612)  — 16 min gap
15:20:52  Killed (PID 31255)  — 3 min gap
15:22:32  Killed (PID 31888)  — 2 min gap
23:44:45  Killed (PID 37497)  — evening

And again on June 10 at 12:38.

Systemd scope confirms rapid death

app-niri-alacritty-109153.scope:
  Consumed 2min 24s CPU time over 5min 39s wall clock time
  14.5G memory peak, 3.9G memory swap peak

The process runs for only ~5 minutes before consuming 14.5 GB and getting killed. This is not an idle-time leak — it is a rapid memory explosion during normal use.

Every kill shows the same pattern

  • total-vm: ~70 GB (virtual address space)
  • anon-rss: 276 kB to 47 kB (almost no physical anonymous memory)
  • unevictable shmem: 12-14 GB (unreclaimable shared memory)

The unevictable shmem mechanism I described in my previous comment still applies — the correction is about when it happens: minutes after launch, not hours of idle.

MoshiQAQ · 1 month ago

Another data point: v2.1.173, Linux native binary, long agent sessions reach 31–33 GB RSS

Environment

  • Claude Code v2.1.173 (Bun native x64 binary)
  • Linux (RHEL 9 kernel 5.14), shared dev server
  • Long-running sessions driven via the Agent SDK / claude --resume, with heavy tool output (data-analysis workloads producing large stdout)

Observation
During long sessions the claude process RSS grows monotonically to 31–33 GB and never shrinks. Growth correlates with accumulated conversation history — especially large tool outputs — being kept in the heap for the lifetime of the session. There is no built-in cap, and NODE_OPTIONS heap flags have no effect (presumably because it's a Bun-compiled native binary, not stock Node).

Workarounds we've landed (in case they help others)

  1. cgroup wrapper — wrap claude in a systemd scope so a runaway session pressures/kills only itself instead of OOMing the box:

``bash
claude() {
systemd-run --user --scope -q \
-p MemoryHigh=16G -p MemoryMax=24G \
"$(command -v claude)" "$@"
}
`
MemoryHigh applies reclaim pressure; MemoryMax hard-kills. Since --resume` restores the session (session id survives), a hard kill is recoverable.

  1. RSS watchdog + session rotation — for unattended/agent runs, a watchdog walks /proc, sums RSS of claude-named processes only (excluding work subprocesses), and past a threshold (we use 8 GB) does a clean stop + relaunch with --resume. This keeps long-lived agent runs bounded indefinitely.
  1. Mitigating the source — instructing the agent to write large outputs to files and read back only summaries ("artifact-first") slows heap growth considerably, but doesn't eliminate it.

Ask: a configurable memory ceiling, plus paging/compacting older conversation history (especially large tool results) out of the resident heap, would address the root cause. --resume already proves session state can live on disk.

russalo · 18 days ago

Hitting this on the Linux CLI too — adding hard kernel-level evidence, since most reports
here describe the symptom but not the proof.

Kernel OOM log (the smoking gun):

kernel: claude invoked oom-killer ... constraint=CONSTRAINT_NONE ... global_oom
Out of memory: Killed process <pid> (2.1.178) total-vm:19128004kB,
anon-rss:16990848kB ... # ~16.2 GB resident, anonymous

So this is an off-heap / native RSS leak killed by the kernel — not a V8 heap-limit
crash. (Same off-heap mechanism as #67433.)

The key data point: process RSS is fully decoupled from session size.

  • The session's on-disk log was ~27 MB when the process was ~16 GB RSS — a ~600x

gap. So this is not "big session -> big RAM"; it's unbounded native growth.

  • Steady-state claude processes on the same host sit at ~0.9 GB RSS, roughly constant

across very different session sizes. The crashed one was the lone outlier.

  • The process comm had been renamed to a version-like string (2.1.178), not

claude — worth noting for process-monitoring: filtering on comm == "claude" misses
the ballooned process. Match by UID or open-fd instead.

Trigger: the OOM landed on the turn right after ingesting an ~86 KB image — clearly the
spike that tipped an already-bloated process, not the cause. Strain was visible beforehand
(tool ops running 10-100x slower for minutes = memory pressure).

Containment != fix: on a no-swap host this is an instant kill with no graceful
degradation. Adding swap + a per-cgroup MemoryMax contains it (degrades / self-OOMs one
session instead of freezing the host), but the underlying native growth in long-lived
sessions is unaddressed and recurs regardless of host config.

nponeccop · 17 days ago

I haven't seen the leak lately - many sessions survive a weekend while inactive.

cwdx · 10 days ago

Adding a datapoint with kernel-level evidence (macOS jetsam report).

Environment: Claude Code 2.1.201 (native/bun build), macOS 26.2, Apple Silicon, 24GB RAM. Large Nx/TypeScript monorepo (~6GB working tree). Six concurrent CC sessions in terminal tabs, each running for several hours with subagent fan-out and occasional long build/typecheck Bash tasks.

Outcome: kernel JetsamEvent followed by two WindowServer userspace watchdog timeouts → GUI crash / forced logout. All six sessions lost.

Jetsam snapshot (top residents at time of event):

15.66GB rss | bun   (CC session)
14.72GB rss | bun   (CC session)
14.67GB rss | bun   (CC session)
14.62GB rss | bun   (CC session)
13.53GB rss | bun   (CC session)
12.84GB rss | bun   (CC session)
 6.26GB rss | bun
 5.73GB rss | bun
 3.98GB rss | watchman
 3.89GB rss | node  (in-flight vitepress build)

~86GB RSS across the six main CC processes alone on a 24GB machine; the compressor was holding ~145GB of uncompressed anonymous pages with ~150MB free when jetsam fired. rpageslifetimeMax on every bun process — they grew monotonically and never released.

Notes that may help triage:

  • The sessions were mostly idle or waiting on a Bash tool call at the time — consistent with #67433 (off-heap RSS growth while idle).
  • Heavy subagent usage earlier in the day (one session spawned 8 parallel subagents); possibly compounding with #71730.
  • The node/tsc child processes OOM'd first (V8 "heap out of memory" aborts over the preceding ~3 hours) — canaries, not the cause; the CC processes were the dominant holders.

Happy to pull specific fields out of the JetsamEvent .ips or run a heapdump on a fresh session if that's useful.