On this page
Enumerate per-project scratchpad directories under /tmp/claude-<uid>/, measure tmpfs usage and newest mtime, and classify stale ones.
#claudewheel.scratchpad
#claudewheel.scratchpad
Scan the per-user Claude Code scratchpad tree under /tmp for stale data.
Claude Code sessions write scratchpad data under /tmp/claude-<uid>/<encoded-project>/<session-uuid>/.... Each top-level subdirectory of /tmp/claude-<uid>/ corresponds to one project. This module enumerates those per-project subdirectories, computing for each its real tmpfs block usage and the newest mtime anywhere in its tree, and classifies a directory as "stale" when nothing in it has been touched within :data:SCRATCHPAD_STALE_DAYS.
Size accounting mirrors :func:claudewheel.health._real_disk_usage: it walks with followlinks=False, lstats each entry, counts st_blocks * 512 for regular files only, and never follows symlinks (symlink targets living outside /tmp are never charged against /tmp space).
#tmp_claude_dir
def tmp_claude_dir() -> PathReturn the per-user Claude scratchpad root under /tmp.
#ScratchpadDir
One top-level per-project scratchpad directory and its measured facts.
size_bytes: real tmpfs block usage (st_blocks * 512) of the regular
files in its tree; symlinks and non-regular files contribute nothing.
newest_mtime: the newestlstatmtime of any entry in its tree
(directories and files, including the directory itself). Symlinks are lstat'd (their own mtime), never followed.
#age_days
def age_days(self, now: float) -> floatDays since the newest activity in this tree, relative to now (epoch).
#is_stale
def is_stale(self, now: float, stale_days: int=SCRATCHPAD_STALE_DAYS) -> boolTrue when the newest activity is older than stale_days before now.
#_scan_tree
def _scan_tree(root: Path) -> tuple[int, float]Return (real_block_bytes, newest_mtime) for the tree under root.
Mirrors :func:claudewheel.health._real_disk_usage for the size half: os.walk(followlinks=False) does not descend into symlinked directories, and lstat + S_ISREG counts only regular files (st_blocks * 512). The mtime half considers every directory and file encountered -- including root itself -- and uses each entry's own lstat mtime, so a symlink contributes its own mtime and is never followed to its target.
#scan_scratchpad_dirs
def scan_scratchpad_dirs(root: Path) -> list[ScratchpadDir]Enumerate the top-level per-project subdirectories of root.
Returns one :class:ScratchpadDir per immediate subdirectory (sorted by name), skipping non-directories and top-level symlinks (which are never followed). A missing or non-directory root yields an empty list.
#stale_scratchpad_dirs
def stale_scratchpad_dirs(root: Path, now: float, stale_days: int=SCRATCHPAD_STALE_DAYS) -> list[ScratchpadDir]Return the scratchpad subdirectories of root that are stale at now.