Skip to content

kcp-memory: Give Claude Code a Memory

Every Claude Code session starts the same way. The context window is empty. The agent has no recollection of what it did yesterday, which files it touched last week, or how it solved a similar problem three sessions ago. Each session is day one.

That is not a limitation of the model. It is a missing infrastructure layer.

Today we are releasing kcp-memory v0.1.0: a standalone Java daemon that indexes ~/.claude/projects/**/*.jsonl session transcripts into a local SQLite database with FTS5 full-text search. Ask it "what was I working on last week?" and it answers in milliseconds.

Update (same day — v0.2.0): kcp-memory now ships with tool-level granularity. kcp-commands v0.9.0 writes every Bash tool call to ~/.kcp/events.jsonl; kcp-memory ingests that stream and makes individual commands searchable via kcp-memory events search. Session-level and tool-level memory in one daemon, one database, zero additional dependencies.

Update (same day — v0.3.0): kcp-memory now ships as an MCP server. Run java -jar ~/.kcp/kcp-memory-daemon.jar mcp — registered in mcpServers in ~/.claude/settings.json — and Claude Code can call kcp_memory_search, kcp_memory_events_search, kcp_memory_list, and kcp_memory_stats inline during a session, without leaving the context window.

Update (same day — v0.4.0): Two new MCP tools close the remaining gaps. kcp_memory_session_detail(session_id) returns full session content — user messages, files touched, tools used — completing the search → read flow. kcp_memory_project_context() reads PWD from the process environment and returns the last 5 sessions and 20 tool events for the current project, with no query needed. Call it at the start of every session and Claude immediately knows what it was doing here last time.

kcp-memory: three-layer memory model for Claude Code — working memory (context window), episodic memory (kcp-memory), semantic memory (Synthesis)

Give Claude Code a memory — kcp-memory search terminal demo


The missing layer

Context windows have grown from 4K to 200K tokens in three years. Retrieval-augmented generation gives agents access to document stores. Model Context Protocol wires agents to external tools. The ecosystem has invested heavily in what an agent can do in one session.

What it has not built is a record of what happened across sessions.

Every Claude Code session starts with Day One amnesia — no memory of yesterday, last week, or three sessions ago

Human experts carry episodic memory: they remember which approaches failed, which components are tricky, which patterns recur across projects. An agent with no episodic layer has to rediscover all of it, every time.

The three layers of a well-equipped agent look like this:

Layer What it holds Provided by
Working Current context — active files, recent tool results Claude Code context window
Episodic What happened in past sessions kcp-memory
Semantic What this codebase means — structure, relationships Synthesis

kcp-memory fills the middle layer. It does not compete with Synthesis — it is complementary. Synthesis answers "what do I know about this codebase?" kcp-memory answers "what did I do here before?"

The three layers of a well-equipped agent: Working Memory (context window), Episodic Memory (kcp-memory), Semantic Memory (Synthesis)


What it indexes

Claude Code writes every session to ~/.claude/projects/<slug>/<session-id>.jsonl. Each line is a JSON object representing one turn: human message, assistant response, or tool result.

Enter kcp-memory: ~/.claude/projects/**/*.jsonl → Java daemon → ~/.kcp/memory.db with FTS5 full-text search

kcp-memory walks that directory, parses each file, and extracts:

  • Session metadata: project directory, git branch, model, start/end timestamps
  • Turn count and tool call count
  • Tool names used (distinct, ordered by first use)
  • File paths touched (from Read, Edit, Write tool inputs)
  • User messages: the first message (for quick scanning) and all human turns concatenated (for full-text search)

Everything lands in a single ~/.kcp/memory.db SQLite file with an FTS5 virtual table over the session content. A 2,000-session history occupies roughly 50MB.

Extracting structure from session transcripts — JSONL structure with 5 extracted fields: metadata, turns, tools, file paths, user messages


The CLI

The CLI experience — scan, search, list, stats subcommands with example output

# Index all sessions (incremental — only new/changed files)
kcp-memory scan

# Search across everything you've ever done
kcp-memory search "OAuth implementation"
kcp-memory search "database migration flyway"
kcp-memory search "how to deploy kubernetes"

# List recent sessions
kcp-memory list
kcp-memory list --project /src/myapp

# Aggregate statistics
kcp-memory stats

# Search individual tool-call events (v0.2.0 — requires kcp-commands v0.9.0)
kcp-memory events search "kubectl apply"
kcp-memory events search "flyway migrate"
kcp-memory events search "docker build"

A stats output from a real session history:

[kcp-memory] statistics
─────────────────────────────────
  Sessions:    847
  Turns:       12,431
  Tool calls:  38,209
  Oldest:      2026-01-15T09:12:00Z
  Newest:      2026-03-03T14:55:00Z

  Top tools:
    Read                      14,821
    Bash                       9,442
    Edit                       7,103
    Glob                       3,218
    Grep                       2,901
    Write                        644

A search result:

  2026-02-18  /src/cantara/kcp-commands
  e3ba3fd     turns=24  tools=67
  "add Phase B output filtering to the ansible manifest"

  2026-02-11  /src/exoreaction/lib-pcb
  a91c2f0     turns=18  tools=41
  "implement the Gerber export for copper layers"

Actionable insights from your coding history — stats showing 847 sessions, 38,209 tool calls, top tools breakdown


The daemon

kcp-memory runs as a local HTTP daemon on port 7735:

Endpoint Method Description
/health GET Liveness check + session count
/search?q=...&limit=20 GET FTS5 search over session transcripts
/sessions?project=...&limit=50 GET List recent sessions
/stats GET Aggregate statistics
/scan?force=true POST Trigger an incremental scan
/events/search?q=...&limit=20 GET FTS5 search over tool-call events (v0.2.0)

Built on com.sun.net.httpserver with virtual threads — the same architecture as kcp-commands. Cold start is under 2 seconds. Queries return in under 5ms on a 1,000-session database.

The daemon runs an initial scan on startup and re-scans every 30 minutes in the background. Existing sessions that have not changed since the last scan are skipped.

A lightweight background daemon built on virtual threads — 6 API endpoints on port 7735, cold start under 2 seconds


PostToolUse hook

For near-real-time indexing, wire the hook into ~/.claude/settings.json:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": ".*",
        "hooks": [{"type": "command", "command": "~/.kcp/memory-hook.sh"}]
      }
    ]
  }
}

The hook fires after every tool call and triggers an async scan. It checks whether the daemon is running with a 500ms timeout and fires a background POST to /scan if it is. Total overhead: under 1ms on the Claude Code side. If the daemon is not running, the hook exits silently. It never blocks.

Near-real-time indexing via the PostToolUse hook — hook config and flow: tool call → memory-hook.sh → async POST /scan → FTS5 index updated


MCP server (v0.3.0)

kcp-memory exposes its search capabilities as MCP tools for Claude Code. Add one entry to ~/.claude/settings.json and Claude can query its own session history inline during a session — no manual CLI call, no context-switching:

{
  "mcpServers": {
    "kcp-memory": {
      "command": "java",
      "args": ["-jar", "/home/totto/.kcp/kcp-memory-daemon.jar", "mcp"]
    }
  }
}

Six tools are registered (four in v0.3.0, two added in v0.4.0):

Tool What it answers
kcp_memory_search "What did we do with OAuth last month?" — FTS5 over session transcripts
kcp_memory_events_search "Which projects did I run kubectl apply in?" — FTS5 over tool-call events
kcp_memory_list Recent sessions, optionally filtered to the current project
kcp_memory_stats Total sessions, turns, tool calls, top tools
kcp_memory_session_detail Full session content — user messages, files touched, tools used (v0.4.0)
kcp_memory_project_context Auto-detect PWD, return last 5 sessions + 20 events — no query needed (v0.4.0)

The MCP server runs an initial scan at startup and calls EventLogScanner inline before kcp_memory_events_search queries — so the most recently written events are always searchable. Transport: stdio (newline-delimited JSON-RPC 2.0). Cold start under 2 seconds.

The loop is now closed: Claude runs → kcp-memory indexes → Claude queries.


Session detail and project context (v0.4.0)

v0.4.0 adds two tools that make the MCP integration proactive rather than reactive.

kcp_memory_session_detail closes the find → read gap. kcp_memory_search returns session metadata — date, project, first message. Once you find a relevant session, you want to read what actually happened. session_detail takes a session ID and returns the full content: all user messages (up to 4,000 chars), every file touched, and the tools used.

Session: ad732c58-af84-48dd-8c4e-80fe074800b0
Project: /src/cantara/kcp-memory
Model:   claude-sonnet-4-6
Date:    2026-03-03
Turns:   47  Tool calls: 183

Tools used: Read, Edit, Bash, Write, Glob, Grep

Files touched (12):
  java/src/main/java/com/cantara/kcp/memory/mcp/McpServer.java
  java/src/main/java/com/cantara/kcp/memory/cli/KcpMemoryCli.java
  ...

User messages:
"ok, should we push further down the line for kcp-memory?"
"yes, let's do it"
...

kcp_memory_project_context makes memory proactive. It reads PWD from the process environment — no query, no session ID, no argument — and returns the last 5 sessions and 20 tool-call events for the current project. Call it at the start of a session and Claude immediately has the context it needs: what was being worked on, which commands were run, what files were touched.

Project context: /src/cantara/kcp-memory

Recent sessions (3):

2026-03-03  /src/cantara/kcp-memory
ad732c58  turns=47  tools=183
"ok, should we push further down the line for kcp-memory?"

Recent tool-call events (7):

2026-03-03 16:35  /src/cantara/kcp-memory
ad732c58  [git-tag]
$ git tag v0.3.0 && git push && git push --tags
...

With project_context in the MCP toolset, the blank slate problem is structurally solved for the current project: the agent arrives knowing what it was doing, not just what the codebase contains.


Performance

Operation Time
Initial scan (1,000 sessions) ~8 seconds
Incremental scan (unchanged sessions) ~0.5 seconds
FTS5 search query <5ms
List query (recent 50) <2ms
Daemon cold start ~1.8 seconds

The incremental scan checks the file modification timestamp against the scanned_at timestamp in the database. A session that has not changed since the last scan is skipped in a single SQL lookup — the entire scan of an unchanged 1,000-session history takes under a second.

Engineered for millisecond latency — search <5ms, list <2ms, cold start ~1.8s, incremental scan ~0.5s, initial scan ~8s


Install

Frictionless installation, zero bloat — one curl install, Zero Spring, zero frameworks, zero cloud calls

curl -fsSL https://raw.githubusercontent.com/Cantara/kcp-memory/main/bin/install.sh | bash

The installer: 1. Downloads kcp-memory-daemon.jar from GitHub Releases to ~/.kcp/ 2. Starts the daemon on port 7735 3. Runs an initial scan of ~/.claude/projects/ 4. Prints the PostToolUse hook configuration

Requires Java 21. No source clone needed.

Alias (add to ~/.bashrc or ~/.zshrc):

alias kcp-memory='java -jar ~/.kcp/kcp-memory-daemon.jar'

How it relates to kcp-commands

kcp-commands and kcp-memory are designed to run alongside each other. They share the ~/.kcp/ directory and use adjacent ports:

kcp-commands kcp-memory
Port 7734 7735
Hook PreToolUse PostToolUse
Stores Nothing (stateless) ~/.kcp/memory.db
Reads 283 command manifests ~/.claude/projects/**/*.jsonl
Answers "How do I run this command?" "What did I do in this project?"

kcp-commands saves context window by giving Claude better command knowledge before execution. kcp-memory makes past sessions retrievable. They solve different problems at different points in the tool call lifecycle — one before, one after.

Ecosystem synergy: kcp-commands (7734, PreToolUse) vs kcp-memory (7735, PostToolUse) — complementary tools covering the full tool call lifecycle

v0.2.0 — shipped today: kcp-commands v0.9.0 now writes a JSON event to ~/.kcp/events.jsonl on every Phase A Bash hook call. Each event carries ts, session_id, project_dir, tool, command (first 500 chars), and manifest_key. kcp-memory v0.2.0 reads that file incrementally using a byte-offset cursor — so each PostToolUse-triggered scan processes only the lines appended since the last scan, typically one event in under 1ms.

The result: kcp-memory events search "kubectl apply" returns every time Claude ran that command across all your projects, with project directory, session ID, and exact timestamp. Session-level granularity ("I was working on X") and tool-level granularity ("I ran Y in project Z at 14:32") from the same daemon and the same database.

Tool-level granularity shipped: kcp-commands → individual tool events → ~/.kcp/events.jsonl → kcp-memory, incremental byte-offset ingestion, per-command FTS5 search


Source

The project is at github.com/Cantara/kcp-memory. Apache 2.0.

~200 lines of SQL and schema across two migrations, ~1,850 lines of Java across seventeen source files. The only dependencies are sqlite-jdbc, jackson-databind, and picocli. No Spring, no framework, no cloud calls.

The KCP ecosystem now has three tools covering three different surfaces of the AI coding workflow:

  • kcp-commands — CLI vocabulary (283 command manifests, PreToolUse hook)
  • kcp-memory — session history (SQLite + FTS5, PostToolUse hook)
  • opencode-kcp-plugin — codebase structure (knowledge.yaml in system prompt)

The complete AI coding workflow surface — kcp-commands (CLI vocabulary, PreToolUse), kcp-memory (session history, PostToolUse), opencode-kcp-plugin (codebase structure, knowledge.yaml)


This post is part of the Knowledge Context Protocol series. Previous: KCP Comes to OpenCode: The First AI Coding Tool Plugin