Claude Code using too much memory? Find the old sessions
On this page
  1. Why one session is more than one process
  2. Step 1: memory per session, helpers included
  3. Step 2: find what was left behind
  4. Step 3: close old sessions the right way
  5. Keep it from piling up
  6. Where Joxo fits
  7. Frequently asked questions
  8. Why does Claude Code use so much memory?
  9. How do I see which Claude Code sessions are running?
  10. Is it safe to kill leftover node processes?
  11. Try it with your team

Blog / claude code

Claude Code using too much memory? Find the old sessions

See how much memory each Claude Code or Codex session uses with its tool servers, find sessions open for days and leftovers, and close them safely.

Your laptop fan spins up, Activity Monitor shows a wall of node and claude processes, and you have no idea which terminal they belong to. Usually nothing is broken. Each coding agent session starts helpers of its own (tool servers, language servers, shells, dev servers), and each one keeps running until its session ends. Leave ten sessions open for a week and they add up.

This post gives you one script that shows the real memory of each session with all its helpers, how to spot the ones you forgot, and how to close them without losing work. We ran everything below on a Mac with sixteen Claude Code sessions open, and the script on Linux too.

Why one session is more than one process#

When you start claude or codex in a folder, the agent process itself typically uses a few hundred MB. On top of that it starts:

  • Tool servers from your config: each entry under your agent's tool server settings is its own program, often launched through npx or uvx, so you get a package runner plus the server itself.
  • Shells for the commands it runs.
  • Anything those commands start: a dev server, a test watcher, a build in watch mode.

Activity Monitor and top list them one by one, with no link to the session that started them. A session with eight tool servers can be fifteen processes. So the question to ask isn't "which process is big" but "which session is big, counting everything under it".

Step 1: memory per session, helpers included#

Save this as agent-mem.sh:

bash
#!/bin/bash
# agent-mem.sh: memory used by each Claude Code or Codex session, helpers included.
tree() {
  local p
  for p in "$@"; do
    echo "$p"
    tree $(pgrep -P "$p")
  done
}
for pid in $(pgrep -x claude) $(pgrep -x codex); do
  kb=0; n=0
  for p in $(tree "$pid"); do
    r=$(ps -o rss= -p "$p" 2>/dev/null)
    kb=$((kb + ${r:-0})); n=$((n + 1))
  done
  dir=$(lsof -a -p "$pid" -d cwd -Fn 2>/dev/null | sed -n 's/^n//p')
  printf '%6s MB  %3s procs  up %-12s %-7s pid %-6s %s\n' \
    "$((kb / 1024))" "$n" "$(ps -o etime= -p "$pid" | tr -d ' ')" \
    "$(basename "$(ps -o comm= -p "$pid")")" "$pid" "$dir"
done | sort -rn

Run it with bash agent-mem.sh. It walks the process tree under each session, adds up resident memory, and prints the biggest first, with how long the session has been open and the folder it runs in. On our Mac the top of the list looked like this (folders shortened):

  4694 MB   18 procs  up 07:36        claude  pid 96503  ~/app
  2577 MB   19 procs  up 52:14        claude  pid 98954  ~/app
   958 MB   14 procs  up 19:53        claude  pid 18925  ~/app
   679 MB   11 procs  up 02-08:57:58  claude  pid 47751  ~/app
   679 MB    7 procs  up 05-08:01:34  claude  pid 24431  ~/app
   660 MB   14 procs  up 05-08:04:05  claude  pid 4827   ~/site

Three things to read from it:

  • The big ones at the top. The 4.7 GB session had been open only seven and a half minutes and was busy. A big number on a young, busy session is usually work in progress, not a leak.
  • The old ones: up 05-08:01:34 means five days and eight hours. Sessions open that long are usually forgotten ones, and each still held 600-700 MB with its tool servers.
  • The process count. Fourteen processes for a session that does nothing is a sign of many tool servers. Every one you configured starts again in every session.

On Linux, lsof is often missing; swap the dir= line for dir=$(readlink "/proc/$pid/cwd"). We ran that version in a Debian container and it printed the same columns.

Step 2: find what was left behind#

When a session ends normally, its helpers end with it. When it is killed, or a command started something with nohup or &, those children can outlive it. The system then adopts them, so their parent process ID becomes 1. List the likely ones:

bash
pgrep -P 1 -lf 'npm exec|npx|uvx|node '

On our Mac this found four npm exec vite servers whose sessions were long gone, each still holding a port. Before you stop one, check what it is and which folder it runs in:

bash
ps -o pid,etime,rss,command -p 34796
lsof -a -p 34796 -d cwd

If it is clearly yours and clearly finished (an old preview server, a watcher for a folder you closed), stop it with kill 34796, and only use kill -9 if it ignores that. Don't kill system processes or anything you don't recognise; the pattern above also matches things you may have started on purpose.

On Linux desktops, orphans may be adopted by your user's service manager instead of process 1. If the list comes back empty, look for processes whose parent is systemd --user.

For ports specifically, see Port already in use? Find the dev server your agent left.

Step 3: close old sessions the right way#

The safest way to get a session’s memory back is to end the session itself, not to kill its helpers one by one:

  1. Find its terminal (the folder in the last column helps), make sure it isn't in the middle of something, and type /exit or press Ctrl+D.
  2. If you can't find the terminal, kill <pid> on the agent process sends a normal stop signal; its tool servers end with it.
  3. Need the conversation again later? claude --resume or codex resume brings it back. Ending a session doesn't delete its history.

Then run agent-mem.sh again and check the list got shorter.

Keep it from piling up#

  • Trim tool servers you don't use. Each one starts in every session. Removing three you never call saves three processes per session, every session.
  • Keep project-only servers in the project. A database server needed for one repo belongs in that repo's config, not your user config.
  • Close sessions when the job is done. Resuming later is cheap; an idle session holds its memory all week.
  • Ask agents to stop what they start. A line in your CLAUDE.md or AGENTS.md like "Stop any dev server or watcher you started before you finish" helps.

Where Joxo fits#

Most of this mess comes from having many terminals and losing track of them. The Joxo desktop app puts every agent session on your computer in one window: what each one is doing, which need you, and which are done, so you can close the finished ones instead of hunting for them. When an agent needs an answer, the question reaches your phone too. Get it from the download page. For running several sessions without the chaos, see manage many Claude Code sessions.

Frequently asked questions#

Why does Claude Code use so much memory?#

The agent itself usually takes a few hundred MB. The rest comes from what it starts: tool servers from your config, shells, and dev servers or builds. Count a session together with its child processes to see its real size.

How do I see which Claude Code sessions are running?#

Run pgrep -lx claude for the list of session processes, or the script in this post for each one's memory, age and folder.

Is it safe to kill leftover node processes?#

Only once you know what they are. Check the command and folder with ps and lsof first, stop the ones you recognise as finished, and leave anything you don't recognise.