<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ilya Kalinin</title>
    <description>The latest articles on DEV Community by Ilya Kalinin (@gerrux).</description>
    <link>https://dev.to/gerrux</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4203417%2Fd0a30909-9b33-4728-acf8-3a15e68b6a58.png</url>
      <title>DEV Community: Ilya Kalinin</title>
      <link>https://dev.to/gerrux</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gerrux"/>
    <language>en</language>
    <item>
      <title>15 Claude Code sessions were sitting on 11 GB of RAM. I built a mod to see which one</title>
      <dc:creator>Ilya Kalinin</dc:creator>
      <pubDate>Fri, 23 Oct 2026 21:09:44 +0000</pubDate>
      <link>https://dev.to/gerrux/15-claude-code-sessions-were-sitting-on-11-gb-of-ram-i-built-a-mod-to-see-which-one-3jdn</link>
      <guid>https://dev.to/gerrux/15-claude-code-sessions-were-sitting-on-11-gb-of-ram-i-built-a-mod-to-see-which-one-3jdn</guid>
      <description>&lt;p&gt;I usually have ten to fifteen Claude Code sessions open. One is fixing tests, another is working on a frontend in a neighbouring worktree, a third has been waiting for my answer since the morning, and I forgot about the fourth. Each has its own subagents and MCP servers, with a vite server up here and a pytest run there. At some point my 64 GB machine started lagging on every window switch.&lt;/p&gt;

&lt;p&gt;Task Manager showed a wall of identical &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;claude&lt;/code&gt; processes. I could see how much they were eating, but not which session they belonged to, and I didn't want to close windows at random.&lt;/p&gt;

&lt;p&gt;So I wrote claude-load, a Claude Code mod that splits the machine's load by session. The first run showed 15 live sessions using 10.8 GB. Most had been idle for a while with merged PRs, and one was running a forgotten Python process whose parent had exited long ago.&lt;/p&gt;

&lt;p&gt;Code (MIT): &lt;a href="https://github.com/Gerrux/claude-load" rel="noopener noreferrer"&gt;github.com/Gerrux/claude-load&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Whose node is this?
&lt;/h2&gt;

&lt;p&gt;You can't tell sessions apart by process name, since they all run the same &lt;code&gt;claude&lt;/code&gt;, &lt;code&gt;node&lt;/code&gt; and &lt;code&gt;bash&lt;/code&gt;. But Claude Code keeps a registry of live sessions: &lt;code&gt;~/.claude/sessions/&lt;/code&gt; has a &lt;code&gt;&amp;lt;pid&amp;gt;.json&lt;/code&gt; for each one, with almost everything you need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;18636&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sessionId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a3a4722e-…"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Refactor the auth middleware"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"busy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cwd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;work&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"entrypoint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claude-desktop"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The format isn't documented, so the mod reads only these fields and doesn't fail if it catches a file mid-rewrite. It never opens the &lt;code&gt;*.key&lt;/code&gt; files with tokens that sit next to them.&lt;/p&gt;

&lt;p&gt;The sampler takes the list of all processes with their parents and walks up the PPID chain from each one until it hits a session's PID. The whole tree under a session counts as its load. Walked chains are cached, so hundreds of processes take a single pass.&lt;/p&gt;

&lt;p&gt;It turned out that even an idle session holds 0.5 to 0.7 GB: 300 to 450 MB for &lt;code&gt;claude&lt;/code&gt; itself, plus its own set of MCP servers on node. Fifteen forgotten windows add up to several gigabytes.&lt;/p&gt;

&lt;p&gt;In the pane, each session shows CPU, memory and a six-minute graph. Orphans come next, and at the bottom everything that isn't a session is folded by name. If it says &lt;code&gt;chrome ×31&lt;/code&gt; there, Claude is off the hook.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1glugu6pdm6drxmu4xqv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1glugu6pdm6drxmu4xqv.png" alt="claude-load pane: CPU and RAM with graphs, sessions, an orphan and processes outside sessions" width="800" height="921"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When CPU goes over 50% or memory over 85%, a line with the top consumers appears above the prompt:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhmsy7z3bocw6aid59xhy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhmsy7z3bocw6aid59xhy.png" alt="Load line above the prompt" width="796" height="101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the terminal, &lt;code&gt;/load&lt;/code&gt; prints the same thing as text:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgpgnb9j1rpucr6ypva80.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgpgnb9j1rpucr6ypva80.png" alt="/load report in the terminal" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The screenshots are rendered from demo data, because my real sessions are named after work projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Orphans and the "end" button
&lt;/h2&gt;

&lt;p&gt;By orphans I mean processes that don't belong to any session but clearly came from one: vite from a session I closed long ago, a language server with no editor, that Python run. I wanted to show them separately and let you end them with one button.&lt;/p&gt;

&lt;p&gt;In the first version, an orphan was any dev process outside sessions with noticeable load. The review before release showed that this pulled in my working PowerShell, IDE helpers and &lt;code&gt;conhost&lt;/code&gt;, and the button offered to end them along with all their children.&lt;/p&gt;

&lt;p&gt;The button itself was worse. It trusted an in-memory snapshot that could be arbitrarily old, and it didn't check the process name. In the meantime a PID can be freed and handed to another process, and &lt;code&gt;taskkill /T&lt;/code&gt; would have taken down an unrelated program together with its children.&lt;/p&gt;

&lt;p&gt;The rule is stricter now. An orphan is a tree whose root's parent is really dead. On Windows that means the parent PID isn't among the living, or the process with that PID was created after the child (the number was reused). On macOS and Linux the root has been reparented to &lt;code&gt;init&lt;/code&gt;, &lt;code&gt;systemd&lt;/code&gt; or &lt;code&gt;launchd&lt;/code&gt;. Only trees with a real dev tool in them are shown, not just shells, and only if they use at least 0.3% CPU or 150 MB. The terminal a session was started from and the sampler itself are never orphans.&lt;/p&gt;

&lt;p&gt;To attribute an orphan to a repository you need its working directory. On Linux it's &lt;code&gt;/proc/&amp;lt;pid&amp;gt;/cwd&lt;/code&gt;, and on macOS &lt;code&gt;lsof&lt;/code&gt; reports it. Windows has no API for this, so the mod reads it from the other process's memory: &lt;code&gt;NtQueryInformationProcess&lt;/code&gt; gives the PEB address, &lt;code&gt;ProcessParameters&lt;/code&gt; is at offset &lt;code&gt;0x20&lt;/code&gt;, and &lt;code&gt;CurrentDirectory&lt;/code&gt; is at &lt;code&gt;0x38&lt;/code&gt; inside those. In code that's a couple of &lt;code&gt;ReadProcessMemory&lt;/code&gt; calls.&lt;/p&gt;

&lt;p&gt;Before ending anything, the mod takes a fresh snapshot, refuses to act on one older than 15 seconds, and checks that the PID still belongs to a process with the same name. Session processes and PIDs missing from the snapshot can't be ended from the pane. You can click the button half an hour after opening the pane and it's still safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  One sampler per machine
&lt;/h2&gt;

&lt;p&gt;If each of fifteen sessions polled processes on its own, the monitor would add load of its own. So exactly one process per machine does the sampling: it writes &lt;code&gt;~/.claude/state/load/snapshot.json&lt;/code&gt;, and the mod in each session reads that file every five seconds, however many sessions there are.&lt;/p&gt;

&lt;p&gt;On Windows the sampler is a hidden PowerShell process that the mod starts when the snapshot is stale. Two measurements on my machine shaped it: &lt;code&gt;Get-Process&lt;/code&gt; takes 76 ms, while a full CIM query with parents takes 400 ms. So every four seconds it reads &lt;code&gt;Get-Process&lt;/code&gt;, and the parent tree from CIM is queried only when new PIDs appear, at most once every eight seconds. CPU share comes from the difference in accumulated time between passes.&lt;/p&gt;

&lt;p&gt;The sampler lives as long as someone needs it. Each session touches a &lt;code&gt;wanted&lt;/code&gt; file every 30 seconds; after three minutes without a touch, the sampler exits. If it crashes, the first session to see a stale snapshot starts a new one, and a PID file with a command-line check prevents a second copy. On a 12-thread machine with 15 sessions this costs about 0.35% CPU and 130 MB of memory.&lt;/p&gt;

&lt;p&gt;On macOS and Linux no separate process is needed, since &lt;code&gt;ps&lt;/code&gt; is cheap. There, one session holds a "lease" (a file with its ID and a timestamp) and does the sampling itself. If the lease isn't renewed for 15 seconds, another session takes over. CPU took some fiddling. On Linux the &lt;code&gt;%cpu&lt;/code&gt; column is the average over the process's whole life, so the mod uses the difference in the &lt;code&gt;time&lt;/code&gt; column instead. But Linux reports &lt;code&gt;time&lt;/code&gt; in whole seconds, and two passes one second apart draw spikes that never happened. So passes run at most once every four seconds and never overlap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results and limitations
&lt;/h2&gt;

&lt;p&gt;I wrote it over a couple of days together with my AI sidekick, Claude Code (Opus 5.5). The first cleanup worked right away. The "Sort it out with Claude" button sends a request to a bundled skill; Claude sorts idle sessions and orphans, asks once, and touches only what you approve. Of 15 sessions, 12 went to the archive: eight with merged PRs and four forgotten ones without a PR. Used memory dropped from 35.2 to 31.2 GB. I also turned on auto-archiving a session when its PR is merged in the desktop app.&lt;/p&gt;

&lt;p&gt;The mod hasn't run on a real Mac or Linux box yet. Tests cover recorded &lt;code&gt;ps&lt;/code&gt;, &lt;code&gt;vm_stat&lt;/code&gt;, &lt;code&gt;/proc/meminfo&lt;/code&gt; and &lt;code&gt;lsof&lt;/code&gt; output, but that doesn't replace a live machine. CPU on Linux is coarser than on Windows because &lt;code&gt;ps&lt;/code&gt; reports time in whole seconds; reading &lt;code&gt;/proc/&amp;lt;pid&amp;gt;/stat&lt;/code&gt; would fix that. Under a strict PowerShell policy (&lt;code&gt;AllSigned&lt;/code&gt; or Constrained Language Mode) the sampler won't start, and the mod says so instead of showing "Waiting…" forever.&lt;/p&gt;

&lt;p&gt;The session registry is undocumented, so if Anthropic changes the &lt;code&gt;~/.claude/sessions&lt;/code&gt; format, the mod will need an update. On Windows the working directory is read from another process's memory. It's read-only and limited to the current user's processes, but an antivirus or EDR may not like it. The mod makes no network requests and has no telemetry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;

&lt;p&gt;You need Claude Code 2.1.287 or newer. The command below adds the repo as a marketplace and installs the mod for your user. On macOS, Linux and Git Bash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude plugin marketplace add Gerrux/claude-load &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; claude plugin &lt;span class="nb"&gt;install &lt;/span&gt;claude-load@claude-load &lt;span class="nt"&gt;--config&lt;/span&gt; &lt;span class="nv"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;auto
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In PowerShell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;claude&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;marketplace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Gerrux/claude-load&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;$?&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;claude&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;claude-load&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;claude-load&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the desktop app without a terminal: "+" next to the prompt, Plugins, Add marketplace, &lt;code&gt;Gerrux/claude-load&lt;/code&gt;, Add plugin. Then run &lt;code&gt;/reload-plugins&lt;/code&gt; and &lt;code&gt;/load&lt;/code&gt;. The &lt;a href="https://code.claude.com/docs/en/plugins/mods/overview" rel="noopener noreferrer"&gt;Claude Code docs&lt;/a&gt; cover mods in general.&lt;/p&gt;

&lt;p&gt;How many sessions do you usually keep open? If you're on a Mac or Linux, tell me what &lt;code&gt;/load&lt;/code&gt; showed and what broke.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was written with the help of Claude, the same way the mod was.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
