session-end-hooks.md•10.5 kB
# SessionEnd Hook Troubleshooting Guide
## Overview
SessionEnd hooks automatically consolidate conversation outcomes when you exit Claude Code. However, many users are confused about **when these hooks actually fire** and why memories might not be created as expected.
This guide clarifies the session lifecycle and common troubleshooting scenarios.
---
## Critical Concept: Session Lifecycle
Claude Code distinguishes between **session pause/suspend** and **session termination**:
| User Action | Session State | Hook Triggered | Memory Created? |
|-------------|---------------|----------------|-----------------|
| **Ctrl+C (once)** | Interrupt input | None | ❌ No |
| **Ctrl+C (twice)** | Suspend session | None | ❌ No |
| **Resume session** | Continue existing | `SessionStart:resume` | ❌ No (loads existing) |
| **`/exit` command** | Terminate | `SessionEnd` | ✅ **Yes** |
| **Close terminal** | Terminate | `SessionEnd` | ✅ **Yes** |
| **Kill process** | May terminate | `SessionEnd` (if graceful) | ⚠️ Maybe |
### Key Takeaway
**Ctrl+C does NOT trigger SessionEnd hooks.** It suspends the session, which you can later resume. Only actual session termination (e.g., `/exit`) triggers SessionEnd.
---
## Common Issue: "My Session Didn't Create a Memory"
### Symptom
You exited Claude Code with Ctrl+C (twice), resumed later, and noticed no `session-consolidation` memory was created for your previous session.
### Root Cause
**Ctrl+C suspends the session rather than ending it.** When you resume with `SessionStart:resume`, the session continues from where you left off - no SessionEnd hook fires.
### Evidence
When you resume a session, you'll see:
```
SessionStart:resume hook success
```
This confirms you **resumed** an existing session, not started a new one.
### Solution
**Always use `/exit` to properly terminate sessions** if you want SessionEnd memories created:
```bash
# In Claude Code prompt:
/exit
```
This triggers graceful shutdown and SessionEnd hook execution.
---
## Common Issue: Connection Failures
### Symptom
During SessionStart, you see:
```
⚠️ Memory Connection → Failed to connect using any available protocol
💾 Storage → 💾 Unknown Storage (http://127.0.0.1:8000)
```
### Root Cause
**HTTP/HTTPS protocol mismatch** between hook configuration and memory service.
**Example**:
- **Server running**: `https://localhost:8000` (HTTPS)
- **Hook configured**: `http://127.0.0.1:8000` (HTTP)
### Diagnosis
Check your server protocol:
```bash
# Check server status
systemctl --user status mcp-memory-http.service
# Look for: "Uvicorn running on https://0.0.0.0:8000" or "http://..."
# Or test connection
curl -sk "https://localhost:8000/api/health"  # HTTPS
curl -s "http://127.0.0.1:8000/api/health"    # HTTP
```
Check your hook configuration:
```bash
grep endpoint ~/.claude/hooks/config.json
# Should show: "endpoint": "https://localhost:8000"
```
### Solution
Update `~/.claude/hooks/config.json` to match server protocol:
```json
{
  "memoryService": {
    "http": {
      "endpoint": "https://localhost:8000",  // Match your server
      "apiKey": "your-api-key-here"
    }
  }
}
```
**No restart required** - hooks reload config on next execution.
---
## SessionEnd Requirements
Even if SessionEnd fires correctly, memory creation requires:
### 1. Minimum Session Length
- Default: **100+ characters** total conversation
- Configurable: `sessionAnalysis.minSessionLength` in `config.json`
- Reason: Prevents noise from trivial sessions
### 2. Minimum Confidence Score
- Default: **> 0.1** (10% confidence)
- Based on conversation analysis quality
- Low confidence = session too generic to extract insights
### 3. Session Consolidation Enabled
```json
{
  "memoryService": {
    "enableSessionConsolidation": true  // Must be true
  }
}
```
### What Gets Extracted
SessionEnd analyzes your conversation to extract:
- **Topics**: Keywords like "implementation", "debugging", "architecture", "performance"
- **Decisions**: Phrases like "decided to", "will use", "chose to", "going with"
- **Insights**: Phrases like "learned that", "discovered", "realized"
- **Code Changes**: Phrases like "implemented", "created", "refactored"
- **Next Steps**: Phrases like "next we need", "TODO", "remaining"
If conversation lacks these patterns, confidence will be low and memory won't be created.
---
## Verification & Debugging
### 1. Check Recent Session Memories
```bash
# Search for recent session consolidation memories
curl -sk "https://localhost:8000/api/search/by-tag" \
  -H "Content-Type: application/json" \
  -d '{"tags": ["session-consolidation"], "limit": 5}' | \
  python -m json.tool | grep created_at_iso
```
Look for recent timestamps (today/yesterday).
### 2. Test SessionEnd Hook Manually
```bash
# Run hook with test conversation
node ~/.claude/hooks/core/session-end.js
```
Check output for:
- `[Memory Hook] Session ending - consolidating outcomes...`
- `[Memory Hook] Session analysis: X topics, Y decisions, confidence: Z%`
- `[Memory Hook] Session consolidation stored successfully`
### 3. Verify Connection
```bash
# Test server health
curl -sk "https://localhost:8000/api/health"
# Check config matches
grep endpoint ~/.claude/hooks/config.json
```
### 4. Check SessionEnd Configuration
```bash
# Verify SessionEnd hook is configured
grep -A 10 "SessionEnd" ~/.claude/settings.json
# Should show:
# "SessionEnd": [
#   {
#     "hooks": [
#       {
#         "type": "command",
#         "command": "node \"/home/user/.claude/hooks/core/session-end.js\"",
#         "timeout": 15
#       }
#     ]
#   }
# ]
```
---
## Quick Diagnosis Checklist
Use this checklist when SessionEnd memories aren't being created:
- [ ] **Did I use `/exit`** or just Ctrl+C?
  - **Fix**: Use `/exit` command for proper termination
- [ ] **Does `config.json` endpoint match server protocol?**
  - **Check**: HTTP vs HTTPS in both config and server
  - **Fix**: Update endpoint in `~/.claude/hooks/config.json`
- [ ] **Is the memory service running?**
  - **Check**: `curl https://localhost:8000/api/health`
  - **Fix**: Start server with `systemctl --user start mcp-memory-http.service`
- [ ] **Was conversation meaningful?**
  - **Check**: Total length > 100 characters
  - **Fix**: Have longer conversations with decisions/insights
- [ ] **Is session consolidation enabled?**
  - **Check**: `enableSessionConsolidation: true` in config
  - **Fix**: Update `~/.claude/hooks/config.json`
- [ ] **Is SessionEnd hook installed?**
  - **Check**: `grep SessionEnd ~/.claude/settings.json`
  - **Fix**: Run `cd claude-hooks && python install_hooks.py --all`
---
## Best Practices
### For Reliable Memory Consolidation
1. **Always use `/exit`** when you want session memories created
2. **Avoid Ctrl+C for final exit** - Use it only for interrupts/corrections
3. **Have meaningful conversations** - Include decisions, insights, plans
4. **Verify endpoint configuration** - HTTP vs HTTPS must match
5. **Check session memories periodically** - Confirm system is working
### For Debugging
1. **Check recent memories** - Look for session-consolidation tag
2. **Test hook manually** - Run `session-end.js` directly
3. **Verify connection** - Test health endpoint
4. **Read hook logs** - Look for error messages in terminal
5. **Consult session requirements** - Length, confidence, enabled settings
---
## Technical Details
### SessionEnd Hook Implementation
**File**: `~/.claude/hooks/core/session-end.js`
**Key Code Sections**:
- **Lines 298-365**: Main `onSessionEnd()` function
- **Line 316**: Minimum session length check (100 chars)
- **Line 329**: Minimum confidence check (0.1)
- **Line 305**: Session consolidation enabled check
- **Lines 213-293**: `storeSessionMemory()` - HTTP API call
### Configuration Structure
**File**: `~/.claude/hooks/config.json`
```json
{
  "memoryService": {
    "protocol": "auto",
    "preferredProtocol": "http",
    "http": {
      "endpoint": "https://localhost:8000",  // Must match server
      "apiKey": "your-api-key",
      "healthCheckTimeout": 3000
    },
    "enableSessionConsolidation": true
  },
  "sessionAnalysis": {
    "extractTopics": true,
    "extractDecisions": true,
    "extractInsights": true,
    "extractCodeChanges": true,
    "extractNextSteps": true,
    "minSessionLength": 100,
    "minConfidence": 0.1
  }
}
```
### Hook Settings
**File**: `~/.claude/settings.json`
```json
{
  "hooks": {
    "SessionEnd": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node \"/home/user/.claude/hooks/core/session-end.js\"",
            "timeout": 15  // 15 seconds (vs 10s for SessionStart)
          }
        ]
      }
    ]
  }
}
```
---
## Related Documentation
- **Hook Installation**: `claude-hooks/README.md`
- **Configuration Guide**: `claude-hooks/CONFIGURATION.md`
- **HTTP Server Management**: `docs/http-server-management.md`
- **General Troubleshooting**: `docs/troubleshooting/general.md`
- **SessionStart Windows Bug**: `claude-hooks/WINDOWS-SESSIONSTART-BUG.md`
---
## Common Questions
### Q: Why didn't my session create a memory even though I used `/exit`?
**A**: Check these conditions:
1. Conversation was too short (< 100 chars)
2. Conversation lacked decision/insight patterns (low confidence)
3. Connection to memory service failed (check endpoint)
4. Session consolidation disabled in config
### Q: Does Ctrl+C ever trigger SessionEnd?
**A**: No. Ctrl+C sends SIGINT which interrupts/suspends but doesn't terminate the session. Use `/exit` for proper termination.
### Q: Can I test if SessionEnd will work before exiting?
**A**: Yes:
```bash
node ~/.claude/hooks/core/session-end.js
```
This runs the hook with a test conversation and shows what would happen.
### Q: How do I see all my session consolidation memories?
**A**:
```bash
curl -sk "https://localhost:8000/api/search/by-tag" \
  -H "Content-Type: application/json" \
  -d '{"tags": ["session-consolidation"]}' | \
  python -m json.tool
```
### Q: What's the difference between SessionStart and SessionEnd hooks?
**A**:
- **SessionStart**: Loads and injects memory context at session start
- **SessionEnd**: Analyzes and stores session outcomes at session end
- Both can have connection issues (check endpoint configuration)
- SessionStart has timeout issues on Windows (Ctrl+C hang bug)
---
**Last Updated**: 2025-11-01
**Applies to**: v8.15.1+
**Author**: Community Documentation