Skip to content

Build 486e23d ·

← J. Jaime Aleman

The memory

Claude Code forgets everything when a session ends. So I gave it a database. This is what's inside it, and how it's wired together.

October 2025 → October 2026 · roughly 12 months of history · snapshot taken 3 minutes ago

1271 MB
On disk
481,161
Rows
23
Tables
37
MCP tools

How it works

Five steps, none of them exotic. The interesting part isn't any single piece — it's that they run continuously and unattended.

  1. 1

    Claude Code writes JSONL

    Every session is appended to a transcript on disk. This is stock behaviour — nothing custom yet.

  2. 2

    A parser ingests it

    jsonl_processor.py walks the transcripts, decodes project paths, extracts messages, tool calls, tokens and cost, and upserts them. Re-runnable and idempotent.

  3. 3

    Embeddings get generated

    Messages and memories are embedded as vector(1536) and stored in Postgres via pgvector, so recall is semantic rather than keyword-only.

  4. 4

    An MCP server exposes it

    37 tools over stdio — search, recall, stats, observations. Claude queries its own history as a first-class tool.

  5. 5

    The agent reads its own past

    Ask about work from months ago and it searches the database instead of guessing. That is the whole point.

The schema

23 tables, 100 indexes, 481,161 rows. The two big ones are big because of embeddings, not text.

Table Rows Size Purpose
memories
18,056 484 MB Long-term facts with vector embeddings. Semantic recall across sessions.
conversation_messages
384,084 412 MB Every message, embedded for hybrid semantic + trigram search.
resources
8,494 159 MB Saved URLs, docs, and reference material.
observations
48,529 154 MB Behavioural notes captured during sessions.
observation_digests
943 35 MB Periodically compacted observations, to keep recall cheap.
session_stats
6,161 5656 kB Per-session metrics: tokens, tool calls, cost, duration.
conversation_sessions
5,990 3776 kB Session index — project path, timing, message counts.
session_summaries
1,063 3320 kB Generated summaries used to warm-start later sessions.
generated_images
519 1488 kB Image generation log.
tool_usage
3,506 1040 kB Daily tool-call counts. Drives the tool distribution chart.
usage_hourly
2,078 392 kB Hourly rollup. Drives the 24-hour clock.
notifications
396 384 kB —
model_usage
643 336 kB Per-model, per-day tokens and cost.
project_profiles
274 256 kB Detected framework and dependencies per project.
pi_memories
55 248 kB Pi scout system memory store.
usage_daily
260 112 kB Daily rollup. Drives the heatmap.
time_entries
61 104 kB Manual time tracking.
clients
18 88 kB —
capture_amendments
4 80 kB —
session_attributions
10 48 kB —
bucket_list
14 32 kB Personal backlog.
reminder_timed_sent
3 24 kB —
pi_observations
0 16 kB Pi scout system observations.

How it filled up

Messages recorded per month, with the running total behind it. The early months are thin because they were backfilled from migrated transcripts — the archive only becomes continuous once the database was running live.

10 363 · 3d
11 5,252 · 12d
12 31,107 · 27d
01 36,953 · 28d
02 53,093 · 28d
03 57,534 · 30d
04 37,334 · 30d
05 17,503 · 30d
06 18,933 · 26d
07 16,627 · 26d
08 39,697 · 31d
09 41,089 · 28d
10 28,599 · 15d
messages that month cumulative 2025-10 → 2026-10 · 384,084 total

The database

Engine
PostgreSQL 16 (pgvector/pgvector:pg16, Docker)
Embeddings
vector(1536)
Extension
pg_trgm 1.6
Extension
vector 0.8.2
Indexes
100
Host
Docker, localhost only

The MCP server

Language
Python, stdio transport
Tools exposed
37
Lines of code
5,664

Modules

api.py conversations.py db_config.py embeddings.py jsonl_processor.py memory.py observations.py stats.py stats_db.py

What this isn't

It isn't a product. It's a local Docker container on one machine, bound to localhost. There's no hosted version and no install script.

It isn't magic recall. Semantic search over 384,084 messages returns plausible neighbours, not guaranteed answers. It's a research tool for the agent, and it still has to read what it finds.

It isn't free. Embedding 481,161 rows costs real money and real disk — 1271 MB of it, most of that vectors rather than prose.

It isn't the hard part. Storing history is easy. Deciding what's worth remembering, and getting the agent to actually consult it before answering, is where the work is.