Survive Compaction

When Claude Code compacts a long conversation, the summary keeps the gist and drops the details. Post-compaction recall puts the details back: right after every compaction, a hook re-injects your project's most recent ContextForge memories and pending tasks into the model's context. Ships in contextforge-mcp 0.12.0. Claude Code only.

The problem

Long sessions fill the context window. Claude Code compacts the conversation, either when you run /compact or automatically when it runs out of room. The summary it keeps is good at the big picture and bad at specifics. What usually goes missing is exactly what you need next:

  • Decisions you made an hour ago and the reasons behind them.
  • Which tasks were done, which are still pending, and what was agreed as the next step.
  • Corrections you gave the agent that it now silently forgets.

The agent does not know what it lost. After compaction it keeps working from the summary as if nothing happened, so the drift only shows up when it re-asks a settled question or undoes a decision.

How it works

Two pieces: a Claude Code hook and a CLI subcommand.

1. The hook installed by init

npx contextforge-mcp init now adds a SessionStart hook with the compact matcher to your project's .claude/settings.json. Claude Code runs it right after every compaction and appends the command's stdout to the model's context.

# .claude/settings.json

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          { "type": "command", "command": "npx -y contextforge-mcp recall" }
        ]
      }
    ]
  }
}

init merges into an existing settings.json without touching other keys or hooks, and is idempotent: re-running it prints "already present". Cursor gets nothing here, since it has no hooks.

2. The recall subcommand

contextforge-mcp recall resolves your API key (from CONTEXTFORGE_API_KEY, else the contextforge server entry in ~/.claude.json, else the project's .mcp.json), reads the linked project from .contextforge in the repo root, fetches the project's 10 most recent memories across its spaces and up to 5 pending tasks, and prints a plain-text block like this:

# stdout of npx contextforge-mcp recall

## ContextForge: context restored after compaction

Recent memories:
- [Decisions] Keep Supabase magic links, drop password login — Decided after the support thread on 2026-09-22. Password reset emails were the top ticket…
- [API] Rate limit is 60 requests per minute per key — Enforced in the edge function. Return 429 with a Retry-After header, never a 500…

Pending tasks:
- [f8drg2] Ship the billing webhook retry (high, due 2026-09-30)
- [k2m9xa] Write the 0.12.0 release notes (medium, due 2026-10-02)

For anything older or more specific, call memory_query before answering.

It never blocks a session. No key, no linked project, a network error, or the 8 second timeout all mean it prints nothing and exits 0. A normal run takes about 4 seconds.

New users

Nothing extra. Run init in the project, as in the "Initialize your project" step of the quick start, and the hook is installed along with everything else:

cd ~/your-project
npx contextforge-mcp init

Existing users

Two steps: get 0.12.0, then re-run init once per project.

1. Update the package

If you installed it globally, update it. If you only ever used npx, you get 0.12.0 on the next launch. Either way, check the version, because a global install of an older version shadows npx:

npm update -g contextforge-mcp
npx contextforge-mcp --version   # expect 0.12.0 or newer

2. Re-run init in each project

It only adds the missing hook. Your CLAUDE.md, other hooks and other settings keys are left as they are.

cd ~/your-project
npx contextforge-mcp init

Prefer to do it by hand? Paste the hooks.SessionStart group from the snippet above into your project's .claude/settings.json. If you already have a SessionStart array, add the group to it instead of replacing it.

Verify it works

  • From the project folder, run the subcommand directly. You should see the block above with your own memories and tasks. Empty output means no key or no linked project.
  • Then, in Claude Code, run /compact and ask "what context did you just receive?". The agent should repeat the memories and tasks from the block.
cd ~/your-project
npx contextforge-mcp recall

Requirements and limits

  • Claude Code only. The hook lives in .claude/settings.json. Cursor has no hooks, so nothing is installed there.
  • A linked project. The project needs a .contextforge file in the repo root. See Project Linking.
  • It only re-injects what you saved. The block holds the 10 most recent memories and up to 5 pending tasks from ContextForge. It cannot tell you what the compaction summary dropped, because it never sees the conversation.
  • So save decisions as you go. Ask the agent to "save where we are and what's next" before a long stretch of work. What is in ContextForge comes back; what was only in the chat does not.

Troubleshooting

The hook runs but injects nothing

A stale export CONTEXTFORGE_API_KEY=... in your shell rc takes precedence over ~/.claude.json. If that key is old, the hook silently prints nothing. Remove the export or replace the key, then re-run npx contextforge-mcp recall to confirm.

The hook runs an old version

An old global install makes npx -y contextforge-mcp run the old version, which has no recall subcommand. Check and update it:

which contextforge-mcp
npm update -g contextforge-mcp
npx contextforge-mcp --version

Empty output, key is fine

The project is not linked. There must be a .contextforge file in the repo root. Ask the agent to "link project" (it uses cf_tools), then run recall again.