# How the SessionEnd Hook Preserves State and Extracts Patterns in Everything-Claude-Code

> Learn how the SessionEnd hook preserves state by serializing conversation memory and extracts patterns using regex before saving to disk in Everything-Claude-Code.

- Repository: [WorldFlowAI/everything-claude-code](https://github.com/WorldFlowAI/everything-claude-code)
- Tags: internals
- Published: 2026-09-07

---

**The `SessionEnd` hook serializes the current conversation memory to JSON and runs configured regex patterns against the transcript before persisting both to disk.**

The `SessionEnd` hook is a critical component of the [WorldFlowAI/everything-claude-code](https://github.com/WorldFlowAI/everything-claude-code) plugin architecture. It executes automatically when a Claude chat session terminates, ensuring no conversational context is lost and enabling automated pattern extraction from the dialogue. This article examines the implementation details found in [`scripts/hooks/session-end.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/session-end.js) and its supporting files.

## State Preservation in the SessionEnd Hook

The primary responsibility of the `SessionEnd` hook is **state persistence**. When invoked, it receives the in-memory `memory` object from the Claude plugin runtime.

### The Serialization Process

The hook performs three discrete operations:

1. **Retrieve** the current conversation state from the Claude plugin API
2. **Serialize** the memory object to JSON format
3. **Write** the serialized data atomically to [`session-state.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/session-state.json) in the plugin's data directory

```javascript
// Conceptual flow based on session-end.js implementation
const memory = await claude.getMemory();           // Fetch live state
const serialized = JSON.stringify(memory, null, 2); // Pretty-printed JSON
await writeFileAtomic('session-state.json', serialized);

```

Atomic writes prevent state corruption if the process terminates unexpectedly during the write operation. The hook also records file size and timestamp to a debug log for troubleshooting persistence issues.

### State Restoration Counterpart

The `SessionStart` hook ([`scripts/hooks/session-start.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/session-start.js)) performs the inverse operation on subsequent sessions. It locates [`session-state.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/session-state.json), parses the JSON, and injects the restored memory back into the Claude runtime—allowing the assistant to resume with full conversational context intact.

## Pattern Extraction Architecture

Before persisting state, the `SessionEnd` hook executes its second core function: **pattern extraction** from the conversation transcript.

### Configuration-Driven Regex Matching

Patterns are defined in [`hooks/hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/hooks.json) as an array of regex strings under the `session-end.patterns` key:

```json
{
  "session-end": {
    "patterns": [
      "(?<task>TODO):\\s*(?<detail>.+)",
      "(?<url>https?://[\\w./-]+)",
      "(?<decision>DECISION):\\s*(?<rationale>.+)"
    ]
  }
}

```

Each pattern may include **named capture groups** (`?<name>`) that the hook uses to structure extracted data.

### Extraction andStorage Pipeline

The hook processes patterns through the following pipeline:

```javascript
// Simplified representation of the extraction logic
const transcript = memory.getTranscript();  // Full conversation text
const config = loadConfig('hooks/hooks.json');
const results = {};

for (const pattern of config['session-end'].patterns) {
  const regex = new RegExp(pattern, 'gmi');
  const matches = [...transcript.matchAll(regex)];
  
  matches.forEach(match => {
    const groups = match.groups || { default: match[0] };
    Object.entries(groups).forEach(([key, value]) => {
      results[key] = results[key] || [];
      results[key].push(value);
    });
  });
}

await writeFileAtomic('extracted-patterns.json', JSON.stringify(results, null, 2));

```

Extracted patterns are written to [`extracted-patterns.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/extracted-patterns.json) with a structure mirroring the named capture groups:

```json
{
  "task": [
    "Refactor the session handling logic",
    "Add unit tests for pattern extraction"
  ],
  "url": [
    "https://github.com/WorldFlowAI/everything-claude-code"
  ],
  "decision": [
    "Use atomic writes for state persistence"
  ]
}

```

## Hook Execution Flow

The complete `SessionEnd` hook lifecycle can be visualized as:

```

Claude session termination
         ↓
┌─────────────────┐
│  SessionEnd Hook  │
│  (session-end.js) │
└─────────────────┘
         ↓
    ┌────────────┐
    │ Get memory │◄────────────────────┐
    │   object   │                      │
    └────────────┘                      │
         ↓                              │
    ┌────────────┐                      │
    │  Extract   │                      │
    │  patterns  │                      │
    │ from config│                      │
    └────────────┘                      │
         ↓                              │
    ┌────────────┐     ┌─────────────┐  │
    │Write       │────►│extracted-   │  │
    │patterns    │     │patterns.json│  │
    └────────────┘     └─────────────┘  │
                                        │
    ┌────────────┐                      │
    │Serialize   │                      │
    │memory      │                      │
    └────────────┘                      │
         ↓                              │
    ┌────────────┐     ┌─────────────┐  │
    │Write state │────►│session-state│──┘
    │atomically  │     │.json        │
    └────────────┘     └─────────────┘
         ↓
    Log summary (patterns found, bytes written)
         ↓
   Claude shutdown continues

```

## Manual Invocation for Debugging

Developers can trigger the `SessionEnd` hook manually to verify state persistence and pattern extraction without closing their Claude session:

```bash
node "${CLAUDE_PLUGIN_ROOT}/scripts/hooks/session-end.js" --force

```

The `--force` flag bypasses the normal session-termination check, allowing inspection of output files while the session remains active.

## Test Coverage

The test suite in [`tests/hooks/hooks.test.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/tests/hooks/hooks.test.js) validates both state preservation and pattern extraction behaviors. Key test scenarios include:

- **State round-trip**: Verifying that saved state loads identically through `SessionStart`
- **Pattern matching accuracy**: Confirming regexes with named groups populate correct output structure
- **Atomic write integrity**: Simulating crashes mid-write and confirming no corruption occurs
- **Empty transcript handling**: Ensuring graceful behavior when no patterns match

## Summary

- **State preservation**: The `SessionEnd` hook in [`scripts/hooks/session-end.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/session-end.js) serializes the conversation `memory` object to [`session-state.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/session-state.json) using atomic writes for crash safety
- **Pattern extraction**: Configured regex patterns from [`hooks/hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/hooks.json) are executed against the full transcript, with named capture groups structuring output to [`extracted-patterns.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/extracted-patterns.json)
- **Complementary hooks**: `SessionStart` restores persisted state, creating seamless session-to-session continuity
- **Observable behavior**: Debug logging reports pattern match counts and serialized state size for operational visibility

## Frequently Asked Questions

### Where does the SessionEnd hook store its output files?

The hook writes to two JSON files in the plugin's data directory: [`session-state.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/session-state.json) containing the serialized memory object, and [`extracted-patterns.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/extracted-patterns.json) containing regex match results. These paths are resolved relative to the `CLAUDE_PLUGIN_ROOT` environment variable.

### How do I add custom patterns for the SessionEnd hook to extract?

Edit [`hooks/hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/hooks.json) and add regex strings to the `session-end.patterns` array. Use named capture groups (`?<name>`) to control the structure of extracted data in [`extracted-patterns.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/extracted-patterns.json). The patterns are evaluated with the `gmi` flags (global, multiline, case-insensitive).

### What happens if the SessionEnd hook crashes during execution?

Atomic write operations ensure that neither [`session-state.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/session-state.json) nor [`extracted-patterns.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/extracted-patterns.json) can be left in a partially-written corrupt state. If the hook fails before completion, the previous valid state files remain untouched, and the next session starts from that last-known-good checkpoint.

### Can other hooks consume the patterns extracted by SessionEnd?

Yes. The [`extracted-patterns.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/extracted-patterns.json) output serves as input for downstream hooks such as `evaluate-session`. These hooks can analyze extracted patterns to generate suggestions, trigger automation, or feed analytics pipelines without re-parsing the full conversation transcript.