claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

[BUG] No postCompact hook

Open outdooricon opened this issue 6 months ago β€’ 8 comments

Environment

  • Platform (select one):
    • [x] Anthropic API
    • [ ] AWS Bedrock
    • [ ] Google Vertex AI
    • [ ] Other:
  • Claude CLI version: 1.0.51
  • Operating System: macOS 15.5
  • Terminal: ghostty

Bug Description

We need a postCompact hook. With preCompact i'm able to save relevant data to graphiti, but I need to tell claude to reference it post compact. I also need to tell claude to read it's claude md file post compact as well

Steps to Reproduce

  1. run /compact

Expected Behavior

Makes a call to postCompact hook file

Actual Behavior

It doesn't

Additional Context

outdooricon avatar Jul 15 '25 11:07 outdooricon

Related to https://github.com/anthropics/claude-code/issues/3447.

almirsarajcic avatar Jul 29 '25 12:07 almirsarajcic

I would like this so that I can inject session ID after compact.

mimkorn avatar Aug 29 '25 11:08 mimkorn

I'd like this to get Claude to re-read certain essential rules.

Claude Code tends to start violating important instructions from CLAUDE.md (or instructions in files linked from CLAUDE.md) after a compact, so I'd like to get Claude to re-read a list of essential rules immediately after a compact completes, to ensure said rules survive in Claude's memory.

andrew-s-faulkner avatar Sep 10 '25 19:09 andrew-s-faulkner

βœ… Workaround Solution + Strong Support for Native PostCompact Hook

I've successfully implemented a workaround using the SessionStart hook, but I'm adding my strong support for a native PostCompact hook implementation.

πŸ› οΈ Current Workaround (SessionStart Hook)

What I implemented:

  • Hook: SessionStart (executes when resuming a session after auto-compact)
  • Script: Displays mandatory instructions in stdout (which gets injected into context)
  • Result: Claude sees instructions to read critical files automatically

Code:

# ~/.claude/hooks/session-start-memory-restore.sh
echo "πŸ“š INSTRUCCIΓ“N MANDATORIA:"
echo "Debes leer estos archivos INMEDIATAMENTE:"
echo "1. cat ~/.claude/POST-COMPACT-README.md"
echo "2. cat /home/murias/Dev/[project]/CLAUDE.md"
echo "3. cat /home/murias/Dev/[project]/.claude/CLAUDE.md"

Settings.json:

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/session-start-memory-restore.sh"
          }
        ]
      }
    ]
  }
}

Does it work? Yes, but...

❌ Why This Workaround is Not Ideal

Issue Impact
SessionStart fires on every session start Unnecessary overhead when no compact occurred
No way to detect if compact actually happened Can't conditionally restore context
Stdout injection happens for normal starts Clutters context unnecessarily
No environment variables about compact Can't adapt script behavior
Not semantically correct Using wrong hook for the job

βœ… Why Native PostCompact Hook is Essential

The Problem (Real-World Impact):

  • After auto-compact, Claude violates critical project rules (e.g., uses sed when Readβ†’Edit is required)
  • Users must manually re-explain requirements repeatedly
  • Professional/enterprise use is severely hampered without context persistence
  • Productivity drops dramatically after each compact

The Solution (Native PostCompact):

  1. Precision: Only fires after actual compaction
  2. Context clarity: Scripts know compact occurred
  3. Environment awareness: Can access compact type (manual/auto), timestamp, project path
  4. Clean design: Right tool for the job
  5. Professional-grade: Enables enterprise adoption

Use Cases Beyond My Implementation:

  1. Auto-read critical configuration files (CLAUDE.md)
  2. Restore session-specific context (current task)
  3. Re-inject custom instructions
  4. Load external memory systems (Graphiti, vector DBs)
  5. Session tracking (inject session IDs for continuity)

πŸ“Š Community Demand

This issue (#3537) + duplicate #3612 show:

  • 19+ community reactions (7 upvotes here + 12 on duplicate)
  • Multiple professional users blocked by this limitation
  • Critical for enterprise adoption where rule enforcement is mandatory

🎯 Implementation Proposal

Minimal viable implementation:

{
  "hooks": {
    "PostCompact": [
      {
        "matcher": "auto",  // or "manual" for /compact
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/post-compact.sh"
          }
        ]
      }
    ]
  }
}

Required behavior:

  • Execute after compact completes
  • Before Claude continues with next task
  • Stdout injected into context (like SessionStart)
  • Environment variables: CLAUDE_COMPACT_TYPE, CLAUDE_COMPACT_TIMESTAMP, CLAUDE_PROJECT_PATH

πŸš€ Impact on Claude Code Adoption

With current workaround: "Claude Code works but loses context frequently" With native PostCompact: "Claude Code maintains context seamlessly"

This single feature would:

  • βœ… Enable professional/enterprise use
  • βœ… Dramatically improve user experience
  • βœ… Reduce user frustration
  • βœ… Increase Claude Code effectiveness by orders of magnitude
  • βœ… Differentiate Claude Code from competitors

πŸ“’ Strong +1 from Professional User

As someone who's implemented the workaround and uses Claude Code professionally, I strongly support native PostCompact hook implementation.

Priority: HIGH (affects all users who hit auto-compact)

Implementation effort: LOW (PreCompact already exists, same pattern)

User impact: MASSIVE (transforms workflow quality)


My setup:

  • Projects: Multiple enterprise Next.js/React applications
  • Project rules: 50+ critical rules that must persist (no sed/awk, specific deployment workflows, etc.)
  • Workaround: Functional but not ideal
  • Willingness to help: Happy to test beta implementations

Thank you Anthropic team for considering this feature! πŸ™

murias002 avatar Nov 14 '25 02:11 murias002

Use case: External memory system for context recovery

I've built a "context map" system - a machine-optimized markdown file (.claude/context-map.md) that serves as Claude's external memory. It contains compressed project state: recent git commits, active tasks, solved problems, code paths, and anti-patterns.

Current setup:

  • SessionStart hook: generates context-map AND cats it into Claude's context
  • PreCompact hook: regenerates context-map (captures current state before it's lost)

The gap:

PreCompact fires before compaction, so if I cat the file during PreCompact, that output gets compacted away - defeating the purpose. The regenerated file exists on disk but Claude can't see it after waking up from compaction.

SessionStart works great for fresh sessions, but after mid-session compaction, Claude loses context and has no automatic way to reload the context-map.

Workaround:

Currently relying on the conversation summary to mention "read context-map.md" - fragile and depends on summary quality.

What PostCompact would enable:

{
  "hooks": {
    "PostCompact": [{
      "matcher": "*",
      "hooks": [{
        "type": "command",
        "command": "cat .claude/context-map.md"
      }]
    }]
  }
}

After compaction completes, Claude would automatically receive the freshly-generated context-map contents, restoring project awareness without manual intervention.

Broader point: CLAUDE.md re-reads

This same mechanism should probably be built into Claude Code itself - automatically re-reading CLAUDE.md after compaction. Reddit is full of users frustrated that Claude "forgets" instructions from CLAUDE.md after compaction. A PostCompact hook would let power users solve this themselves, but automatic CLAUDE.md re-injection after compaction seems like it should be default behavior.

This seems like a straightforward addition given PreCompact already exists - just fire the same hook mechanism after compaction instead of before.

bhpascal avatar Nov 30 '25 20:11 bhpascal

Supporting this feature request with a comprehensive workaround example

I've built a more elaborate system to solve this exact problem. Here's what works (and what doesn't):

My Current Setup

1. SessionStart Hook (similar to yours):

{
  "hooks": {
    "SessionStart": [{
      "matcher": "*",
      "hooks": [{
        "type": "command",
        "command": "bash ~/.claude/scripts/session-start-memory-restore.sh"
      }]
    }]
  }
}

2. The hook script detects the current project and injects:

  • ~/.claude/POST-COMPACT-README.md (global rules - 400+ lines)
  • .claude/POST-COMPACT.md (project-specific rules)
  • .claude/CLAUDE.md (project config)
  • Last 3 git commits for context recovery

3. Skills auto-loading (~/.claude/skills/*/Skill.md):

  • 17 skills that define behaviors Claude should "always remember"
  • Example: seo-specialist, no-sed-awk, curl-verification

What Works

βœ… Fresh sessions: Claude starts with full context (rules, skills, project state) βœ… Git as memory: Commits serve as recoverable context (git log -5) βœ… Structured POST-COMPACT files: Checklists, rules, and "read this first" instructions

What Doesn't Work (The Gap)

❌ Mid-session /compact: Everything gets lost. The SessionStart hook doesn't fire. ❌ Skills disappear: Even registered skills vanish after compact ❌ Relying on summary: As you said, fragile and depends on summary quality

The Real Problem

User: /compact
Claude: [compacts conversation]
Claude: [wakes up with summary only]
Claude: [has NO access to POST-COMPACT files, skills, or rules]

The only way Claude sees the context is if the summary happens to mention "read POST-COMPACT.md" - which is unreliable.

Why PostCompact Would Solve This

With a PostCompact hook, we could:

{
  "hooks": {
    "PostCompact": [{
      "matcher": "*", 
      "hooks": [{
        "type": "command",
        "command": "cat ~/.claude/POST-COMPACT-README.md .claude/POST-COMPACT.md"
      }]
    }]
  }
}

This would guarantee context restoration after every compact, not just on fresh sessions.

Agreeing with the Broader Point

"automatic CLAUDE.md re-injection after compaction seems like it should be default behavior"

100% agree. The number of times I've had to tell Claude "read CLAUDE.md again" after a compact is frustrating. This should be automatic.

Suggested Implementation

  1. PostCompact hook (for power users to customize)
  2. Automatic CLAUDE.md re-read (as default behavior for everyone)
  3. Optional: Skills re-injection (for users with ~/.claude/skills/)

This would make Claude Code significantly more reliable for long sessions and complex projects.


TL;DR: I have a working workaround with SessionStart + POST-COMPACT files + skills, but it all breaks on mid-session /compact. PostCompact hook would elegantly solve this for everyone.

murias002 avatar Dec 01 '25 21:12 murias002

Update: Improved PreCompact Hook Strategy

Following up on my previous comment, I've implemented additional improvements that make the workaround more robust:

New Multi-Layer Recovery System

Layer 1: Enhanced PreCompact Hook

The PreCompact hook now does two things:

  1. Generates a context checkpoint file (.claude/last-context.md) with recent git activity
  2. Outputs repetitive critical instructions designed to survive summarization:
# Key strategy: Repetition and explicit "summary instruction"
echo "MANDATORY POST-COMPACT ACTIONS:"
echo "1. Read: ~/.claude/POST-COMPACT-README.md"
echo "DO NOT PROCEED until these files are read."
echo "DO NOT PROCEED until these files are read."
echo "DO NOT PROCEED until these files are read."
echo ""
echo "Summary instruction: This compact summary MUST include the instruction to read POST-COMPACT-README.md"

The theory: By repeating the instruction multiple times AND explicitly telling the summarizer to include it, we increase the probability it survives in the compact summary.

Layer 2: Prominent CLAUDE.md Recovery Section

Added a highly visible section at the TOP of project CLAUDE.md:

## πŸ”΄πŸ”΄πŸ”΄ POST-COMPACT RECOVERY - READ FIRST πŸ”΄πŸ”΄πŸ”΄

**If you just compacted or your context seems limited, IMMEDIATELY execute:**

Read: ~/.claude/POST-COMPACT-README.md
Read: .claude/POST-COMPACT.md

**DO NOT proceed with any task until these files are read.**

Since CLAUDE.md is automatically re-read, Claude sees this instruction first.

Layer 3: SessionStart Hook (unchanged)

Still works for fresh sessions and resumed sessions.

Results

Scenario Before After
Fresh session βœ… Full context βœ… Full context
Resume session βœ… Full context βœ… Full context
Mid-session /compact ❌ Lost context ⚠️ Better chance of recovery

Still Not Perfect

The mid-session compact is still problematic because:

  • PreCompact output might still get summarized away
  • No guarantee the summary includes our instructions
  • No way to detect if compact actually happened

Conclusion

This multi-layer approach is the most robust workaround possible with current hooks, but it's still a workaround. A native PostCompact hook would eliminate all this complexity and provide guaranteed context restoration.

The workaround code is available at: my claude-config repo (if others want to adapt it)


TL;DR: Improved PreCompact hook + prominent CLAUDE.md section = better odds of surviving mid-session compact, but still not guaranteed. Native PostCompact hook remains the proper solution.

murias002 avatar Dec 01 '25 21:12 murias002