feat: Add tmp-cleanup plugin to mitigate /tmp file leak (#8856)#33015
Open
qbit-glitch wants to merge 1 commit intoanthropics:mainfrom
Open
feat: Add tmp-cleanup plugin to mitigate /tmp file leak (#8856)#33015qbit-glitch wants to merge 1 commit intoanthropics:mainfrom
qbit-glitch wants to merge 1 commit intoanthropics:mainfrom
Conversation
…nthropics#8856) Adds a new plugin that cleans up orphaned working directory tracking files created by the Bash tool. These files are never deleted by the runtime, accumulating hundreds per day as reported in anthropics#8856. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This was referenced Mar 11, 2026
12 tasks
|
A Notification start + Stop hook pair can handle tmp cleanup: find /tmp -name 'claude-*' -mmin +120 -delete 2>/dev/null
find /tmp -name 'cc-*' -mmin +120 -delete 2>/dev/null
echo "Cleaned stale tmp files" >&2
exit 0Also as a Stop hook for post-session cleanup: find /tmp -name 'cc-*' -user $(whoami) -delete 2>/dev/null
exit 0 |
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 new tmp-cleanup plugin that mitigates #8856 — the accumulation of orphaned
/tmp/claude-{hex}-cwdfiles created by the Bash tool.As documented in #8856, every Bash tool invocation creates a temporary file to track the working directory, but
fs.unlinkis never called afterward. Users report 174+ files per day accumulating indefinitely untilsystemd-tmpfiles-cleanruns (Linux) or manual cleanup.This plugin does not patch the core runtime (which is closed-source). It provides a hook-based workaround that cleans up stale files automatically.
What it does
Two hooks, sharing a common module:
tmp_cleanup_post_tool.pytmp_cleanup_stop.pyBoth hooks use the same 60-second staleness threshold. Neither hook performs unconditional deletion — files from concurrent Claude Code sessions are preserved.
Safety measures
Each of these was specifically tested (see Test Plan below):
os.lstat()checks beforeos.unlink()— symlinks are detected and skipped, never followed. Prevents the classic/tmpsymlink attack on shared systems.stat.S_ISREG()check ensures only regular files are deleted (not directories, pipes, devices).glob("claude-????-cwd")narrows to exactly 4 wildcard characters, thenre.compile(r"^claude-[0-9a-f]{4}-cwd$")validates the basename contains only lowercase hex.mtimeolder than 60 seconds are removed. The runtime reads the file immediately after command execution, so a 60-second window provides ample safety margin.hooks.jsonprevents blocking Claude Code if/tmpis slow or contains many files.try/except ImportErroron module import with JSONsystemMessagefallback.try/except OSErroron all file operations. Hook failures don't affect Claude Code operation.tempfile.gettempdir()instead of hardcoded/tmp. Works on Linux (/tmp) and macOS (/private/tmp). On Windows the plugin has no effect (no matching files exist).Files added (6 files, 201 lines)
Convention compliance
security-guidance,hookify, and other existing pluginshooks.jsonformat matches existing plugins (withtimeoutfield as used byhookify)matcherfield (consistent withhookifyandralph-wiggumStop hooks)#!/usr/bin/env python3shebang (consistent withsecurity-guidance)systemMessageoutput for observabilityLimitations (stated explicitly)
cli.jsruntime wherefs.unlinkis never called after reading the cwd file. Only an Anthropic engineer with source access can fix the actual leak.os.lstat()andos.unlink(). This is not practically exploitable —os.unlink()on a symlink removes the link (not the target), and hardlink creation in/tmpis restricted on modern Linux (kernel 3.6+,fs.protected_hardlinks=1) and macOS.Test plan
All tests were run and passed locally (Python 3.14, macOS Darwin 25.2.0):
py_compilepasses on all 3 Python filesjson.load()passes onhooks.jsonandplugin.jsonfrom cwd_file_cleanup import run_hooksucceedstry/except ImportErrorwith JSON fallbackos.lstat()detects it and skips deletion, confirmed the symlink target file is preservedclaude-abcd-cwdandclaude-1234-cwd, rejectsclaude-ABCD-cwd(uppercase),claude-abcde-cwd(5 chars),claude-abc-cwd(3 chars),claude-my-backup-cwd(arbitrary string),claude--cwd(empty)"timeout": 10inhooks.jsonmatcherfield, both entry points have shebangs, no hardcoded/tmpin metadata filestempfile.gettempdir()resolves correctly on macOSCloses #8856
🤖 Generated with Claude Code