feat(plugin): add tmp-cleanup plugin for /tmp disk leak mitigation#39977
Open
zvndev wants to merge 1 commit intoanthropics:mainfrom
Open
feat(plugin): add tmp-cleanup plugin for /tmp disk leak mitigation#39977zvndev wants to merge 1 commit intoanthropics:mainfrom
zvndev wants to merge 1 commit intoanthropics:mainfrom
Conversation
Task .output files in /tmp/claude-{uid}/ grow without bound when
background tasks produce infinite output — interactive prompts in
non-interactive shells, verbose builds, or runaway processes. Users
have reported 46 GB+ per file, 95 GB+ per session, and up to 740 GB
total disk consumption. CWD tracking files (claude-*-cwd) also
accumulate at ~174/day without cleanup.
This plugin adds a SessionStart hook that automatically prunes both
file types using a three-pass strategy:
1. Delete .output files exceeding 100 MB (configurable)
2. Delete .output files older than 72 hours (configurable)
3. If remaining total exceeds 5 GB, prune largest files first
4. Delete stale claude-*-cwd files older than 24 hours
Safety measures:
- Symlink-safe: lstat + isSymbolicLink checks at every level
- Path validation: resolved paths verified within tmp base
- Ownership check: cwd files only deleted if UID matches
- Regular files only: never deletes directories or specials
- Cross-platform: exits cleanly on Windows (no getuid)
- All errors caught silently — never blocks session start
All thresholds configurable via CLAUDE_TMP_CLEANUP_* env vars.
Set CLAUDE_TMP_CLEANUP_DISABLED=1 to opt out entirely.
Closes anthropics#26911, closes anthropics#39909, closes anthropics#8856
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
This is already solvable with a Stop hook today — no plugin needed: find /tmp -maxdepth 1 -name 'claude-*' -type f -mmin +60 -delete 2>/dev/null
find /tmp -path '*/claude-*/tasks/*.output' -size +100M -delete 2>/dev/null
REMAINING=$(du -sh /tmp/claude-* 2>/dev/null | tail -1)
[ -n "$REMAINING" ] && echo "NOTE: Remaining /tmp/claude files: $REMAINING" >&2
exit 0Add to settings.json under USAGE=$(df /tmp --output=pcent 2>/dev/null | tail -1 | tr -d ' %')
[ "$USAGE" -gt 90 ] && echo "⚠ /tmp disk usage: ${USAGE}%" >&2
exit 0Install both: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a
tmp-cleanupplugin that automatically prunes two categories of leaked files from Claude Code's/tmpdirectory:.outputfiles — the primary disk killer. Background tasks and subagents produce.outputfiles with no size cap. Users have reported 46 GB+ per file, 95 GB+ per session, and up to 740 GB total consumption.claude-*-cwd) — small 22-byte files that accumulate at ~174/day without cleanup on crash.Why a plugin?
The root cause is in the compiled runtime (no size cap on output capture, no cleanup on session end). Until that's fixed upstream, this plugin provides immediate relief via the existing hook system — no binary patches, no external dependencies, runs on every session start.
Approach
A
SessionStarthook with a three-pass cleanup strategy:.outputfiles.outputfiles.outputfilesclaude-*-cwdfilesAll thresholds configurable via
CLAUDE_TMP_CLEANUP_*environment variables. SetCLAUDE_TMP_CLEANUP_DISABLED=1to opt out entirely.Safety
lstat(notstat) +isSymbolicLink()check at every directory and file levelresolve()d and verified to start with the tmp base directoryisFile()entries are deleted — never directories or special filesprocess.getuid()is unavailableComparison with existing PRs
.outputfiles (the 740 GB problem)cwdfilesFiles
Closes
.outputfiles in/tmpgrow unbounded (537 GB+).outputfiles grow unbounded (95 GB+)/tmp/claude-*-cwdfiles never deletedTest plan
process.getuid()(Windows)node -c).outputfiles are deleted (create >100 MB test file).outputfiles are deleted (touch file with old mtime)claude-XXXX-cwdpattern are cleanedCLAUDE_TMP_CLEANUP_DISABLED=1skips all cleanup🤖 Generated with Claude Code