# How the `suggest-compact` Hook Works in Claude Code: A Technical Deep Dive

> Uncover the technical details of the suggest-compact hook in Claude Code. Learn how it manages context window pressure and prevents automatic truncation, boosting your workflow efficiency.

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

---

**The `suggest-compact` hook tracks tool calls and prints a reminder to run `/compact` when a configurable threshold is reached, helping users manage context window pressure without automatic truncation.**

The `suggest-compact` hook in the `WorldFlowAI/everything-claude-code` repository implements a **manual compaction reminder** that runs before tool operations. Unlike automatic compaction, this hook preserves user agency by suggesting — not forcing — context cleanup at strategic checkpoints.

## What the `suggest-compact` Hook Does

The hook serves as a **conversation health monitor**. It counts how many tool calls have occurred since the start of the session and emits a friendly nudge to consider `/compact` when:

- The call count hits a configurable threshold (default: 50)
- Subsequent multiples of 25 calls occur thereafter

Crucially, the hook **does not trigger compaction itself**. It only surfaces a suggestion, leaving the decision to the user. This design avoids interrupting workflows mid-thought while still combatting context staleness.

## Hook Registration and Configuration

The hook integrates with Claude Code's **PreToolUse event system**. In [`skills/strategic-compact/suggest-compact.sh`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/skills/strategic-compact/suggest-compact.sh) (lines 11–20), the registration pattern matches any tool named `Edit` or `Write`, ensuring the counter increments during active file modifications.

```json
{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{
        "type": "command",
        "command": "~/.claude/skills/strategic-compact/suggest-compact.sh"
      }]
    }]
  }
}

```

Place this configuration in `~/.claude/settings.json` to enable the hook globally.

## The Counter Mechanism: How Call Tracking Works

### Counter File Creation and Persistence

The hook maintains state using a **PID-scoped temporary file** in `/tmp`. The file path `claude-tool-count-$$` incorporates the shell process ID (`$$`), ensuring isolation between concurrent Claude sessions.

As implemented in [`suggest-compact.sh`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/suggest-compact.sh) (lines 30–42):

```bash
COUNTER_FILE="/tmp/claude-tool-count-$$"

if [[ -f "$COUNTER_FILE" ]]; then
    COUNT=$(cat "$COUNTER_FILE")
    COUNT=$((COUNT + 1))
else
    COUNT=1
fi

echo "$COUNT" > "$COUNTER_FILE"

```

This plain-integer approach avoids dependencies and survives across multiple hook invocations within the same process tree.

### Threshold Evaluation and Messaging

The hook compares the current count against two triggers, defined in [`suggest-compact.sh`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/suggest-compact.sh) (lines 44–52):

1. **Initial threshold**: When `count === COMPACT_THRESHOLD` (default 50)
2. **Periodic reminders**: Every 25 calls thereafter (`count % 25 === 0`)

The output messages differ slightly to guide user behavior:

```bash

# First threshold (line 46)

echo "[StrategicCompact] 50 tool calls reached - consider /compact if transitioning phases" >&2

# Periodic reminders (line 51)

echo "[StrategicCompact] ${COUNT} tool calls - good checkpoint for /compact if context is stale" >&2

```

Both messages route to **stderr** (`>&2`) to appear in Claude's console without contaminating tool output streams.

## JavaScript Implementation: [`scripts/hooks/suggest-compact.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/suggest-compact.js)

The repository provides an equivalent **Node.js implementation** for users preferring JavaScript hooks. The core algorithm remains identical:

- Temporary directory resolution via `getTempDir()` from `scripts/lib/utils`
- File-based counter using Node's `fs` API
- Same threshold logic and message formatting
- `log()` utility for stderr output

The JavaScript version differs only in **path derivation** and **API surface** — the behavioral contract is preserved for consistency across shell and Node environments.

## Configuration via Environment Variables

Customize the hook's sensitivity by setting `COMPACT_THRESHOLD` before launching Claude:

```bash
export COMPACT_THRESHOLD=30   # Earlier suggestions

export COMPACT_THRESHOLD=100  # Delayed suggestions for long-haul sessions

```

Unset or absent, the default of 50 applies as defined in [`suggest-compact.sh`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/suggest-compact.sh) (line 44).

## Why Manual Suggestion Beats Auto-Compact

The `suggest-compact` hook's design reflects deliberate trade-offs:

| Approach | Behavior | Risk |
|----------|----------|------|
| **Auto-compact** | Truncates context automatically | Cuts off reasoning mid-task, loses critical state |
| **`suggest-compact` hook** | Surfaces reminders at user-controlled checkpoints | Requires manual intervention, but preserves intent |

By waiting for natural phase transitions — after research before coding, after implementation before testing — the hook helps users **compress context without compression artifacts**.

## Testing and Verification

Unit tests in [`tests/hooks/hooks.test.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/tests/hooks/hooks.test.js) verify:

- Counter increment behavior across invocations
- Threshold detection accuracy
- Message formatting and stderr routing
- PID isolation between sessions

These tests ensure the hook behaves predictably across shell environments and Node versions.

## Summary

- The `suggest-compact` hook tracks tool calls via a **PID-scoped temporary file** in `/tmp`
- It **suggests** `/compact` at 50 calls by default (configurable via `COMPACT_THRESHOLD`), then every 25 calls
- Two implementations exist: **[`skills/strategic-compact/suggest-compact.sh`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/skills/strategic-compact/suggest-compact.sh)** (Bash) and **[`scripts/hooks/suggest-compact.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/suggest-compact.js)** (Node.js)
- Messages route to **stderr** to avoid polluting tool output
- Registration occurs through **`PreToolUse`** events matching `Edit` and `Write` tools

## Frequently Asked Questions

### How do I enable the `suggest-compact` hook in my Claude Code setup?

Add the JSON configuration from the hook registration section to `~/.claude/settings.json`, ensuring the path to [`suggest-compact.sh`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/suggest-compact.sh) resolves correctly on your system. Restart Claude Code to load the new hooks.

### What's the difference between the Bash and JavaScript implementations?

Functionally none — both implement identical counting, threshold logic, and messaging. Use the Bash version for minimal dependencies or the JavaScript version if your Claude Code installation runs hooks through Node.

### Why does the hook use `/tmp` for state instead of memory?

The `/tmp` file persists across separate PreToolUse invocations within the same session. Memory-based state would reset between hook calls since each invocation is a fresh process. The PID in the filename (`claude-tool-count-$$`) prevents collisions between concurrent sessions.

### Can I disable the periodic reminders after the first suggestion?

Not without modifying the source. The `count % 25 === 0` logic in [`suggest-compact.sh`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/suggest-compact.sh) (line 49) is hardcoded. To change this behavior, fork [`skills/strategic-compact/suggest-compact.sh`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/skills/strategic-compact/suggest-compact.sh) and adjust the modulo interval or remove the periodic branch entirely.