[FEATURE] Hook write access to conversation history for in-session context eviction

Resolved 💬 3 comments Opened Mar 16, 2026 by fdaviddpt Closed Mar 16, 2026

[FEATURE] Hook write access to conversation history for in-session context eviction

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

Tool outputs are the #1 context consumer in long Claude Code sessions — and once they're in context, they're permanent until a full /compact.

A concrete example from our codebase: reading a 200-line file to edit one line costs ~4000 tokens, permanently. A "quick edit" session with five file reads consumes ~25% of the context window before a single line of code is written. There's no way to say "I'm done with that file — compress it."

The current options:

  • /compact — all-or-nothing. Summarizes everything. You lose precision on recent context to reclaim old context.
  • Sub-agent delegation — helps, but adds latency and coordination overhead for what should be simple operations.
  • Don't read the file — not realistic.

What's missing: a way to selectively evict or summarize specific tool outputs after they've served their purpose.

Proposed Solution

Extend the PostToolUse hook response format with an optional context_directive field:

{
  "context_directive": "summarize",
  "summary": "Read posts-data.php: 64 blog entries, post 61 has pending flag",
  "retain_turns": 3
}

Three directives:

| Directive | Behavior |
|-----------|----------|
| summarize | Replace the tool output in context with the provided summary string |
| trim | Reduce output to first/last N lines (useful for command outputs where only the tail matters) |
| retain_turns | Keep full output for N more turns, then auto-apply the directive (deferred eviction) |

The hook has full context: tool type, file path, turn number, output size. It can implement any eviction policy — LRU, type-based, age threshold, importance scoring, or project-specific logic. Claude Code provides the mechanism; the hook decides the policy.

Alternative Solutions

Current workarounds all fall short:

  • /compact is all-or-nothing — it summarizes the entire conversation, trading precision on recent context to reclaim space from old context. There's no surgical option.
  • Sub-agent delegation offloads work to a fresh context window, but adds latency and coordination overhead for what should be simple read-then-edit operations.
  • Lazy-loading (community workaround, see #19105) — architectural pattern to delay tool calls, but doesn't help once outputs are already in context.
  • Context virtualization via MCP (see #34391) — third-party server approach that works around the limitation rather than addressing it.

Six related issues show the community has been circling this problem from multiple angles:

  • #28984 — Increase effective context window / reduce compaction overhead
  • #14245 — Surgical context compaction (/shrink command)
  • #24058 — Let Claude trigger context compaction via tool call
  • #27298 — Layered memory system for persistent cross-session context
  • #19105 — Lazy-Loading Architecture for Token Optimization
  • #34391 — Context Mode (third-party MCP server for context virtualization)

All of these work around the inability to modify conversation history from outside the model. Context directives would make them composable — a hook-based eviction policy could implement any of these strategies without requiring model-side changes or new slash commands.

Priority

High - Significant impact on productivity

Feature Category

Configuration and settings

Use Case Example

Step-by-step scenario showing the full lifecycle of context eviction in a real editing session:

  1. Turn 1: Agent reads config.php (200 lines) to find the value to edit. Claude Code adds the full file output to context: ~4000 tokens.
  2. Turn 2: Agent edits line 47. The file read has served its purpose — but those 4000 tokens remain in every subsequent API call.
  3. Turn 3: The next tool call fires. PostToolUse hook runs. Hook logic: "Turn 1 output was a Read, it's 2 turns old, and the edit is complete — summarize it."
  4. Hook returns:

``json
{
"context_directive": "summarize",
"summary": "Read config.php (200 lines): DB config, cache settings, module options. Line 47 edited."
}
``

  1. Turn 4 onward: The next API call sends ~30 tokens for that message instead of 4000. The full output is preserved in a sidecar log for debugging.

Multiply this by five file reads in a session — typical for any non-trivial task — and the difference between 80% context remaining and 5% context remaining is hook-managed eviction.

The hook author decides the policy. The examples above use age-based eviction, but the same mechanism supports LRU, type-based rules (always summarize Read outputs, never summarize Write confirmations), importance scoring, or any project-specific logic.

Additional Context

Proof of concept — between-session compression

We've already built and open-sourced this pattern for between-session memory (Digital-Process-Tools/claude-remember):

  • Haiku summarizes verbose session data into one-line memory entries
  • Near-Duplicate Compression merges repeated entries about the same work
  • Layered retention: recent data stays detailed, older data gets progressively compressed
  • Production result: 81% token reduction in memory files loaded at session start

The architecture works. The gap is applying it within a session — evicting tool outputs that have already served their purpose, not just between sessions.

Implementation notes

PostToolUse hooks already fire after every tool call — no new hook point is needed.

Changes required:

  1. Add optional context_directive field to the PostToolUse hook stdout JSON schema
  2. Claude Code processes directives between turns (after hook fires, before next API call)
  3. Apply the directive to the current tool call's output before it's included in the next request

Safety constraints:

  • Directives only affect tool outputs, never user messages, assistant turns, or system prompts
  • Each directive targets the current tool call's output only — no cross-message modification
  • Original output preserved in a sidecar log for debugging
  • Backward compatible: hooks that don't return context_directive are unaffected

---

This proposal comes from a team running Claude Code in production: 3 AI agents (dev partner, QA investigator, code quality sweeper), 146 custom skills, and a codebase with 111K commits. We've already built the between-session half of this system. Happy to share implementation details or collaborate on a prototype if that's useful.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗