HookStack
Back to catalogue
WorkflowSessionEnd

Temporary file cleanup at session end

Sessions end with a clean logs directory

Automatically removes temporary files (.tmp) and stale artifacts from the logs directory at session end.

What does the Temporary file cleanup at session end hook do?

Temporary file cleanup at session end is a Claude Code SessionEnd hook. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Sessions end with a clean logs directory.

As a SessionEnd hook it runs after the action, reacting to what just happened rather than blocking it. Because it is a deterministic Node.js script, it executes on every matching event without relying on the model to remember — the guarantee that makes agentic workflows safe to automate.

Use cases

  • Keep a clean logs directory without manual intervention
  • Free disk space at the end of a long session

Tags

#cleanup#session#temp-files#maintenance

settings.json fragment

{
  "hooks": {
    "SessionEnd": [
      {
        "hooks": [
          {
            "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/session-end-cleanup.mjs",
            "type": "command"
          }
        ],
        "matcher": ""
      }
    ]
  }
}

Script · .claude/hooks/session-end-cleanup.mjs

#!/usr/bin/env node
// @hookstack session-end-cleanup-temp
// Nettoie les fichiers temporaires Claude datant de plus de 24h (SessionEnd)
import { readdirSync, statSync, unlinkSync } from "node:fs";
import { join } from "node:path";
import { fileURLToPath } from "node:url";

const MAX_AGE_MS = 24 * 60 * 60 * 1_000;
const PREFIX = "claude-";

export function run({
	readdir = readdirSync,
	stat = statSync,
	unlink = unlinkSync,
	tmp = "/tmp",
	maxAge = MAX_AGE_MS,
	now = () => Date.now(),
} = {}) {
	let cleaned = 0;
	try {
		for (const f of readdir(tmp)) {
			if (!f.startsWith(PREFIX)) continue;
			const fp = join(tmp, f);
			try {
				const age = now() - stat(fp).mtimeMs;
				if (age > maxAge) {
					unlink(fp);
					cleaned++;
				}
			} catch {}
		}
	} catch {}

	return cleaned > 0
		? {
				cleaned,
				message: `[session-end-cleanup] ${cleaned} fichier(s) temporaire(s) supprimé(s).\n`,
			}
		: { cleaned: 0 };
}

/* v8 ignore next 4 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
	const result = run();
	if (result?.message) process.stderr.write(result.message);
}

Learn more

Related hooks