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

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 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 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 in the plugin's data directory
// 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) performs the inverse operation on subsequent sessions. It locates 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 as an array of regex strings under the session-end.patterns key:

{
  "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:

// 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 with a structure mirroring the named capture groups:

{
  "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:

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 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 serializes the conversation memory object to session-state.json using atomic writes for crash safety
  • Pattern extraction: Configured regex patterns from hooks/hooks.json are executed against the full transcript, with named capture groups structuring output to 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 containing the serialized memory object, and 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 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. 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 nor 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →