Rekal is the memory your team is missing — the why behind your code, captured at every commit and shared in git, not someone else's cloud. Your AI agent starts every session blank; Rekal gives it your team's reasoning, dead-ends and all.
Quick start · How it works · Benchmarks · Docs · Paper · Discord
📄 Research published: "Why Git Is the Memory Solution for the Agentic Development Lifecycle" on arXiv (2607.14390)
Memory that lives in git — shared by your team, personally adaptive as you recall. Works with Claude Code, Cursor, Copilot, Codex, Gemini, Kiro, and OpenCode.
Every AI session settles decisions — why this approach, what got tried and thrown away. Then the session ends and that reasoning is gone. Rekal captures it at every commit, stores it raw in git, indexes and embeds it locally in the background, and shares it across your team when the work merges. No memory SaaS, no external memory service — embedding is local, and the store is just two files in .rekal/. Your agent recalls the conversation behind any change: the reasoning, the dead-ends already ruled out, the exact decision — in ~7.5K context tokens, in a few seconds, from git.
- Know why, not just what — the conversation behind every change, not just the diff.
- Stop re-deciding — dead-ends already ruled out stay ruled out; nobody re-proposes them.
- Team memory in git — merged work travels with the repo over plain push/fetch. No server.
- Personalised & adaptive — as you recall, load-bearing memories get a local usage hint and a gentle ranking nudge — on your machine only, never synced.
Requirements: Git, macOS or Linux.
/plugin marketplace add rekal-dev/rekal-cli
/plugin install rekal@rekal-dev
Then /rekal:install once per machine, and /rekal:init in each repo you want
memory in. Both confirm before touching anything. That's the whole setup — skip
to step 3 below.
# 1. Install (default: ~/.local/bin — override with --target <dir>)
curl -fsSL https://raw.githubusercontent.com/rekal-dev/rekal-cli/main/scripts/install.sh | bash
# 2. Turn it on in your repo
cd your-project
rekal init
# 3. Work as normal — commit, and your AI session is captured automatically
git commit -m "…"
# 4. In any later session, ask
rekal "why did we drop batching?"rekal init sets up .rekal/ (the store), a post-commit/pre-push git hook,
the agent skill under .claude/skills/rekal/, an orphan branch
rekal/<your-email> for transport, and one marker-tagged line in CLAUDE.md
pointing your agent at the skill — plus the equivalent line in the rules file of
any other agent it detects (AGENTS.md for Codex/Cursor/OpenCode, GEMINI.md,
.github/copilot-instructions.md, or .kiro/steering/rekal.md for Kiro). Your
own content is never touched. That
line is the whole developer experience for most users: init, then commit and
push as normal — your agent routes its own memory from there.
After you upgrade the binary, the next recall that sees a pinned skill-version
mismatch refreshes .claude/skills/ in place (hooks and agent instruction
files are left alone). Re-run rekal init to also refresh hooks, the CLAUDE.md
marker line, and other detected-agent rules — data stays untouched. To remove
everything Rekal created, run rekal clean (no residue). Full setup, teardown,
and verification detail: docs/usage.md.
The Claude Code plugin above is setup only — /rekal:install and /rekal:init,
plus the installer it ships. The recall skill itself comes from the binary, so it
always matches the version answering your commands.
Last week, one engineer and their agent settled how webhook retries should work. This week, a different agent is about to re-propose the approach that was already rejected — until it asks Rekal first:
$ rekal "should webhook retries use a fixed delay?"INJECT top=0.81 gap=0.28 2 seeds
01JNQX8F2K9M conf=0.81 t14 [reached 3×· "webhook retry policy"] "no, a fixed 5s delay stampedes the downstream on recovery. Use exponential backoff with jitter…"
01JNR2A7YQ4P conf=0.53 t9 "we capped retries at 5 attempts then dead-letter — anything past that never lands…"
Compact text by default — the whole answer in two lines. Line one is the
verdict: INJECT (surface this memory now); the alternatives are
KNOWLEDGE (read a HEAD-prose pointer instead) and SILENCE (memory isn't
the tool — stay quiet). Each seed is a session id, its absolute
confidence, the turn to drill (t14), and the snippet. [reached 3×· …] is
your personal recall graph: you have used this memory three times before,
last for "webhook retry policy" — a load-bearing decision on your machine
(local-only, never pushed), and a good first drill.
The agent gets the decision and the reason the alternative was rejected — sourced from the human's own mid-course correction — before it wastes a round re-proposing it. It drills in for the full reasoning with one more call:
$ rekal query --session 01JNQX8F2K9M --role human_steeringEverything defaults to text an agent can act on directly; add --json when a program needs to parse it — the same result carries score (rank within the set, max-normalized), absolute confidence, and raw BM25 mass, so a silence gate can reject a query that is merely the best of a weak set:
$ rekal --json "should webhook retries use a fixed delay?"{
"query": "should webhook retries use a fixed delay?",
"results": [
{
"session_id": "01JNQX8F2K9M",
"score": 0.87, "confidence": 0.81, "mass": 5.4,
"snippet": "no, a fixed 5s delay stampedes the downstream on recovery. Use exponential backoff with jitter…",
"snippet_role": "human_steering",
"session": { "author": "dev@team.dev", "branch": "feat/webhooks", "commit": "a1b2c3d" }
}
]
}| Instead of | The gap | Rekal |
|---|---|---|
a MEMORY.md / notes file |
rots, hand-maintained, tied to one branch | captured automatically at every commit, immutable, branch-aware |
| a RAG / memory SaaS | a service to run + external servers + privacy risk | local-only, nothing to operate, memory that travels with the repo |
| editor rules (Cursor/Copilot) | per-user, per-editor, ephemeral, no team history | team-wide persistent memory, travels with repo, shared decision ledger |
git log / git blame |
tell you what changed, never why | the conversation and reasoning behind the change |
Rekal is built on beliefs. Those beliefs guide every decision. When a choice conflicts with a belief, the choice loses. That is the difference.
- Data and index, separated. Your sessions land in an append-only
data.dbraw — no LLM pre-summarization, no lossy "memory" distillation. The derivedindex.db(full-text + embeddings) is built and rebuilt locally from that data, and can be thrown away and regenerated at any time. - Local embedding, no external memory service. Embeddings are computed by an on-device model; retrieval — lexical + graph + deep semantic — runs on your machine. No memory SaaS, no vector-DB tier, no session text leaving the box (unless you explicitly point embeddings at a remote endpoint).
- One immutable source of truth — fresh, no stall. Raw sessions are an append-only, immutable ledger in git — the truth; the index (embeddings and all) is a disposable derivative, a pure function of that truth. So it can never drift or go stale the way a separate memory store does — a rebuild always reconciles it — and because it's disposable, the heavy passes run in the background, hard-timeboxed, so your commit never waits. Thin on the wire, rich on the machine.
- Personalised, adaptive recall graph. Every recall links a session to the query that reached it — on your machine only (never pushed or synced). Well-trodden memories surface with a
[reached N×]hint and, by default, rank a little higher (reach_boost). Self-activating; inert until you accumulate edges. See docs/design/recall-graph.md. - Intent in git. Not in a separate system, not behind someone else's service. Orphan branches, full history, travels with the repo. No servers, no APIs, no telemetry.
- Single binary. Everything embedded — database, embeddings, inference engine, compression. Zero setup. Just
rekal initand commit. - Provenance. Every answer traces back: the turn, the session, the commit it produced, the reasoning it captured. Full graph.
- Agent-first output. A compact text digest built for an agent to act on — verdict, per-seed confidence, drill pointers — with structured JSON one
--jsonaway. Silence gates and confidence thresholds, not prose.
The full version: SOUL.md.
This is the payoff: your team's reasoning, shared without a server. Rekal data
rides plain git on orphan branches named rekal/<email> — no common ancestor
with your code, so it never touches your history, merges, or working tree.
rekal syncfetches teammates' branches and folds their sessions into your local index — team context before you start working.- Merged work only. Your local store keeps every branch at full fidelity,
but only work that landed on the default branch reaches the wire (ancestor
of
main, or a squash-merge detected by patch-equivalence — no heuristics). Unmerged spikes stay local; a dead-end never leaks to the team, and merged work ships automatically on the next push. - Cross-repo recall (optional) can span every local session on your machine, index-only so it's structurally unshareable.
Team memory is the shared session ledger. The recall graph is separate: personal and local — it adapts to your access patterns and never rides the wire. Full workflow: docs/usage.md.
Recall isn't only past sessions. Rekal also chunks your repo's prose at HEAD
(README, docs/, design notes) into a knowledge substrate, so a question
about a current convention returns a pointer to the authoritative file and lines
rather than an old conversation — the KNOWLEDGE verdict in the digest above.
Design: docs/design/knowledge-layer.md.
The design is argued and measured in our paper — "Why Git Is the Memory Solution for the Agentic Development Lifecycle" (arXiv:2607.14390, PDF): memory bound to git inherits its hard guarantees instead of rebuilding them; retrieval is closed as a seed-supply problem (honest grep floors, a mechanism study, the facet term); and a gated router answers each question kind — structure, episode, or rationale — at a few hundred tokens per question. The benchmark labels itself from your own commit–session links, so every result is replicable on your own history at zero annotation cost. See docs/research/ for details.
On two public long-term-memory benchmarks, Rekal reaches strong answer quality with no memory layers and no external memory service — retrieval runs locally over git. The answering agent is GPT-5 Sol; Rekal supplies the memory, the model supplies the answer:
| Benchmark | Accuracy | Recall@20 | Context tokens/query | Agent turns/query | Time/query (agent) |
|---|---|---|---|---|---|
| LoCoMo | 90.57% | 98.61% | ~7.5K | 5.9 | a few seconds |
| LongMemEval | 86.60% | 99% | ~10.5K | 6.6 | a few seconds |
| Additional metric (LoCoMo) | Result |
|---|---|
| Recall@10 | 93.60% |
| Recall@5 | 86.44% |
| Official F1 | 63.0 |
| Typical answer output | ~78–80 tokens |
| L1 / L2 memory layers | None |
| External memory service | None |
That is 90.6% LoCoMo accuracy, 86.6% LongMemEval accuracy, and Top-20 recall of 98.6% (LoCoMo) / 99% (LongMemEval) — at roughly six agent turns per question, with no memory tier behind it. And these are the shipped skill in the loop, not a hand-tuned harness: as the answering agent gets stronger, so does the skill — accuracy climbs toward the ~98.6% / 99% Top-20 recall ceiling as the right seeds are surfaced.
Local store, wire & recall latency (Rekal's own coding sessions, Apple M4 —
6 Claude transcripts / 14 sessions, 473 turns; pure rekal, no answering model):
| Metric | Result |
|---|---|
| Raw JSONL | 8.5 MB |
| Wire | 54 KB (~158×) |
data.db |
5.8 MB |
index.db |
10.8 MB |
Local store (data + index) |
16.5 MB |
| Recall latency | median ~150 ms (p95 ~210 ms) |
| LoCoMo synthetic recall | median ~350 ms (p95 ~400 ms) |
| In-process search | ~76 ms |
Time/query in the accuracy table is end-to-end agent answering; these rows are retrieval and footprint alone. Wire reduction is vs the raw agent transcript (strip tool outputs / file bodies / JSONL chrome, then zstd) — see SOUL.md. Local DBs stay rich on the machine; only the wire is thin.
The trade we make on purpose: one immutable source of truth — no summaries, no upkeep, real reasoning on demand. Rekal keeps your raw sessions as an append-only, immutable ledger in git — the single source of truth — and never distills them into lossy "memories." There is nothing to summarize, nothing to maintain, nothing that drifts: the index (embeddings and all) is just a disposable accelerator over the ledger, reconciled to truth by a one-command rebuild, with raw sessions drillable the instant you commit. The intelligence isn't pre-baked into stored summaries — the heavy reasoning (retrieval, ranking, routing, the agent's own judgment) runs at query time, over the real record, when you actually ask. It's lazy evaluation — the oldest trick in the engineering book, compute on demand instead of eagerly up front — applied to memory: lazy inference, so nothing is derived until a question needs it, and nothing derived can rot in the meantime. And when you do pay for ask-time reasoning, that ask becomes another session — distilled, reasoned, riding git with the team — so the cost of the inference is implicitly cached for the next recall. The one expensive write-time step, building that index, runs in the background and hard-timeboxed, so your commit never waits. Fresh memory, no upkeep, real reasoning on demand.
Token estimates are the visible context produced during the enhanced hard-question runs. Reproduce them on your own history: the benchmark labels itself from your commit–session links at zero annotation cost (see docs/research/).
flowchart LR
subgraph capture ["Capture"]
A["AI Session"] -->|"rekal checkpoint<br/>(post-commit)"| B[("data.db<br/>append-only")]
end
subgraph transport ["Transport"]
B -->|"rekal push"| C["Wire Format<br/>zstd + varint interning"]
C -->|"git push<br/>rekal/<email>"| D[("Remote<br/>orphan branch")]
end
subgraph index ["Index"]
B -->|"rekal index"| E[("index.db<br/>local-only")]
D -->|"rekal sync"| E
E --- F["BM25 FTS"]
E --- G["LSA Embeddings"]
E --- N["Deep Embeddings"]
E --- H["Co-occurrence"]
E --- I["Facets"]
E --- KN["Knowledge chunks"]
end
subgraph query ["Query"]
J["rekal 'keyword'"] -->|"hybrid + knowledge"| E
E -->|"seed digest (text)<br/>conf · mass · --json"| K["Agent"]
K -->|"rekal query<br/>--session <id>"| B
B -->|"full conversation"| K
end
style capture fill:#fff5f5,stroke:#e94560,color:#333
style transport fill:#f0fdf4,stroke:#22c55e,color:#333
style index fill:#f0f4ff,stroke:#3b82f6,color:#333
style query fill:#faf5ff,stroke:#a855f7,color:#333
The flow: commit → capture → push → sync → recall.
| You do | Rekal does |
|---|---|
rekal init (once per repo) |
Creates .rekal/, installs git hooks, writes the agent skill (tip + scripts + references) |
git commit |
Hook runs rekal checkpoint — snapshots your active AI session into data.db (append-only) |
git push |
Hook runs rekal push — encodes only your unexported data into compact wire format (zstd + string interning) and pushes to your orphan branch rekal/<email> |
rekal sync (manual, when you want team context) |
Fetches teammates' orphan branches, imports their sessions into your local DB and rebuilds the search index |
rekal clean (if needed) |
Removes .rekal/ and hooks from the repo |
Day-to-day: commit and push as normal. Everything else is automatic.
Your agent recalls with rekal "<query>" — the compact seed digest it acts on
directly — and drills into any session with rekal query --session <id>,
controlling how much context it loads: search first, drill progressively, full
sessions only when needed. The complete command surface and the
progressive-loading pattern are in docs/usage.md.
rekal init installs one Claude Code skill under .claude/skills/rekal/. It is
a thin route: the agent classifies each question and sends it to one substrate —
tree (grep, now), knowledge (prose at HEAD), ledger (past
reasoning), or map (structure). For a ledger question, a second step
classifies the answer type and loads exactly one specialist workflow, so
"how long", "how many", and "when" each get concentrated, non-overlapping
guidance. Retrieval and navigation are commands in the binary; the skill is
judgment, not scripts.
flowchart TB
tip["SKILL.md route<br/>always loaded, thin"]
tip --> triage{"Which substrate?"}
triage -->|Tree now| grep["grep / read HEAD"]
triage -->|Knowledge| readk["rekal '<q>' → Read HEAD prose"]
triage -->|Map| mapf["map.sh fresh → map.md"]
triage -->|Ledger / past reasoning| gate{"Answer type?"}
gate -->|duration| w1["workflows/duration.md"]
gate -->|count / set| w2["workflows/complete-set.md"]
gate -->|event time| w3["workflows/event-time.md"]
gate -->|inference| w4["workflows/inference.md"]
gate -->|fact / why| w5["workflows/point-fact.md"]
Full skill reference: docs/usage.md#the-agent-skill · every command and flag: docs/commands.md · design: docs/design/skill-router.md.
Two local DuckDB databases keep the split clean: data.db (append-only truth,
the only thing pushed) and index.db (rebuildable local intelligence — FTS,
embeddings, the recall graph, knowledge chunks). Linked git worktrees share one
store. The databases, transport, and cross-repo recall are covered in
docs/usage.md.
Rekal is zero-config by default. To tune ranking weights — the hybrid layer
mix, the facet layer, and the recency / recall-graph reach boosts — or point
deep embeddings at an OpenAI-compatible endpoint (vLLM, Ollama, LM Studio, TEI),
there is exactly one file — .rekal/config.json, gitignored and local-only,
never committed. See docs/configuration.md.
| Command | Description |
|---|---|
rekal init |
Initialize Rekal in the current git repository |
rekal clean |
Remove Rekal setup from this repository |
rekal version |
Print the CLI version |
rekal checkpoint |
Capture the current session after a commit |
rekal push [--rebuild] |
Push Rekal data to the remote branch (merged work only; append-only — no force) |
rekal sync [--self] |
Sync team context from remote rekal branches |
rekal index [--include-all|--include <repo>|--no-local] |
Rebuild the index DB (atomic temp→rename); optionally fold in cross-repo local sessions |
rekal embed |
Fill missing semantic embeddings (resumable; also started after index/sync) |
rekal log [--limit N] |
Show recent checkpoints |
rekal find "<term>" [role] |
Enumerate every ledger mention of a term (complete, time order) |
rekal [--file <re>] [--commit <sha>] [--author <email>] [--actor human|agent] [-n N] [--explain] [--json] [query] |
Hybrid search → seed digest by default; --json for raw structured results; --explain adds per-layer scores |
rekal query --session <id> [--role <r>] [--offset N] [--limit N] [--full] [--json] |
Drill into a session — readable turns by default; --json for one object |
rekal query --sql "<sql>" [--index] [--json] |
Raw SQL → TSV by default; --json for NDJSON |
Full details: docs/spec/command/.
| Guide | What's in it |
|---|---|
| docs/usage.md | The two databases, orphan branches & merged-work-only sharing, worktrees, the full agent command surface, the skill, cross-repo recall |
| docs/configuration.md | .rekal/config.json — ranking weights, embedding backends, API-key handling |
| docs/spec/command/ | Per-command reference specs |
| docs/research/ | The paper, benchmark harness, and evaluation strategy |
| docs/DEVELOPMENT.md | Building, testing, and releasing |
| CONTRIBUTING.md | What a contribution has to satisfy, and what will be declined |
| SECURITY.md | The security model, what's in scope, how to report a vulnerability |
| SOUL.md | The beliefs behind every design decision |
git clone https://github.com/rekal-dev/rekal-cli.git rekal-cli
cd rekal-cli
mise installSee docs/DEVELOPMENT.md for the full development guide.
Read SOUL.md first — it is the review bar, not a mission statement. Then CONTRIBUTING.md for the checks, the doc-sync rule, and the list of changes that will be declined before you spend a weekend on them.
Everyone participating is expected to follow the Code of Conduct.
Security vulnerabilities go through SECURITY.md, never a public issue.
rekal --help
rekal <command> --helpIssues: github.com/rekal-dev/rekal-cli/issues
If you use Rekal or build on the research, please cite the paper:
@misc{guo2026rekal,
title = {Why Git Is the Memory Solution for the Agentic Development Lifecycle},
author = {Guo, Frank},
year = {2026},
eprint = {2607.14390},
archivePrefix = {arXiv},
primaryClass = {cs.SE},
url = {https://arxiv.org/abs/2607.14390}
}Apache-2.0 — see LICENSE.