Memory leak: Missing cleanup for /tmp/claude-*-cwd working directory tracking files

Status Open
Maintainer reply ✓ Yes — wolffiex
Activity 111 comments · opened Oct 3, 2025
💡 Likely answer: A maintainer (wolffiex, collaborator) responded on this thread — see the highlighted reply below.

Bug Description

Claude Code creates temporary files to track working directory changes across Bash command executions but never deletes them, causing accumulation of /tmp/claude-*-cwd files.

Environment

  • Claude Code Version: 2.0.1
  • OS: Linux (WSL2)
  • Node Version: (System default)

The Problem

Every Bash tool invocation creates a temporary file at /tmp/claude-{random-4-hex}-cwd to track the working directory after command execution. These files are never cleaned up, leading to accumulation.

Evidence

  • Observed: 174 files accumulated in one day of usage
  • Pattern: Each file is 22 bytes containing the working directory path
  • Debug log: Shows 2,018 Bash invocations over 4 days
  • Only cleanup: systemd-tmpfiles-clean removes them daily at 07:15

Root Cause Analysis

Location in Code

File: /usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js

The issue is in the lq6 function (around line 1520 in the minified code):

// Current implementation (BUG - no cleanup):
P.result.then(async(k)=>{
  if(k&&!Y&&!k.backgroundTaskId)try{
    j$(bq6(K,{encoding:"utf8"}).trim(),M)  // Reads file but never deletes it
  }catch{
    B1("tengu_shell_set_cwd",{success:!1})
  }
})

The Mechanism

  1. Claude Code generates a random temp file path: let K = \${V}/claude-${F}-cwd\``
  2. Appends pwd -P >| ${K} to every Bash command to capture final directory
  3. Reads the file with bq6(K,{encoding:"utf8"}) to update internal cwd
  4. Missing step: Never calls unlinkSync(K) to delete the file

The Fix

Add cleanup immediately after reading the file:

// Fixed implementation:
P.result.then(async(k)=>{
  if(k&&!Y&&!k.backgroundTaskId)try{
    let cwdContent=bq6(K,{encoding:"utf8"}).trim();
    try{C1().unlinkSync(K)}catch{};  // <- Add this line
    j$(cwdContent,M)
  }catch{
    B1("tengu_shell_set_cwd",{success:!1})
  }
})

Verification

I applied this fix locally and confirmed:

  • Files are now created and immediately deleted after use
  • Working directory tracking continues to function correctly
  • No accumulation even after running 15+ commands in succession

Impact

  • Resource leak: Accumulates filesystem entries (500+ files/day for heavy users)
  • Privacy concern: Working directory paths persist in /tmp
  • Disk usage: While minimal (22 bytes each), it's unnecessary accumulation

Reproduction Steps

  1. Run any Bash command: ls
  2. Check temp files: ls /tmp/claude-*-cwd
  3. Observe new file created but not deleted
  4. Repeat and watch accumulation

Why This Design Exists

The temp file approach is actually clever and necessary:

  • Tracks cd commands across subprocess isolation
  • Doesn't pollute stdout with pwd output
  • Works reliably across all shell types
  • The implementation is 95% correct, just missing the cleanup step

Recommendation

This is a simple one-line fix that should be included in the next Claude Code release. The temp file mechanism itself is sound and necessary for stateful directory navigation in a stateless subprocess model.

Additional Notes

  • The fix has been tested and verified locally
  • No side effects observed
  • This affects all Claude Code users on Unix-like systems

View original on GitHub ↗

111 Comments

Sundeepg98 · 11 months ago

Additional Analysis & Impact Assessment

Quantitative Impact Data

After monitoring for 24 hours, here's the accumulation rate:

  • 174 orphaned files created in ~12 hours of usage
  • 2,018 Bash invocations tracked in logs
  • ~14.5 files/hour accumulation rate during active use
  • 22 bytes each = minimal individual impact but compounds over time

Why This Matters

  1. Multi-user systems: Shared servers could accumulate thousands of files
  2. Long-running sessions: Power users running Claude Code 24/7
  3. CI/CD environments: Automated systems without regular reboots
  4. Docker containers: May not have systemd-tmpfiles-clean

Reproduction Script

#!/bin/bash
# Monitor temp file accumulation
echo "Starting temp file monitor..."
INITIAL_COUNT=$(ls /tmp/claude-*-cwd 2>/dev/null | wc -l)
echo "Initial count: $INITIAL_COUNT files"

# Trigger some Bash commands through Claude Code
for i in {1..10}; do
  # This would need to be triggered through Claude Code's UI/API
  echo "Trigger Bash command #$i through Claude Code"
  sleep 1
done

FINAL_COUNT=$(ls /tmp/claude-*-cwd 2>/dev/null | wc -l)
echo "Final count: $FINAL_COUNT files"
echo "Accumulated: $((FINAL_COUNT - INITIAL_COUNT)) new files"

Suggested Priority

Given the silent nature of this bug (no errors, just accumulation), I'd suggest Medium Priority with the following reasoning:

  • ✅ Has a simple one-line fix
  • ✅ Affects all users universally
  • ⚠️ No immediate functionality impact
  • ⚠️ Mitigated by system cleanup on most Linux distros
  • ❌ Could cause issues on constrained systems

Testing the Fix

The fix has been verified locally by modifying /usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js:

// After line containing readFileSync(K)
try { require('fs').unlinkSync(K) } catch {}

Happy to provide any additional information or testing assistance needed!

KCW89 · 10 months ago

Have we resolved this issue?

github-actions[bot] · 8 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.

erykwieliczko · 8 months ago

The issue still persists and is really annoying. After a few days the amount of claude-*-cwd files reaches thousands which really slows things down.

cute-slime · 7 months ago

<img width="245" height="607" alt="Image" src="https://github.com/user-attachments/assets/fb719adb-db38-478c-bbb6-5e8cc10f1516" />

Issue: Temporary working directories not being cleaned up
I'm still experiencing this issue. As shown in the screenshot, multiple tmpclaude-XXXX-cwd directories are accumulating and not being properly cleaned up after sessions end.
Environment:

Multiple temporary directories with pattern tmpclaude-*-cwd persist after use
Directories observed: tmpclaude-02a6-cwd, tmpclaude-6f46-cwd, tmpclaude-7b7a-cwd, tmpclaude-67aa-cwd, tmpclaude-144b-cwd, tmpclaude-191b-cwd, tmpclaude-685d-cwd, tmpclaude-1687-cwd, tmpclaude-2601-cwd, tmpclaude-cb02-cwd, tmpclaude-d549-cwd, tmpclaude-e2ac-cwd, tmpclaude-f0c9-cwd, tmpclaude-f096-cwd, tmpclaude-fb05-cwd, tmpclaude-fe76-cwd, and more...

Expected behavior:
Temporary working directories should be automatically removed when the session ends or the tool exits.
Actual behavior:
Temporary directories persist indefinitely, requiring manual cleanup.
This is still actively occurring. Would appreciate a fix for proper cleanup of these temporary directories.

Duskfen · 7 months ago

as the bug is tagged with linux: This is also an issue in windows:

<img width="629" height="543" alt="Image" src="https://github.com/user-attachments/assets/d6747842-9352-4265-8ea6-80f0eb80cdfa" />

anatolii-karpiuk · 7 months ago

<img width="1056" height="535" alt="Image" src="https://github.com/user-attachments/assets/1124fded-24d5-41bb-a98c-e31342298ac8" /> Still persists in windows. Latest claude code 2.1.5

kolkov · 7 months ago

Now I have files like this created right in the working repository at the root...

<img width="640" height="505" alt="Image" src="https://github.com/user-attachments/assets/0580aac0-34da-404b-97d6-deb53c7c98bd" />

rafaljasionowski · 7 months ago

Same issue:
<img width="281" height="756" alt="Image" src="https://github.com/user-attachments/assets/1bced9ab-4ef0-44d9-b204-25b56f912c81" />

cyanxwh · 7 months ago

Same issue

lifefloating · 7 months ago

+1 same issue

danielrodgers · 7 months ago

+1 same issue

zawraz · 7 months ago

+1

Ditronian · 7 months ago

+1, this is spewing these files out all over my Unity project...

erykwieliczko · 7 months ago

Anthopic - you have no moat. Just open-source Claude Code already, there is zero reason not to.

Opus 4.5 as "the best model" lasted for a few weeks. Now it really makes little difference if a prompt is ran on Claude Code with Opus 4.5 or on Codex/OpenCode with GPT-5.2.

Even GLM-4.7, albeit slow and less capable is very usable if you just give it a bunch of work (with a proper validation harness) and come back tomorrow.

As for CC pretty much every day I have a situation where one CC instance is eating 100% CPU just sitting there waiting for text input. And I have to run a while :; do chmod -R 777 /tmp/claude*; sleep 2; done simply because if you run two CC instances on different users they will fight over the permissions to the /tmp/claude* directories.

AI companies are like utility - you don't care where your electricity is coming from, only that it's 220V. And I'm certain that MiniMax 3, GLM-5, GPT-6 and Grok 5 will be better than Opus 4.6.

Again - you have no moat. Stop trying to build a "walled garden" and let people use a harness that's NOT broken. Or just open-source it so we can fix it by ourselves.
Moats aren't a thing when switching agents is literally an npm install away. And CC is the only major closed-source agent.

laywill · 7 months ago

+1

Affects Version / Steps to reproduce

Workaround

  • Add tmpclaude* to .gitignore
  • Add the following to claude.md:

``
Clean up any files that match the GLOB pattern
tmpclaude after you are done working using rm ./tmpclaude.
``

fav83 · 7 months ago

same issue on Windows and Claude Code 2.1.5

ezin82 · 7 months ago

same issue on Windows and Claude Code 2.1.5

xullul · 7 months ago

I have a workaround using a PowerShell script that runs automatically via Claude Code's Stop hook.
Work with Claude Code 2.1.5 on Windows

1. Create cleanup script at C:\Users\<YourUsername>\.claude\scripts\cleanup-claude-temp.ps1:

$locations = @($env:TEMP, $env:USERPROFILE, "<PATH_TO_PROJECT_ROOT>", (Get-Location).Path)
$patterns = @("tmpclaude-*", "claude--cwd*")
foreach ($loc in $locations) {
    if ($loc -and (Test-Path $loc)) {
        foreach ($pattern in $patterns) {
            Get-ChildItem -Path $loc -Filter $pattern -Recurse -Depth 3 -ErrorAction SilentlyContinue |
            Remove-Item -Force -ErrorAction SilentlyContinue
        }
    }
}
Replace <PATH_TO_PROJECT_ROOT> with your project directory (e.g., C:\Users\JohnDoe\ClaudeProjects)

2. Add Stop hook to your settings (C:\Users\<YourUsername>\.claude\settings.json):

{
  "hooks": {
    "Stop": [{
      "type": "command",
      "command": "powershell -ExecutionPolicy Bypass -File \"$HOME\\.claude\\scripts\\cleanup-claude-temp.ps1\""
    }]
  }
}

3. Restart all terminals and editors. Problem solve

SnirAzulay12 · 7 months ago

Same issue on Windows and Claude Code 2.1.5

MarlonAEC · 7 months ago

Same issue on windows 2.1.5

Javierdds · 7 months ago

Same issue on Windows and Claude Code 2.1.5

vicckuo · 7 months ago

Same issue on windows 2.1.5

ACEThreat · 7 months ago
I have a workaround using a PowerShell script that runs automatically via Claude Code's Stop hook. Work with Claude Code 2.1.5 on Windows 1. Create cleanup script at C:\Users\<YourUsername>\.claude\scripts\cleanup-claude-temp.ps1: $locations = @($env:TEMP, $env:USERPROFILE, "<PATH_TO_PROJECT_ROOT>", (Get-Location).Path) $patterns = @("tmpclaude-", "claude--cwd") foreach ($loc in $locations) { if ($loc -and (Test-Path $loc)) { foreach ($pattern in $patterns) { Get-ChildItem -Path $loc -Filter $pattern -Recurse -Depth 3 -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue } } } > Replace <PATH_TO_PROJECT_ROOT> with your project directory (e.g., C:\Users\JohnDoe\ClaudeProjects) 2. Add Stop hook to your settings (C:\Users\<YourUsername>\.claude\settings.json): { "hooks": { "Stop": [{ "type": "command", "command": "powershell -ExecutionPolicy Bypass -File \"$HOME\\.claude\\scripts\\cleanup-claude-temp.ps1\"" }] } } 3. Restart all terminals and editors. Problem solve

I get an error with this due to new format - had to switch settings.json to be:

{
  "hooks": {
    "Stop": [{
      "matcher": "",
      "hooks": [{
        "type": "command",
        "command": "powershell -ExecutionPolicy Bypass -File \"$HOME\\.claude\\scripts\\cleanup-claude-temp.ps1\""
      }]
    }]
  }
yamb0x · 7 months ago

same issue, very annoying

Erodenn · 7 months ago

+1 windows, at least update the changelog when you push the version please

tiredIsa · 7 months ago

+1 windows

neoking89 · 7 months ago
  • windows
gnalvesteffer · 7 months ago

+1

leex279 · 7 months ago

+1 windows

iwatts3519 · 7 months ago

+1 windows - only started for me today

slimshader · 7 months ago

+1

alessandrozuliani · 7 months ago

Duplicate of #17777

djamatgit · 7 months ago

+1

albswaai · 7 months ago

+1

Raithmir · 7 months ago

For the love of Claude. Stop with the +1 and "me too!".

We know. Just subscribe to the issue and wait for actual meaningful updates.

Caleb-KS · 7 months ago
> I have a workaround using a PowerShell script that runs automatically via Claude Code's Stop hook. Work with Claude Code 2.1.5 on Windows > 1. Create cleanup script at C:\Users\<YourUsername>\.claude\scripts\cleanup-claude-temp.ps1: > $locations = @($env:TEMP, $env:USERPROFILE, "<PATH_TO_PROJECT_ROOT>", (Get-Location).Path) > $patterns = @("tmpclaude-_", "claude--cwd_") > foreach ($loc in $locations) { > if ($loc -and (Test-Path $loc)) { > foreach ($pattern in $patterns) { > Get-ChildItem -Path $loc -Filter $pattern -Recurse -Depth 3 -ErrorAction SilentlyContinue | > Remove-Item -Force -ErrorAction SilentlyContinue > } > } > } > > Replace <PATH_TO_PROJECT_ROOT> with your project directory (e.g., C:\Users\JohnDoe\ClaudeProjects) > > > 2. Add Stop hook to your settings (C:\Users\<YourUsername>\.claude\settings.json): > { > "hooks": { > "Stop": [{ > "type": "command", > "command": "powershell -ExecutionPolicy Bypass -File "$HOME\.claude\scripts\cleanup-claude-temp.ps1"" > }] > } > } > 3. Restart all terminals and editors. Problem solve I get an error with this due to new format - had to switch settings.json to be: `` { "hooks": { "Stop": [{ "matcher": "", "hooks": [{ "type": "command", "command": "powershell -ExecutionPolicy Bypass -File \"$HOME\\.claude\\scripts\\cleanup-claude-temp.ps1\"" }] }] } ``

This seems like a good idea. How to handle the case where multiple claudes are running in the same folder?

ilrelax · 7 months ago

same issue

mr-jones123 · 7 months ago

Same issue. This is ridiculous

<img width="565" height="781" alt="Image" src="https://github.com/user-attachments/assets/706ab6c1-db6f-41dd-99fd-43ddb4e378ad" />

JoeSelfani · 7 months ago

+1 as well

<img width="277" height="269" alt="Image" src="https://github.com/user-attachments/assets/7ab4e0cb-382a-49aa-b688-399da40d4ef5" />

krugdenis · 7 months ago

<img width="525" height="599" alt="Image" src="https://github.com/user-attachments/assets/94d843cb-4e1d-463a-a0b5-167b2a0dfc0e" />
nice work :-D

AmirKhan47 · 7 months ago

this happening since last 2 days after i ddi claude update

ddm-j · 7 months ago

Also experiencing this issue. Over SSH in a vscode remote session.

tomyumm-ge · 7 months ago

Same here, that is funny

<img width="314" height="365" alt="Image" src="https://github.com/user-attachments/assets/8f09c4f3-f7b1-46ee-889e-e9ed8bbe9760" />

Platform: win64
Shell: PowerShell
Third-party endpoint (blue whale)

Staying up to date

tukao89 · 7 months ago

+1 v2.1.5 windows

Davronov-Alimardon · 7 months ago

also this version same issue

2.1.6 (Claude Code)

siyukok · 7 months ago

+1 2.1.6 (Claude Code) Windows

<img width="738" height="480" alt="Image" src="https://github.com/user-attachments/assets/e178683c-3767-4839-b411-9613a0b9e701" />

MDDev31 · 7 months ago

+1 v2.1.5 windows

Activer007 · 7 months ago

Linux users are fine, but on Windows it creates a bunch of temporary files and nul files directly in the current project’s root directory.

Linux 用户还好呢,windows 用户直接在当前项目根目录生成一堆临时文件和nul文件;

<img width="685" height="1163" alt="Image" src="https://github.com/user-attachments/assets/e8d549a7-b663-4111-9b67-58711a94ef4f" />

QianLongGit · 7 months ago

Version 2.1.6, the issue indeed still persists.

AlanAltonchi · 7 months ago

<img width="568" height="541" alt="Image" src="https://github.com/user-attachments/assets/d911992b-d9da-4185-9941-88fc58c873e8" />

v2.1.5

19Ash82 · 7 months ago

Same here. really annoying

<img width="376" height="914" alt="Image" src="https://github.com/user-attachments/assets/4ef67bcd-e44d-4ff6-b01d-c0118e022df1" />

thisisavs · 7 months ago

Please fix this. crazy annoying

vjekob · 7 months ago

Yeah, this is crazy! These files are now not showing in the tmp directory, but IN THE REPOSITORY, and not always in the same directory but scattered around!

Fix this, please, it's unmanageable!

AizenvoltPrime · 7 months ago

It seems the files get generated when claude executes bash commands on windows

pablos1rvent · 7 months ago

Please fix this... it's crazy annoying

pablos1rvent · 7 months ago
It seems the files get generated when claude executes bash commands on windows

Git Bash right?

AizenvoltPrime · 7 months ago
> It seems the files get generated when claude executes bash commands on windows Git Bash right?

Yes basically if I tell it to create a hello world file it wont generate any of the tmp files. When I tell it to delete it and it executes Bash tool it generates the tmp file.

pablos1rvent · 7 months ago
> > It seems the files get generated when claude executes bash commands on windows > > > Git Bash right? Yes basically if I tell it to create a hello world file it wont generate any of the tmp files. When I tell it to delete it and it executes Bash tool it generates the tmp file.

Do you have a rule to deny rm commands? Or maybe some git bash issue deleting files with rm command or preventing deleting, I don't know...

AizenvoltPrime · 7 months ago
> > > It seems the files get generated when claude executes bash commands on windows > > > > > > Git Bash right? > > > Yes basically if I tell it to create a hello world file it wont generate any of the tmp files. When I tell it to delete it and it executes Bash tool it generates the tmp file. Do you have a rule to deny rm commands? Or maybe some git bash issue deleting files with rm command or preventing deleting, I don't know...

No rules like that, I allow deletes. Its just an example. Any bash tool call will generate the tmp files.

pablos1rvent · 7 months ago
eythaann · 7 months ago

+1

GKMCM · 7 months ago

+1

JohnnyPixelz · 7 months ago

+1

lbowes-incremental · 7 months ago

+1

ontisme · 7 months ago

+1

ThimoDEV · 7 months ago

I got this also happening in a tanstack start project and even more so in my dotnet project

whisky0809 · 7 months ago

+1

kilianfug · 7 months ago

+1

armando-herastang · 7 months ago
It seems the files get generated when claude executes bash commands on windows

started happening for me yesterday/today after latest update. Windows 11 25H2! Running on Windows Terminal

mallen-jfi · 7 months ago

upvote

bdblaere · 7 months ago

+1

ZhuoRC · 7 months ago

+1

Lymdun · 7 months ago

+1

bradleygirl · 7 months ago

+1

patrkclarke · 7 months ago

+1

vishal-android-freak · 7 months ago

Claude... you cooked!

px-pmikolajczak · 7 months ago

+1

KiwoonKim · 7 months ago

<img width="271" height="642" alt="Image" src="https://github.com/user-attachments/assets/8ef81278-a3d4-41bf-8950-2ed6325a4791" />

same issue on 2.1.6 and windows 11 with bash.

addabis · 7 months ago

+1

timgu0 · 7 months ago

Thanks for the detailed write-up! This should be fixed in tomorrow's release

wolffiex collaborator · 7 months ago

*today's releae, right @timgu0 ?

wellitongervickas · 7 months ago

Just waiting to check if it fixed

JoelBiron · 7 months ago

+1

Kipstz · 7 months ago

+1

<img width="163" height="310" alt="Image" src="https://github.com/user-attachments/assets/55761015-2d97-4d69-9d03-2b0a17a84cd4" />

spookiaction · 7 months ago

Same

kala1883 · 7 months ago

2.1.7 version has fixed this issue.

josh-sachs · 7 months ago

2.1.7 does not fix this on windows at least.

suryapratap · 7 months ago
2.1.7 does not fix this on windows at least.

Please reopen the issue, it is not fixed

redrockvp · 7 months ago

Still an issue on 2.1.7 on Windows, yeah

AmirKhan47 · 7 months ago

seems fixed on windows

tomyumm-ge · 7 months ago

not yet for now, but it may be just needs to be arrived to me

AizenvoltPrime · 7 months ago

On windows 11 it doesnt generate tmp anymore for me.

astralmedia · 7 months ago

still happening for me on windows 2.1.7

timgu0 · 7 months ago

Checking again now. If it's still happening to you, do you mind sharing a screenshot of your claude with the version number and the path of these tmp files?

LuisAguilarDev · 7 months ago

<img width="1443" height="533" alt="Image" src="https://github.com/user-attachments/assets/a0713f5f-d0ef-4481-a5ac-2e1aa027c8aa" /> yep this is still happening

Varietyz · 7 months ago

Temporary Workaround: Automated Cleanup

I've created an automated solution that cleans up these temp files automatically: tmpclaude-auto-cleanup

Quick Setup (30 seconds)

Just copy the prompt from CLAUDE_PROMPT.md and paste it into Claude Code. Claude will configure everything automatically.

What It Does

  • Session Start Cleanup: Runs automatically when you start Claude Code
  • On-Save Cleanup: (Optional) Runs on every file save in VSCode
  • Cross-Platform: Works on Linux, macOS, Windows
  • Git Ignore: Prevents temp files from showing in git status

Manual Setup

Full instructions and manual configuration files available in the repo.

---

Note: This is a workaround until the core issue is fixed in Claude Code CLI. The real bug still needs to be addressed by Anthropic.

AmirKhan47 · 7 months ago

This is the reason people love opencode than claude code and yet they force claude code

songchao168 · 7 months ago

Yes, the problem still persists. I have just cleaned up dozens of CWD files.
os: win10

tomyumm-ge · 7 months ago

2.1.7 still happening here
win64 (windows 11)
Dev Drive (not wsl)

duanebc · 7 months ago

The best cleanup is never creating the files in the first place.

Seems that an environment variable is the fix. CLAUDE_CODE_TMPDIR

https://github.com/anthropics/claude-code/issues/18008#issuecomment-3751048803

ShonaDouglasKT · 5 months ago
The best cleanup is never creating the files in the first place. Seems that an environment variable is the fix. CLAUDE_CODE_TMPDIR #18008 (comment)

And yet new issues suggesting that are being closed as duplicates of this one. #31024

yurukusa · 5 months ago

Great analysis. Until the upstream fix lands, here's a simple cleanup approach:

Option 1: Stop hook (cleans up when Claude Code exits)

#!/bin/bash
# ~/.claude/hooks/cleanup-tmp.sh (Stop hook)
find /tmp -maxdepth 1 -name 'claude-*-cwd' -user "$(whoami)" -delete 2>/dev/null
exit 0  # exit 0 = don't block the stop
{
  "hooks": {
    "Stop": [
      {
        "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/cleanup-tmp.sh" }]
      }
    ]
  }
}

Option 2: Cron (catches sessions that crash without triggering Stop)

# Clean up every hour
echo '0 * * * * find /tmp -maxdepth 1 -name "claude-*-cwd" -mmin +60 -user "$(whoami)" -delete 2>/dev/null' | crontab -

The Stop hook handles normal exits; the cron catches edge cases. Both are safe — these files are only read once immediately after each Bash call, so deleting files older than 60 minutes has zero risk of interfering with active sessions.

yurukusa · 5 months ago

A Stop hook can clean these up at session end:

find /tmp -maxdepth 1 -name 'claude-*-cwd' -type f -mmin +60 -delete 2>/dev/null
exit 0

Add to ~/.claude/settings.json:

{
  "hooks": {
    "Stop": [{
      "matcher": "",
      "hooks": [{ "type": "command", "command": "~/.claude/hooks/tmp-cleanup.sh" }]
    }]
  }
}

Only deletes files older than 60 minutes so it won't affect active sessions. Or install it with:

npx cc-safe-setup --install-example tmp-cleanup
yurukusa · 5 months ago

You can clean these up automatically with a Stop hook that runs when each session ends:

find /tmp -maxdepth 1 -name 'claude-*-cwd' -mmin +5 -delete 2>/dev/null
find /tmp -maxdepth 1 -name 'claude-*' -type f -mmin +60 -delete 2>/dev/null
exit 0
// ~/.claude/settings.json
{
  "hooks": {
    "Stop": [{
      "hooks": [{ "type": "command", "command": "bash ~/.claude/hooks/cleanup-tmp.sh" }]
    }]
  }
}

This runs automatically when Claude Code stops (session end, Ctrl+C, /exit). The -mmin +5 avoids deleting files from a concurrent session.
One-liner to clear the backlog:

find /tmp -maxdepth 1 -name 'claude-*-cwd' -delete

If you want belt-and-suspenders, add a cron job alongside the hook:

echo "0 */6 * * * find /tmp -maxdepth 1 -name 'claude-*-cwd' -mmin +30 -delete" | crontab -

The Stop hook handles normal session ends; cron catches crashed sessions where Stop doesn't fire.

yurukusa · 5 months ago

/tmp/gh-comment-8856.md

alexanderadam · 1 month ago

Just to clarify in case the devs are not Linux users: modern *nix systems use /tmp with tmpfs and /var/tmp for disk.
This is true for a modern Fedora, a modern Ubuntu, a modern ArchLinux, Solaris etc

The way Claude Code is implemented right now, leaves all of these systems with less RAM the longer you use it. Even after you close it.

There are three things to tackle here:

1. The system prompt

The system prompt about the "Scratchpad Directory" explicitly refers putting everything into the directory /tmp/claude-<uid>/<sanitized-project-path>/<session-id>/scratchpad.
Which is obviously a terrible idea given, that this is an invitation to fill the user's memory with literal scratch data.

2. Missing clean up directive in the system prompt

Most people barely reboot their machines nowadays. Notebooks go into suspend/hibernation and people often just reboot when a system upgrade forces them to. So even _if_ we would not speak about memory here, the Claude Code agent should be advised to clean up once they don't need the data any more.
What if Claude Code sessions just stay open at people's machines?
Then Claude Code acts as a perpetuum trash generator.

3. Automatic clean up hook on close

Now the third fix would be to have a strict hook to clean the tmp session dir. This is just a boy scout rule and even if Claude forgets to clean up, we would have it done at latest once Claude is closed.
Naturally this won't help people who keep their session open and don't know what's happening because they think that using /clear is fine enough to start a new task.

4. Please do not suggest your SessionEnd advice!

Check on your docs where you suggest

{
  "hooks": {
    "SessionEnd": [
      {
        "matcher": "clear",
        "hooks": [
          {
            "type": "command",
            "command": "rm -f /tmp/claude-scratch-*.txt"
          }
        ]
      }
    ]
  }
}

Now, naive users would think that this is the fix number 3 that I just mentioned. But not only is /tmp/claude-scratch-*.txt the wrong path (it's /tmp/claude-<uid>/<sanitized-project-path>/<session-id>/scratchpad), but it would also remove the valid sessions if it would also delete all valid, still-running, sessions.
Replace the example with something else to avoid user confusion here. 😉

PS:

Probably duplicates of #46479, #75354
And using hardcoded tmpfs destinations (1, 2) leads to other issues like #64799

tongflau-dongzhu · 12 days ago

To be clear up front: this is not a fix for Claude Code itself — the leak needs an upstream fix, and I can see this thread is already trying plugin-based mitigations. I'm sharing an independent tool because the /tmp/claude-*-cwd flood is one instance of a broader problem I'm working on: agent workspaces accumulating byproducts with no policy and no undo.

workspace-metabolism is a zero-dependency Python CLI where one policy file (metabolism.json) decides what each path is worth, and nothing is ever deleted directly:

  • wm audit — read-only report: candidates, unregistered paths, growth trend
  • wm clean --grades G4 — moves expired items to a recycle area (dry-run by default)
  • wm rollback <run_id> — restores a run after a per-file SHA-256 integrity check
  • every action lands in a hash-chained journal; wm verify detects edits

It's early days (v0.2, no external users yet), so I'm looking for people to run it against real clutter. 30-second throwaway trial, nothing touches your real machine:

git clone https://github.com/metabolism-tools/workspace-metabolism.git
cd workspace-metabolism
python examples/demo.py
# read-only audit on a copy of your own workspace:
PYTHONPATH=src python -m workspace_metabolism audit --root /path/to/copy

Genuinely curious: for the 174-files-a-day case, would an "audit → recycle → rollback" workflow be more useful than a plain cleanup script — or is a delete-on-exit hook all you actually need?

alexanderadam · 12 days ago
To be clear up front: this is not a fix for Claude Code itself

It actually is, because it's a terrible combination of 4 different issues and all of them are directly coming from Claude Code/Anthropic.

For instance the system prompt itself advices agents to use /tmp/claude-<uid>/ for scratchpad things.
This should never be the case in the first place.

Just imagine an agent trying something out with an 8GB blob. Then by default it'll do the experiment in RAM. That memory is automatically lost during the experiment and that surely should _not_ be the case in the first place.
Scratchpad directories should _not_ be in /tmp/.
This is a change that needs to be done in the system prompt.

Also read about the other things that I mentioned.

Your Python script does not fix the root-cause.
It does not solve the issue of having agents putting trash into memory in the first place. Instead it looks like it tries to _guess_ what might be okay to be deleted by some rules.
That guesswork would be unnecessary if agents just automatically clean up themselves (see my second and third point).

tongflau-dongzhu · 12 days ago

You're right, and I understated it: this is squarely Claude Code's problem, and all four threads in your breakdown — scratchpad under /tmp/claude-<uid>/ as a system-prompt decision, the missing cleanup directive, the absent close hook, plus the tmpfs/RAM consequence — are upstream. Nothing external fixes them, and the dup trail (#46479, #75354) shows how long this has been known. Your tmpfs point also sharpens it: on systems where /tmp is RAM, even the 22-byte cwd files are memory staying allocated after you quit, not just disk clutter.

On "guesswork" — fair challenge, one correction: the tool doesn't guess. It only acts on an explicit metabolism.json policy the user writes and commits; audit is read-only, clean is dry-run by default, and nothing is deleted by pattern — items move to a recycle area and rollback restores them after a per-file SHA-256 check. It's mechanical enforcement of user-owned rules, not heuristics deciding what's trash. That said, your points 2 and 3 are the right endgame: if the agent cleaned up its own scratchpad, or a strict close hook did, no external layer is needed — I'd rather see those land than see anyone depend on a stopgap like mine.

The only honest niche left is the gap until that lands: Docker, WSL without systemd, Windows, multi-instance setups — where residue keeps growing today, and the usual "fix" is a blind rm -rf /tmp/claude-*, exactly the accident class your SessionEnd warning describes. A policy-plus-recycle design avoids deleting a valid running session by construction: nothing is ever glob-removed in place; it's moved per policy item and can be rolled back.

If Anthropic ships the prompt fix and the close hook, this tool's job for this case becomes nothing — that would be the best outcome. Have you gotten any traction from Anthropic on the system-prompt scratchpad point, or is #8856 stuck in maintainer limbo?

tongflau-dongzhu · 12 days ago

Following up on your review earlier today — it was acted on, and the changes shipped as v0.2.1:

  1. Your tmpfs point is now a first-class audit dimension. wm audit detects memory-backed mounts and reports residue there as a RAM cost, not just disk — the 22-byte-cwd-files-are-memory point, made visible instead of argued.
  2. The "guesswork" objection has a public answer. A new page, "What workspace-metabolism is not", takes your four objections in order — including the SessionEnd blind-delete accident class and why recycle + rollback avoids it by construction.
  3. The demo now shows the difference instead of claiming it. python examples/demo.py contrasts a blind rm (gone, no record, no undo) with the wm way (clean → recycle → rollback → verify) in about 30 seconds.

To be clear, nothing about my position changed: this is still not a fix for Claude Code — the scratchpad/system-prompt/close-hook work remains Anthropic's to do, and I'd still rather see that land than see anyone depend on this tool. If you have a minute, the positioning page is the part I'd value your read on most; it exists because of your comment.