Back to catalogue
ContextSessionStart· compact
Re-inject context after compaction
Conventions survive a context compaction
Re-injects the project conventions and critical context into the session after Claude Code compacts the context window, preventing the loss of important information.
What does the Re-inject context after compaction hook do?
Re-inject context after compaction is a Claude Code SessionStart hook matching compact. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Conventions survive a context compaction.
As a SessionStart 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
- Recall the project conventions (package manager, code style) after compaction
- Re-inject the current sprint or critical tasks
- Recall important test or build commands
Tags
#context#compaction#session#conventions
settings.json fragment
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/reinject-after-compact.mjs",
"type": "command"
}
],
"matcher": "compact"
}
]
}
}Script · .claude/hooks/reinject-after-compact.mjs
#!/usr/bin/env node
// @hookstack session-start-reinject-after-compact
// Réinjecte le contexte sauvegardé avant la dernière compaction (SessionStart)
import { existsSync, readdirSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { fileURLToPath } from "node:url";
export function run(
input,
{
exists = existsSync,
readFile = readFileSync,
readdir = readdirSync,
backupDir = "/tmp/claude-compact-backups",
} = {},
) {
const sessionId = input.session_id ?? "";
if (!exists(backupDir)) return null;
// Cherche le backup de la session courante en priorité, sinon le plus récent
let backupFile = sessionId ? join(backupDir, `${sessionId}.json`) : null;
if (!backupFile || !exists(backupFile)) {
const files = readdir(backupDir)
.filter((f) => f.endsWith(".json"))
.map((f) => ({
f,
mtime: new Date(
readFile(join(backupDir, f), "utf8")
.split('"saved_at":"')[1]
?.split('"')[0] ?? 0,
),
}))
.sort((a, b) => b.mtime - a.mtime);
backupFile = files[0] ? join(backupDir, files[0].f) : null;
}
if (!backupFile || !exists(backupFile)) return null;
try {
const { summary, saved_at } = JSON.parse(readFile(backupFile, "utf8"));
if (summary) {
return `## Contexte de la session précédente (avant compaction du ${saved_at})\n\n${summary}\n`;
}
} catch {
// Fichier corrompu — ignorer silencieusement
}
return null;
}
/* v8 ignore next 5 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
const input = JSON.parse(readFileSync(0, "utf8"));
const result = run(input);
if (result) process.stdout.write(result);
}