Teaching Claude to Remember Before It Forgets 🧠🦆

There is a moment in long Claude Code sessions where the conversation compresses. Context fills up, Claude quietly collapses the history into a summary, and when it resurfaces it is still working on your problem but with a slightly hazier sense of where you were.

I accepted this for a while as the background cost of long sessions. Context windows are finite. Summaries are necessary. What I had not done was look for a lever.

There is one. It is called PreCompact.

This hook fires immediately before Claude Code compacts the conversation, whether you run /compact manually or the context window fills on its own. You can register a shell command that runs at that moment and outputs a JSON object containing custom_instructions. Claude folds that into the compaction process.

The constraint is important: this hook cannot stop compaction. Exit code 2, which blocks other hooks like PreToolUse, does nothing here. The summary will happen regardless. What you are influencing is what survives.

That reframe changed how I think about it. You are not preventing memory loss. You are leaving a structured note for the version of Claude that wakes up on the other side.

What Goes in the Note

I have found there are two categories of things worth injecting.

1) Facts the hook can discover

The first category is observable state. The current git branch is the most useful signal. In many workflows, branches are named after tickets, so the branch alone often encodes what is actively in progress.

A minimal hook can read the current branch, extract a ticket identifier if present, collect a short list of recent commits, and check for uncommitted changes. This is measurable state. No inference required.

The script formats that state into a compact markdown snapshot and wraps it as JSON under a custom_instructions key. That JSON is written to stdout. Claude Code consumes it during compaction.

2) Guidance about what to preserve

The second category is emphasis.

Claude does not automatically know which details represent active state versus conversational noise. If you do not tell it that the current failing test matters, it may summarize around it. If you do not tell it that you are mid-refactor, that phase boundary may disappear.

My guidance list is short and specific: preserve the active task and ticket, any in-progress TDD phase, unresolved errors or blocked steps, decisions made and the reasoning behind them, and the next concrete action if the session was mid-task.

The hook does not force these into the summary. It biases the summarizer toward them.

A Minimal Hook Sketch

Instead of a full implementation, here is the structural shape in pseudocode:

#!/usr/bin/env bash

# 1. Gather observable repository state
branch = git_current_branch()
ticket = extract_ticket_id(branch)
recent_commits = git_recent_commits(limit=5)
dirty_files = git_uncommitted_changes(limit=10)

# 2. Build a structured snapshot
snapshot = format_markdown(
  branch,
  ticket,
  recent_commits,
  dirty_files
)

# 3. Add preservation guidance
instructions = snapshot + """
Preserve in summary:
- current task and active ticket
- TDD state (red/green/refactor)
- unresolved errors or blocked steps
- key decisions and rationale
- next concrete action
"""

# 4. Emit JSON for Claude Code
print_json({ "custom_instructions": instructions })

Mechanically, that is all it does. Read state. Format it. Emit JSON.

Registering the Hook

In your project’s .claude/settings.local.json, register a PreCompact hook:

{
  "hooks": {
    "PreCompact": [
      {
        "matcher": "auto|manual",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/project/.claude/hooks/pre-compact.sh"
          }
        ]
      }
    ]
  }
}

The auto|manual matcher fires for both automatic and manual compaction. If you only want this behavior when explicitly running /compact, use manual.

What It Actually Measures

The honest answer is: not much, directly.

Compaction quality is subjective. Auto-compact fires at irregular moments. To measure improvement rigorously, you would need to rate post-compact recovery quality, count clarification turns, and repeat that across enough sessions to see a pattern. That is more instrumentation than I am willing to build for something that triggers occasionally.

What this hook really is: a low-cost hedge against a bad edge case. The setup takes an afternoon. The upside is that when compaction happens at the worst possible moment, the summary is more likely to retain the state that matters.

There is also a manual technique worth knowing. When you invoke /compact yourself, you can append inline context.

/compact debugging failing auth test, next step is static analysis

That trailing text becomes part of the compaction instruction. The hook supplements this. It does not replace it.

The core idea is simple. When the session collapses, a small, structured reminder is already waiting.

It is a quiet adjustment. No new tools. No elaborate scaffolding. Just a note slipped under the door before the lights flicker.

Comments