JR

janbjorge/rekal

Developer tools
52 stars 0 forks Качество 55 Тренд 55

rekal is an MCP server that gives AI coding agents persistent memory across sessions. Memories are stored locally in SQLite and retrieved with hybrid search (BM25 keywords + vector semantics +...

Обзор

rekal is an MCP server that gives AI coding agents persistent memory across sessions. Memories are stored locally in SQLite and retrieved with hybrid search (BM25 keywords + vector semantics +...

README

rekal

Long-term memory for LLMs. One SQLite file, no cloud, no API keys.

rekal is an MCP server that gives AI coding agents persistent memory across sessions. Memories are stored locally in SQLite and retrieved with hybrid search (BM25 keywords + vector semantics + recency decay). Nothing leaves your machine.

How it works · Quickstart · Install · Setup · Updating · Tools · Under the hood · Troubleshooting

Works with any MCP-capable agent: Claude Code, Codex CLI, OpenCode, Cursor CLI.

Session 1:   "I prefer Ruff over Black"  → memory_store(...)
Session 47:  "Set up linting"            → memory_build_context("formatting preferences")
                                          ← "User prefers Ruff over Black" (0.92)
                                          Sets up Ruff without asking.

How it works

  1. Store. The agent saves a durable fact with memory_store: a preference, a decision, a non-obvious discovery.
  2. Index. rekal writes it to SQLite and builds two indexes over it: a BM25 keyword index and a 384-dimensional vector embedding, both computed locally with no network calls.
  3. Recall. In a later session the agent calls memory_build_context. rekal blends keyword match, semantic similarity, and recency into a single score and returns the top hits above a relevance floor.

All state is a single file: ~/.rekal/memory.db. For the scoring formula, schema, and embedding model, see Under the hood.

Quickstart (Claude Code)

uv tool install rekal                            # 1. install rekal (or: pip install rekal)
claude mcp add --scope user rekal -- rekal mcp       # 2. register the MCP server (all projects)
claude plugin marketplace add janbjorge/rekal    # 3. add the plugin marketplace
claude plugin install rekal-skills@rekal         # 4. install the plugin

Then add "autoMemoryEnabled": false to ~/.claude/settings.json so Claude Code’s built-in memory doesn’t compete with rekal.

Restart Claude Code and the agent has persistent memory. For what each step does, the other agents (Codex CLI, OpenCode), and the rationale behind disabling built-in memory, read on.

Install

pip install rekal
# or
uv tool install rekal

Requires Python 3.11+. On first run, rekal creates ~/.rekal/memory.db. To upgrade an existing install later, see Updating.

Setup for Claude Code

Three steps: add the MCP server, install the plugin, and disable built-in memory.

1. Add the MCP server. This gives Claude Code the memory tools:

claude mcp add --scope user rekal -- rekal mcp

--scope user registers rekal for all your projects. Without it, claude mcp add defaults to local scope and the server loads only in the project where you ran it (MCP scopes), and memory should follow you everywhere. The -- separates Claude Code’s own flags from the command that launches the server; stdio is the default transport.

2. Install the plugin. This teaches Claude Code when to use those tools and prevents conflicts with built-in memory:

claude plugin marketplace add janbjorge/rekal
claude plugin install rekal-skills@rekal

3. Disable built-in auto memory. Add "autoMemoryEnabled": false to ~/.claude/settings.json:

{
  "autoMemoryEnabled": false
}

Setup for Codex CLI

One step. rekal is a standard MCP stdio server, with no plugin system and no competing memory to disable (Codex memories are off by default).

Add to ~/.codex/config.toml (Codex MCP docs):

[mcp_servers.rekal]
command = "rekal"
args = ["mcp"]

# optional: scope all memories to a project automatically
[mcp_servers.rekal.env]
REKAL_PROJECT = "my-project"

Instruct the agent to call memory_build_context at session start. Add to your project’s AGENTS.md:

Call memory_build_context with your current task before exploring the codebase.

Setup for OpenCode

One step. OpenCode has no built-in memory system, so there is nothing to disable.

Add to opencode.jsonc in your project root (OpenCode MCP docs):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "rekal": {
      "type": "local",
      "command": ["rekal", "mcp"],
      "enabled": true,
      "environment": {
        "REKAL_PROJECT": "my-project"
      }
    }
  }
}

OpenCode does not auto-read AGENTS.md; you must list instruction files explicitly (OpenCode config docs). Add to your opencode.jsonc:

{
  "$schema": "https://opencode.ai/config.json",
  "instructions": ["AGENTS.md"]
}

Setup for Cursor CLI

One step. rekal is a standard MCP stdio server, and Cursor has no competing memory to disable. The CLI shares the editor’s MCP config, so this also enables rekal in the Cursor editor (Cursor CLI MCP docs).

Add to ~/.cursor/mcp.json (global, all projects) or .cursor/mcp.json (project-only) (Cursor MCP docs):

{
  "mcpServers": {
    "rekal": {
      "command": "rekal",
      "args": ["mcp"],
      "env": {
        "REKAL_PROJECT": "my-project"
      }
    }
  }
}

The env block is optional; drop it for global (unscoped) memory. Then enable and verify:

agent mcp enable rekal
agent mcp list

Instruct the agent to call memory_build_context at session start. Add to your project’s AGENTS.md:

Call memory_build_context with your current task before exploring the codebase.

Updating

Update rekal (the MCP server)

pip install -U rekal
# or
uv tool upgrade rekal

Restart your agent so it relaunches the server. The SQLite schema migrates automatically on the next start: new columns are added in place and existing memories are preserved, so you never run a migration by hand. To start fresh instead, delete ~/.rekal/memory.db (rekal recreates it on next run).

Update the Claude Code plugin

Third-party marketplaces have auto-update off by default (auto-update docs), so refresh manually, then reload:

claude plugin marketplace update rekal     # refresh the catalog
claude plugin install rekal-skills@rekal   # reinstall to pull the update

If hooks or skills are still missing afterward, Claude Code is serving a stale plugin cache. Clear it, restart Claude Code, then reinstall (official remedy):

rm -rf ~/.claude/plugins/cache

Tools

rekal exposes exactly three MCP tools. A small surface keeps the tool schemas cheap in the agent’s context and leaves no ambiguity about which tool to call:

Tool Purpose
memory_build_context Recall: hybrid search over stored memories. Results below the relevance floor (min_score, default 0.25) are dropped
memory_store Store a distilled durable memory with project and tags. Pass replaces= to update an existing memory instead of creating a near-duplicate
memory_delete Remove a memory by ID

Setting REKAL_READONLY=1 in the server’s environment registers only memory_build_context, for sessions that should recall but never write. In read-only sessions the injected memory block also points the agent at rekal recall --query in the shell, so it can pull stored knowledge mid-task without any MCP tool mounted.

Admin operations live in the CLI, not the tool surface:

Command Purpose
rekal health Database stats: total, counts by project, date range
rekal export Dump all memories as JSON
rekal prune Bulk-delete by scope (project / age); dry-run by default
rekal recall Print memories for a query (what the hooks inject)

Under the hood

Storage

Everything lives in ~/.rekal/memory.db. Three tables share it:

Table Holds
memories the atomic unit: content + project scope + tags + timestamps
memories_fts FTS5 keyword index over content+tags+project, trigger-synced
memory_vec sqlite-vec 384-dim embedding, 1:1 with memories (synced in Python, no trigger)

memory_store(replaces=) stores the new memory and deletes the old one in a single operation, so a topic is only ever covered by one memory and stale versions never show up in search.

The schema is deliberately minimal. Earlier versions carried conversation graphs, memory links, a scratch tier, memory types, and access counters; benchmarks showed the structure cost tokens (fatter payloads, fatter instructions) without earning them back. The full schema and the auto-migration from older databases live in docs/data-model.md. Existing DBs migrate in place on first open, keeping content and embeddings.

Embeddings

rekal uses fastembed with BAAI/bge-small-en-v1.5 (384 dimensions). It runs locally via ONNX and makes no network calls. The model downloads once on first use (~50MB) and is cached.

Every recall runs two parallel lookups, merges candidates, then scores:

score = w_fts × sigmoid(-BM25)                       ← keyword relevance    (default 0.4)
      + w_vec × (1 - cosine_distance)                 ← semantic similarity  (default 0.4)
      + w_recency × exp(-0.693 × days/half_life)      ← recency              (default 0.2, 30-day half-life)

Why three signals? Keywords miss synonyms (“deploy” vs “ship to prod”). Vectors miss exact identifiers. Recency alone buries important old knowledge. The blend covers all three failure modes.

Full ranking reference, covering normalization, candidate retrieval, weight resolution, and a tuning guide, is in docs/scoring.md.

Why SQLite?

  • One file you can copy, back up, version-control, or delete to start fresh
  • There is no daemon, port, or connection string to configure
  • FTS5 gives BM25 ranking without an external search engine
  • sqlite-vec runs vector search in the same process, so there is no separate vector DB
  • Queries hit local disk and return in under a millisecond

Troubleshooting for Claude Code

Agent still writes to MEMORY.md

  1. Check autoMemoryEnabled is false in ~/.claude/settings.json
  2. Check the plugin is installed: claude plugin list should show rekal-skills

Session starts with no memory injected

The UserPromptSubmit hook recalls memory in-process (rekal hook user-prompt-submit) and injects prompt-matched hits, so memory should be present without the agent calling a tool (SessionStart injects only a directive; memories arrive with your first prompt). If nothing shows up, confirm uv is available to Claude Code’s hook subprocesses, and that any REKAL_PROJECT / REKAL_DB_PATH you rely on is set where the hook subprocess sees it (shell or settings.json env, not the MCP env block). See Recall hooks: environment scoping.

Memories not being stored

Check the MCP server is running: claude mcp list should show rekal. If missing:

claude mcp add --scope user rekal -- rekal mcp

Hooks or skills missing after a plugin update

Claude Code may serve a stale plugin cache. Clear it and reinstall (see Update the Claude Code plugin).

CLI

rekal mcp      # Run the stdio MCP server (what Claude Code connects to)
rekal recall   # Print memories for hook context injection (--query, --project, --format)
rekal health   # Database health report
rekal export   # Export all memories as JSON
rekal prune    # Bulk-delete memories by scope (dry-run unless --yes)

rekal prune requires at least one filter: --project NAME, --older-than-days N, or --before "YYYY-MM-DD HH:MM:SS". Without --yes it only reports the match count.

Architecture (for contributors)

License

MIT

View this README on GitHub

Установка

This server does not publish a one-line install command.

Open the repository installation guide

Конфигурация

{ "mcpServers": { "rekal": { "command": "rekal", "args": ["mcp"], "env": { "REKAL_PROJECT": "my-project" } } } }