# How to Use the Pre‑Compact Hook for Context‑Window Management in Claude‑Code

> Master Claude Code context window management with the PreCompact hook. Preserve session state, log events, and annotate files before message summarization. Learn how now.

- Repository: [WorldFlowAI/everything-claude-code](https://github.com/WorldFlowAI/everything-claude-code)
- Tags: how-to-guide
- Published: 2026-09-07

---

**The Pre‑Compact hook runs just before Claude compacts the conversation context, allowing you to preserve session state, log compaction events, and annotate active session files before older messages are summarized.**

The **Pre‑Compact hook** is a Claude‑Code extension point that intercepts the automatic context compaction process. When a Claude session reaches its configured context‑window limit, the system truncates older messages and replaces them with a compressed summary. By hooking into this moment, you can capture critical state that would otherwise be lost.

This guide walks through enabling, customizing, and verifying the Pre‑Compact hook using the official `everything-claude-code` repository configuration.

---

## How the Pre‑Compact Hook Works

The hook executes immediately before Claude generates the context summary. Its core responsibilities include:

- **Logging the compaction event** for debugging and audit trails
- **Annotating the active session file** with a human‑readable timestamp marker
- **Persisting custom state** such as temporary files or environment snapshots

The implementation relies on three interconnected files: the global [`hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks.json) configuration that registers the hook, the Node script that performs the work, and a shared utility library for file operations.

---

## Hook Registration in hooks.json

Claude‑Code discovers hooks through the [`hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks.json) file. The **PreCompact** entry wires the context‑window management logic:

```json
// hooks/hooks.json – PreCompact section (lines 56-66)
"PreCompact": [
  {
    "matcher": "*",
    "hooks": [
      {
        "type": "command",
        "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/pre-compact.js\""
      }
    ],
    "description": "Save state before context compaction"
  }
]

```

The `matcher: "*"` ensures this hook runs for all sessions. The `${CLAUDE_PLUGIN_ROOT}` environment variable resolves to the plugin installation directory, making the path portable across installations.

---

## Core Implementation in pre-compact.js

The main hook logic lives in [`scripts/hooks/pre-compact.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/pre-compact.js). This script performs six sequential operations:

| Step | Operation | Source Reference |
|------|-----------|------------------|
| 1 | Resolve sessions directory via `getSessionsDir()` | [`utils.js:30-35`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/lib/utils.js#L30-L35) |
| 2 | Ensure directory exists with `ensureDir(sessionsDir)` | [`utils.js:54-58`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/lib/utils.js#L54-L58) |
| 3 | Append timestamped entry to [`compaction-log.txt`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/compaction-log.txt) | [`pre-compact.js:28-31`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/pre-compact.js#L28-L31) |
| 4 | Locate newest session file via `findFiles(sessionsDir, '*.tmp')` | [`utils.js:96-101`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/lib/utils.js#L96-L101) |
| 5 | Insert markdown annotation block into session file | [`pre-compact.js:34-40`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/pre-compact.js#L34-L40) |
| 6 | Emit log message to stderr for Claude visibility | [`pre-compact.js:41`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/pre-compact.js#L41) |

The hook uses `log('[PreCompact] State saved before compaction')` to provide real‑time feedback in Claude's interface.

---

## Utility Functions in utils.js

The [`scripts/lib/utils.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/lib/utils.js) library provides cross‑cutting functionality for hook implementations:

```javascript
// Key utilities used by PreCompact hook

// Returns ~/.claude/sessions
getSessionsDir()

// Creates directories recursively if missing
ensureDir(dirPath)

// Finds files by glob pattern, sorted by modification time
findFiles(directory, pattern)

// Generates YYYY-MM-DD_HH-MM-SS formatted timestamp
getDateTimeString()

// CLI output helper that writes to stderr
log(message)

```

These utilities standardize path resolution and file operations across all Claude‑Code hooks.

---

## Customizing the Pre‑Compact Hook

You can extend the default behavior to capture additional state. Below is a modified [`pre-compact.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/pre-compact.js) that backs up a custom JSON state file:

```javascript
// scripts/hooks/pre-compact.js – extended with state backup
const { copyFileSync, existsSync } = require('fs');
const path = require('path');
const { getSessionsDir, getHomeDir, getDateTimeString, log } = require('../lib/utils.js');

const sessionsDir = getSessionsDir();
const STATE_FILE = path.join(getHomeDir(), '.myapp/state.json');

// Default: log compaction event
// (existing lines 28-31 here)

// Custom: backup state file if present
if (existsSync(STATE_FILE)) {
  const backupName = `state-backup-${getDateTimeString()}.json`;
  const backupPath = path.join(sessionsDir, backupName);
  copyFileSync(STATE_FILE, backupPath);
  log(`[PreCompact] State file backed up to ${backupPath}`);
}

// Default: annotate session file
// (existing lines 34-41 here)

```

Place this logic after the compaction log entry and before the session file annotation.

---

## Verifying Hook Execution

To confirm the Pre‑Compact hook fired correctly:

1. **Check the compaction log:**

```bash
cat ~/.claude/sessions/compaction-log.txt

```

Expected output:

```

[2026-09-07 14:27:12] Context compaction triggered

```

2. **Inspect the annotated session file:**

```bash
cat ~/.claude/sessions/$(ls -t ~/.claude/sessions/*.tmp | head -1)

```

Look for the inserted markdown block:

```

---
**[Compaction occurred at 14:27]** - Context was summarized

```

3. **Review Claude's output panel** for the log message:

```

[PreCompact] State saved before compaction

```

---

## Alternative Entry Point: Bash Wrapper

The repository includes a shell script alternative at [`hooks/memory-persistence/pre-compact.sh`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/memory-persistence/pre-compact.sh). This wrapper provides the same functionality for environments where Node is unavailable or for users preferring shell implementations. Both entry points use the same [`utils.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/utils.js) library through Node's `child_process` when needed.

---

## Key Files Reference

| File | Purpose | Location |
|------|---------|----------|
| [`hooks/hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/hooks.json) | Hook registry and configuration | [[`hooks/hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/hooks.json)](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/hooks.json#L56-L66) |
| [`scripts/hooks/pre-compact.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/pre-compact.js) | Main Node implementation | [[`scripts/hooks/pre-compact.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/pre-compact.js)](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/pre-compact.js) |
| [`hooks/memory-persistence/pre-compact.sh`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/memory-persistence/pre-compact.sh) | Bash alternative entry point | [[`hooks/memory-persistence/pre-compact.sh`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/memory-persistence/pre-compact.sh)](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/memory-persistence/pre-compact.sh) |
| [`scripts/lib/utils.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/lib/utils.js) | Shared utilities for file I/O and logging | [[`scripts/lib/utils.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/lib/utils.js)](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/lib/utils.js) |

---

## Summary

- The **Pre‑Compact hook** executes immediately before Claude summarizes conversation context, preventing silent data loss
- Enable it through the **PreCompact entry in [`hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks.json)**, which invokes [`scripts/hooks/pre-compact.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/pre-compact.js)
- The default implementation **logs compaction events** to [`compaction-log.txt`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/compaction-log.txt) and **annotates active session files** with markdown timestamps
- Extend the hook by modifying [`pre-compact.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/pre-compact.js) to capture custom state using utilities from [`scripts/lib/utils.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/lib/utils.js)
- Verify execution through log files, session annotations, and Claude's stderr output

---

## Frequently Asked Questions

### What triggers the Pre‑Compact hook to run?

Claude‑Code invokes the Pre‑Compact hook automatically when a conversation approaches the configured context‑window limit and the system prepares to summarize older messages. This occurs transparently during long sessions without user intervention. The hook fires once per compaction event.

### Can I disable the Pre‑Compact hook if I don't need it?

Yes. Remove or comment out the **PreCompact array** in [`hooks/hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/hooks.json) (lines 56-66). Claude‑Code will then compact context without executing custom preservation logic. Alternatively, set the `matcher` to a non‑matching pattern like `"none"` to disable it selectively.

### How is this different from the Post‑Compact hook?

The **Pre‑Compact hook** runs *before* summarization, giving you access to the full, uncompacted conversation state. A Post‑Compact hook would run *after* the summary is applied, when original messages may already be truncated. Use Pre‑Compact to capture data; use Post‑Compact (if implemented) to react to the new compacted state.

### Why does the hook write to stderr instead of stdout?

Claude‑Code captures **stderr for log visibility** in the interface while treating stdout as potential command output. The `log()` function in [`utils.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/utils.js) deliberately writes to `process.stderr` so compaction notifications appear in Claude's activity panel without interfering with any structured data the hook might emit to stdout.