---
title: "Local Session Persistence"
description: "How .claude/memory/ JSONL files act as optional local artifacts for OrchestKit skills, status, and compaction snapshots."
canonical: "https://orchestkit.yonyon.ai/docs/memory/local-memory"
---

# Local Session Persistence

How .claude/memory/ JSONL files act as optional local artifacts for OrchestKit skills, status, and compaction snapshots.

import { Callout } from 'fumadocs-ui/components/callout';

Local memory is Tier 2 in the public docs model: optional JSONL (JSON Lines) files under `.claude/memory/`. The directory is created when something writes to it. It is not an automatic safety net that captures every graph decision.

## The `.claude/memory/` Directory

```
.claude/memory/
  decisions.jsonl        # Optional log if something appends it (not auto-written)
  graph-queue.jsonl      # Leftover artifact if present (not auto-flushed to MCP)
  open-problems.jsonl    # Tracked open problems and blockers
  completed-flows.jsonl  # Completed workflow records
  tool-preferences.json  # Learned tool usage preferences
```

Each file serves a distinct purpose when present. Treat them as optional local artifacts for skills and compaction snapshots, not as an automatic write-ahead queue flushed into the graph by a hook.

## `decisions.jsonl`: The Decision Log

This is the primary local backup when something appends to it. Skill scripts and tooling may write JSONL here for viz and status. There is no `memory-writer` hook that appends automatically.

### Record Structure

```json
{
  "id": "decision-m1abc-x7y2z3",
  "type": "decision",
  "content": {
    "what": "Use cursor-based pagination for all list endpoints",
    "why": "Better performance for large datasets, stable under inserts/deletes",
    "alternatives": ["offset-based pagination"],
    "constraints": ["Must support 2M+ rows"],
    "tradeoffs": ["Slightly more complex client implementation"]
  },
  "entities": ["cursor-pagination", "PostgreSQL"],
  "relations": [],
  "identity": {
    "user_id": "user@example.com",
    "anonymous_id": "anon-abc123",
    "machine_id": "machine-xyz"
  },
  "metadata": {
    "session_id": "sess-123",
    "timestamp": "2026-02-06T10:30:00.000Z",
    "confidence": 0.85,
    "source": "user_prompt",
    "project": "orchestkit",
    "category": "pagination",
    "importance": "high",
    "is_generalizable": true,
    "sharing_scope": "global"
  }
}
```

### How It Gets Written

No registered OrchestKit hook auto-appends to `.claude/memory/decisions.jsonl`. Writes come from skills, scripts, or agent file tools when those paths are used. Separately, some stop and compaction hooks read `.claude/logs/decisions.jsonl` (a different path under `.claude/logs/`).

`lifecycle/pre-compact-saver` counts lines under `.claude/memory/*.jsonl` and snapshots recent `.claude/logs/decisions.jsonl` entries into session state before compaction. It does not append new decisions.

### How It Gets Read

There is no live `memory-context-loader` hook on main. Reading happens when you run `/ork:memory` (load, history, viz, status) or when an agent opens the files directly. Claude Code still injects project `MEMORY.md` at session start for the native tier.

Skill viz/history scripts may read the last lines of `.claude/memory/decisions.jsonl` when that file exists. Treat the sample below as the shape those tools format, not as automatic prompt injection:

```markdown
## Recent Project Decisions

- **[Decision]** Use cursor-based pagination for all list endpoints
  _(because: Better performance for large datasets)_
  `cursor-pagination`, `PostgreSQL`
- **[Preference]** Prefer TypeScript over JavaScript for new modules
- **[Decision]** JWT tokens for auth, not session cookies
  _(because: Stateless auth for microservices)_
  `JWT`, `session-cookies`

_For deeper graph traversal: use mcp__memory__search_nodes or mcp__memory__open_nodes_
```

## `open-problems.jsonl`: Problem Tracking

This file tracks unresolved problems and blockers encountered during sessions. Entries include the problem description, related entities, and status.

## `completed-flows.jsonl`: Workflow Records

Records of completed multi-step workflows, providing an audit trail of complex operations.

## `tool-preferences.json`: Learned Preferences

Stores learned tool usage preferences (e.g., preferred editor, testing framework) as a JSON object rather than JSONL.

## Optional Local Artifacts

Local JSONL under `.claude/memory/` is optional. Skills and scripts may create the directory and append records. Nothing on main auto-flushes `graph-queue.jsonl` into MCP memory.

If a writer uses atomic line appends, a crashed process can leave at most one partial line. Consumers that parse JSONL should skip malformed lines. That is application discipline, not a live context-loader hook.

## Health Monitoring

`lib/memory-health.ts` exposes `analyzeJsonlFile()` for per-file metrics (exists, line count, corrupt lines, size, mtime). The `checkMemoryHealth()` report used by status tooling currently probes only whether `.claude/memory/` exists and maps that to the graph-tier status. It does not probe MCP reachability, MEMORY.md, or queue depth.

Run `/ork:memory status` for the skill-side health view.

## Synchronization Between Local and Graph

There is no `memory-writer.ts` and no live `graph-queue-sync` stop hook. The primary write path is `/ork:remember` calling `mcp__memory__*` directly (validated by `memory-validator`). Local JSONL under `.claude/memory/` is an optional artifact surface, not an automatic write-ahead queue flushed by OrchestKit hooks.

| Stage | Target | Timing |
|---|---|---|
| **`/ork:remember` (skill)** | Knowledge graph via MCP | On explicit invoke |
| **Agent Edit/Write** | `MEMORY.md` or local memory files when chosen | On explicit edit |
| **`pre-compact-saver`** | Session state snapshot of local + logs | On compaction |
| **`session-summary`** | Graph capture *suggestion* via additionalContext | On stop (busy sessions) |

If local `decisions.jsonl` exists, skill scripts can still use it for viz and status. Replaying it into the graph is a manual or skill-driven operation, not an automatic hook flush.

## File Size Management

- `decisions.jsonl` can grow unbounded; readers that only need recent entries should read from the tail
- `graph-queue.jsonl`, if present, is a leftover artifact. No live hook on main clears or flushes it

## Next Steps

- [Graph Memory](/docs/memory/graph-memory): the primary tier for typed entities and relations
- [Architecture Overview](/docs/memory/overview): the full 3-tier system
