claude-code - 💡(How to fix) Fix Feature request: hook surface that fires before memory injection (so users can dedup duplicate rule content) [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#55988Fetched 2026-05-05 06:01:03
View on GitHub
Comments
0
Participants
1
Timeline
2
Reactions
0
Author
Participants
Timeline (top)
labeled ×2

Root Cause

The root cause is that the memory loader has no extension point. Hook taxonomy currently exposes SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop, PostToolUseFailure, and PreCompact — but memory injection happens inside the binary BEFORE any hook fires. SessionStart runs post-injection, so it cannot un-inject content already in the system prompt.

Fix Action

Fix / Workaround

Workaround in use today

Without a pre-injection hook, the only available mitigation is documenting the issue as an advisory rule and asking users to /clear periodically when the duplicate-injected memory block becomes a problem. This works but is manual.

RAW_BUFFERClick to expand / collapse

Problem

When a user organises their codebase with git worktrees + symlinks (a common pattern for parallel feature branches), Claude Code can inject the same rule file's content twice into a single session's memory block. The duplicate paths resolve to the same on-disk content via the symlink, but the loader treats them as distinct injection sources.

Symptoms observed:

  • A single rule file's body appears twice in the memory block
  • The duplication scales with the number of overlapping memory paths — e.g. ~165 KB of duplicate rule content per session in a worktree-heavy workflow
  • The duplicate content burns context budget on every session start and every memory refresh
  • More importantly: it creates a silent override risk. If the loader ever returns two different snapshots of the same rule (one from a stale cache, one fresh), the second injection silently overrides the first with no warning

The root cause is that the memory loader has no extension point. Hook taxonomy currently exposes SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop, PostToolUseFailure, and PreCompact — but memory injection happens inside the binary BEFORE any hook fires. SessionStart runs post-injection, so it cannot un-inject content already in the system prompt.

Proposed surface

Add a PreMemoryLoad (or similarly-named) hook surface that fires AFTER the loader has computed its planned injection list but BEFORE it commits the list to the system prompt. The hook receives the planned list as JSON on stdin, can return a transformed list, and the loader uses the transformed list as the final injection.

This is the same shape as the existing PreToolUse hook, just at a different point in the lifecycle.

Why content-hash dedup is the right strategy

The natural-seeming alternative — dedup by realpath (collapse symlinks to canonical path, then dedup) — is necessary but not sufficient. It correctly dedups the symlink-driven duplicate case, but it ALSO collapses intentionally-different worktree-local rule overrides (e.g. an experimental rule edit on a feature branch). That's a false dedup that hides the override.

Content-hash dedup (SHA-256 the body, dedup on hash) handles both cases correctly:

  • Same content → same hash → only one injection (intended dedup)
  • Different content → different hashes → both injected, with the conflict visible in the memory block (intended override)

A user-supplied PreMemoryLoad hook can implement either strategy, but the platform's own behaviour should not silently collapse overrides.

Workaround in use today

Without a pre-injection hook, the only available mitigation is documenting the issue as an advisory rule and asking users to /clear periodically when the duplicate-injected memory block becomes a problem. This works but is manual.

Impact

  • Token-budget impact: linear in session count × overlap × rule-surface size. For users with multi-worktree workflows and large rule surfaces this is a non-trivial recurring cost.
  • Correctness impact: silent override is the deeper concern. A pre-injection hook that dedups by content-hash makes the silent-override path impossible by construction.

Acceptance criteria

A user-supplied script registered as PreMemoryLoad can:

  1. Receive the planned memory injection list (paths + content) as JSON on stdin
  2. Return a transformed list (subset, reordered, or dedup'd) on stdout
  3. Have the loader use the transformed list as the final injection

The hook fires for every memory refresh, not only session start.


extent analysis

TL;DR

Implement a PreMemoryLoad hook to deduplicate memory injections by content-hash, ensuring that only unique rule content is loaded into the system prompt.

Guidance

  • To address the issue, consider implementing a PreMemoryLoad hook that receives the planned injection list as JSON, transforms it to remove duplicates based on content-hash, and returns the transformed list.
  • The hook should fire after the loader computes its planned injection list but before it commits the list to the system prompt, allowing for customization of the injection process.
  • When implementing the hook, use a content-hash dedup strategy (e.g., SHA-256) to correctly handle both symlink-driven duplicates and intentionally different worktree-local rule overrides.
  • Test the hook by registering a user-supplied script as PreMemoryLoad and verifying that it receives the planned injection list, returns a transformed list, and that the loader uses the transformed list as the final injection.

Example

// Example input JSON on stdin
{
  "injections": [
    {"path": "/path/to/rule1", "content": "rule1 content"},
    {"path": "/path/to/rule2", "content": "rule2 content"},
    {"path": "/symlink/to/rule1", "content": "rule1 content"}
  ]
}

// Example output JSON on stdout (deduplicated by content-hash)
{
  "injections": [
    {"path": "/path/to/rule1", "content": "rule1 content"},
    {"path": "/path/to/rule2", "content": "rule2 content"}
  ]
}

Notes

The proposed solution relies on the implementation of a PreMemoryLoad hook, which may require changes to the existing loader architecture. Additionally, the content-hash dedup strategy may have performance implications, depending on the size of the rule surfaces and the frequency of memory refreshes.

Recommendation

Apply a workaround

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix Feature request: hook surface that fires before memory injection (so users can dedup duplicate rule content) [1 participants]