# How Session Continuity Works Across Conversation Compaction in Claude Code with context-mode

> Discover how Claude Code's context-mode ensures session continuity through conversation compaction. Learn how tool executions are stored and snapshots re-injected for seamless conversations.

- Repository: [Mert Köseoğlu/context-mode](https://github.com/mksglu/context-mode)
- Tags: deep-dive
- Published: 2026-04-24

---

**Context-mode preserves complete session history across automatic conversation compactions by recording every tool execution to a SQLite database, generating a compact XML resume snapshot before truncation, and re-injecting that snapshot as a system directive after the compact.**

The **context-mode** repository (`mksglu/context-mode`) solves a critical limitation in Claude Code: the loss of historical context when conversations automatically compact to stay within token limits. This open-source tool ensures **session continuity across conversation compaction** by intercepting tool calls at three specific lifecycle phases and resurrecting previous context through a rigorous persistence pipeline.

## The Three-Pillar Continuity Architecture

Context-mode maintains state through three tightly-coupled lifecycle hooks that execute around compaction events. Together, they create an immutable audit trail that survives unlimited conversation truncations.

### PostToolUse Hook: Capturing Every Action

Immediately after each tool execution, the **PostToolUse** hook (implemented in `hooks/posttooluse.mjs`) extracts structured events and writes them to a per-project SQLite database named `session.db`.

```typescript
// hooks/posttooluse.mjs
const { extractEvents } = await loadExtract();
const db = new SessionDB({ dbPath });
const sessionId = getSessionId(input);

// ensure meta row exists
db.ensureSession(sessionId, process.env.CLAUDE_PROJECT_DIR || process.cwd());

// turn a tool call into one or more SessionEvent objects
const events = extractEvents({ 
  tool_name, 
  tool_input, 
  tool_response, 
  tool_output 
});

// write each event atomically (deduplication + FIFO eviction)
for (const ev of events) {
  db.insertEvent(sessionId, ev, "PostToolUse");
}

```

The `extractEvents` function (located in [`src/session/extract.ts`](https://github.com/mksglu/context-mode/blob/main/src/session/extract.ts)) classifies tool calls into **13 distinct categories** (file operations, git commands, environment changes, etc.) and normalizes them into `SessionEvent` objects. The `SessionDB.insertEvent` method (in [`src/session/db.ts`](https://github.com/mksglu/context-mode/blob/main/src/session/db.ts)) provides atomic storage with built-in deduplication and **FIFO eviction** once the per-session limit of `MAX_EVENTS_PER_SESSION = 1000` events is reached.

### PreCompact Hook: Building the Resume Snapshot

Right before Claude truncates the conversation to manage token limits, the **PreCompact** hook (`hooks/precompact.mjs`) generates a compact-size XML resume snapshot that encodes the session's essential context without the bloat.

```typescript
// precompact.mjs
const events = db.getEvents(sessionId);
if (events.length) {
  const stats = db.getSessionStats(sessionId);
  const snapshot = buildResumeSnapshot(events, {
    compactCount: (stats?.compact_count ?? 0) + 1,
  });
  db.upsertResume(sessionId, snapshot, events.length);
  db.incrementCompactCount(sessionId);
}

```

The `buildResumeSnapshot` function (in [`src/session/snapshot.ts`](https://github.com/mksglu/context-mode/blob/main/src/session/snapshot.ts)) groups events by category, generates concise XML summaries for each group, and appends a **search tool call** (`ctx_search`) that can retrieve full details on demand. Despite encoding a complete table of contents for the session, the snapshot remains **under 2 KB**, well within Claude's token budget for system context.

### SessionStart Hook: Restoring Lost Context

When Claude restarts after a compaction event, the **SessionStart** hook (`hooks/sessionstart.mjs`) detects the `source === "compact"` condition and strategically re-injects the stored snapshot as a system-level directive.

```typescript
// sessionstart.mjs – compact branch
if (source === "compact") {
  const resume = db.getResume(sessionId);
  if (resume && !resume.consumed) db.markResumeConsumed(sessionId);
  
  const events = getSessionEvents(db, sessionId);
  if (events.length) {
    const eventMeta = writeSessionEventsFile(
      events, 
      getSessionEventsPath()
    );
    additionalContext += buildSessionDirective(
      "compact", 
      eventMeta, 
      toolNamer
    );
  }
}

```

The `getResume` function retrieves the XML snapshot, while `markResumeConsumed` prevents duplicate injection. The `buildSessionDirective` function wraps the snapshot in a `<session_resume …>` XML block that Claude treats as immutable system context, effectively resurrecting the knowledge that would otherwise have been lost to truncation.

## Full-History Resume with --continue

When users restart a session using the `--continue` flag, context-mode shifts from "snapshot mode" to "full replay mode." The SessionStart hook detects `source === "resume"` and executes a complete context restoration:

1. **Clears the cleanup flag** to prevent old session data from being purged
2. **Retrieves all events** that survived previous compactions via `getLatestSessionEvents`
3. **Writes raw events** to [`session_events.json`](https://github.com/mksglu/context-mode/blob/main/session_events.json) for auto-indexing
4. **Injects both** the compact snapshot and the full event log via `buildSessionDirective("resume", …)`

This dual-injection strategy allows the LLM to reconstruct the exact pre-compact state by combining the categorized snapshot with granular event details.

## Analytics and Continuity Metrics

The system tracks continuity health through [`src/session/analytics.ts`](https://github.com/mksglu/context-mode/blob/main/src/session/analytics.ts), which aggregates metrics including `total_events`, `compact_count`, and per-category breakdowns. These statistics power the Insight UI and benchmark reports, while the snapshot header includes `compact_count` to generate human-readable session footers:

```text
Session continuity: 25 events preserved across 2 compactions

```

## Summary

- **Event Capture**: Every tool call is immediately persisted to `session.db` via the PostToolUse hook, with automatic deduplication and FIFO eviction at 1000 events per session.
- **Snapshot Generation**: The PreCompact hook condenses full history into a <2KB XML resume snapshot containing categorized summaries and searchable references to full details.
- **Context Restoration**: The SessionStart hook automatically re-injects the resume snapshot after compaction, while `--continue` mode provides full event replay for complete state reconstruction.
- **Storage Backend**: All persistence uses atomic SQLite operations in [`src/session/db.ts`](https://github.com/mksglu/context-mode/blob/main/src/session/db.ts), ensuring durability even during abrupt session termination.

## Frequently Asked Questions

### How large are the resume snapshots?

Resume snapshots are intentionally compressed to **under 2 KB** regardless of session length. The `buildResumeSnapshot` function in [`src/session/snapshot.ts`](https://github.com/mksglu/context-mode/blob/main/src/session/snapshot.ts) achieves this by categorizing events and referencing full details through a `ctx_search` tool call rather than inlining verbose content, keeping the payload well within Claude's system context budget.

### What happens if a session compacts multiple times?

The system maintains continuity across unlimited compactions through the `compact_count` counter stored in `session.db`. Each PreCompact execution increments this counter and generates a new resume snapshot that incorporates all previous events. The FIFO eviction policy in `SessionDB.insertEvent` ensures the most recent 1000 events are always available for snapshot generation.

### Can I inspect the session database manually?

Yes. The `session.db` file is a standard SQLite database located in your project directory. You can query it directly using the SQLite CLI or any database browser to inspect the `events` table, `session_resume` table, and metadata fields including `event_count`, `compact_count`, and `last_event_at`.

### Does context-mode work with any Claude Code project?

Context-mode automatically activates for any project where the hooks are installed. It determines the project root via `process.env.CLAUDE_PROJECT_DIR` or `process.cwd()`, creating isolated `session.db` files per project. This ensures session continuity is scoped correctly when working across multiple codebases.