Memory should belong to the person—not the model.
Mindmory is a local-first memory and evidence layer for AI assistants. It gives an assistant durable access to your preferences, decisions, corrections, projects, and history—without making any model or vendor the owner of that information.
AI models are replaceable. Your memory is not.
Download Mindmory Lite · Agent installation guide · MCP integrations
An AI model has a temporary working context. Product-managed memory can make that context last longer, but it is often opaque, difficult to correct, and locked to one provider. Asking a model to “remember everything” creates another problem: guesses, stale details, and model errors can quietly become supposed facts.
Mindmory treats personal memory as user-owned infrastructure and keeps three concerns deliberately separate:
| Layer | Meaning |
|---|---|
| Evidence | What the person actually said or supplied |
| Memory | The structured claim derived from that evidence |
| Retrieval | How relevant, policy-eligible memories are selected |
An evidence hash proves where a memory came from; it does not pretend that the statement is objectively true. Provenance stays visible, corrections remain possible, and the model never becomes the authority.
The model may propose a memory. The memory system decides whether it may be stored, retrieved, or trusted.
Human–machine memory should outlive any one assistant, model, vendor, database, or generation of hardware. AI is making technology evolve faster, not slower; the systems that create and retrieve memories will change many times during a person's life. The memory record itself should not inherit the short lifespan of the technology currently operating on it.
After considering richer databases and more specialized storage formats, Mindmory chose JSONL as its canonical record. The choice is deliberately simple: each line is a self-contained JSON object that a person can open and inspect with an ordinary text editor, while machines can parse, stream, hash, copy, validate, and migrate it with tools available in virtually every programming language. It does not require a particular database server, application, embedding model, or cloud provider to remain intelligible.
SQLite indexes, vectors, and future retrieval technologies are useful, but they are disposable projections. They can be rebuilt or replaced as better technology arrives. The JSONL record remains the portable source of truth.
Simplicity is a preservation strategy. A lifetime memory should be easy to understand today, recover decades from now, and carry anywhere in between.
flowchart LR
A["Conversations and evidence"] --> B["Canonical JSONL archive"]
B --> C["SQLite lexical index"]
B --> D["Optional vector index"]
C --> E["Policy-filtered retrieval"]
D --> E
E --> F["AI assistants through native hooks or optional MCP"]
- Portable by design. Human-readable JSONL is canonical and remains usable independently of a database, model, or vendor.
- Fast without surrendering ownership. SQLite is the complete read projection for search, recall, messages, and evidence. SQLite and persistent vector files can both be rebuilt from the canonical archive.
- Lexical first. Porter-tokenized BM25 handles natural-language matches, while trigram/CJK indexing and identifier-aware ranking preserve exact names, dates, codes, and preferences without embeddings. Semantic search is optional when it proves useful.
- Correctable history. New records supersede outdated memories without erasing the evidence or the history of the change.
- Model-independent. The same memory can serve Codex, Claude Code, DSH, and other assistants through native hooks or optional MCP.
“Lite” describes the operational footprint, not the design. Mindmory Lite is a single-owner service built as one Go process with JSONL, SQLite, and optional embeddings. It requires no Docker, PostgreSQL, hosted vector database, or local LLM. The result is a memory service that can be inspected, backed up, moved, repaired, and understood by the person who owns it.
Current release: 0.2.2 (2026-09-22)
Author: OOI YC · Organization: KELE Research
| Binary | Purpose |
|---|---|
mindmoryd-lite |
Loopback HTTP daemon and canonical store |
mindmory-mcp-stdio |
MCP stdio bridge used by the assistant |
mindmoryctl |
Read-only status, integrity, and guarded operator actions |
mindmory-eval-lite |
Retrieval evaluation tool (source build only) |
The daemon exposes evidence-backed memory search, recall, context packets,
explicit remember/correct/forget proposals, feedback, operational status, and
startup incident reporting. MCP callers can read sanitized configuration and
statistics through the compact gateway's mindmory_status action; secrets and
memory content are excluded.
- Go 1.26.6 or newer to build from source
- macOS or Linux for the supplied release targets
- A supported native-hook client or an MCP-capable client
No Docker is used by the build, tests, or runtime.
make test
make test-race
make evaluate
make buildNative binaries are written to bin/. To build checksummed archives for
macOS and Linux on AMD64 and ARM64:
make releaseThe source-only evaluator can also exercise synthetic short, medium, long, and superlong corpora with a fixed number of scored queries per size:
go run ./cmd/mindmory-eval-lite \
--scale \
--scale-sizes 240,1000,10000,50000 \
--scale-queries 50 \
--model none \
--output var/evaluation/scale.jsonMindmory reads configuration from the process environment. It does not load a
project .env file. Supply secrets through your service manager, shell,
keychain, or MCP host configuration.
export MINDMORY_OWNER='local-owner'
export MINDMORY_CURSOR_SIGNING_KEY='replace-with-at-least-32-random-characters'
export MINDMORY_ADMIN_TOKEN='replace-with-at-least-24-random-characters'
export MINDMORY_MCP_CLIENT_TOKENS_JSON='{"local-agent":{"token":"replace-with-at-least-24-random-characters","capabilities":["CONTEXT_READ","ARCHIVE_CHECKPOINT","MEMORY_PROPOSE","ARTIFACT_SEARCH","ARTIFACT_READ","RESOURCE_READ","OPS_READ"]}}'
export MINDMORY_LOCAL_CLIENT_KEY='local-agent'
export MINDMORY_EMBED_PROVIDER='disabled'
export MINDMORY_SEMANTIC_SEARCH='0'
./bin/mindmoryd-liteExperimental steady-state RAM reduction can be enabled with
MINDMORY_LOW_RAM_EXPERIMENT=1. It serves complete records from SQLite and
releases archive-sized Go maps after startup. Startup still temporarily
materializes canonical JSONL, so this is not yet the default.
The default bind is 127.0.0.1:58080. Keep it on loopback. Administrative
routes always require MINDMORY_ADMIN_TOKEN; set MINDMORY_AUTH=token to
require bearer authentication for model-facing routes too.
Paths are configurable and relative to MINDMORY_ROOT_DIR unless absolute.
| Variable | Default | Role |
|---|---|---|
MINDMORY_DATA_DIR |
var/data |
Canonical JSONL authority data |
MINDMORY_ALIAS_FILE |
data directory + aliases.json |
Optional startup alias overlay |
MINDMORY_DERIVED_DIR |
var/derived |
Rebuildable SQLite index |
MINDMORY_VECTOR_DIR |
var/derived/vectors |
Rebuildable vector generations |
MINDMORY_SNAPSHOT_DIR |
var/data/snapshots |
Integrity-checked snapshots |
MINDMORY_EXPORT_DIR |
var/export |
Import/export exchange |
Canonical data may not overlap derived or vector directories. Runtime state
under var/ is ignored by Git and excluded from release archives.
Lexical retrieval is the default and works without an embedding model.
MINDMORY_EMBED_PROVIDER=disabled: no embeddings.MINDMORY_EMBED_PROVIDER=ollama: local Ollama-compatible endpoint.MINDMORY_EMBED_PROVIDER=openai-compatible: external embeddings endpoint.
Remote embeddings require HTTPS, MINDMORY_EMBED_ALLOW_REMOTE=1, an API key,
and an explicit stable MINDMORY_EMBED_MODEL_DIGEST. Remote providers receive
memory and query text, so enabling them is a deliberate privacy decision.
Validate the configured provider contract before enabling semantic retrieval:
./bin/mindmoryctl providers certify
./bin/mindmoryctl providers certify --probeThe optional probe submits only fixed synthetic strings. It checks provider identity, dimensions, determinism, and basic separation without reading the canonical memory archive.
When provider, model, digest, dimensions, or embedding format changes, startup
detects the mismatch, disables semantic retrieval, and reports an actionable
incident through logs and MCP. Canonical memory remains usable. Follow the
incident-bound instructions shown by the mindmory_status action, for example:
export MINDMORY_ADMIN_ENDPOINT=http://127.0.0.1:58080
export MINDMORY_ADMIN_TOKEN='your-admin-token'
./bin/mindmoryctl vectors status
./bin/mindmoryctl vectors rebuild --incident-id inc_FROM_STATUS --confirmThe new generation is built separately and becomes current only after full
verification; a failed rebuild leaves the prior generation intact. Keep
MINDMORY_SEMANTIC_SEARCH=0 unless evaluation with real queries shows a
measurable quality benefit.
The derived SQLite search index follows the same continuity principle during schema reconstruction: a bounded background writer builds the replacement, WAL readers continue using the current generation, and the verified index is committed atomically. Once committed, new searches use it immediately; the daemon does not need another restart just to activate the rebuilt index.
Codex can use Mindmory without registering any MCP server. The bundled
UserPromptSubmit hook archives the prompt, performs strict local retrieval,
and injects only a bounded plain-text packet. The Stop hook archives the
assistant response. Sessions that receive no relevant memory pay zero
Mindmory context tokens.
./setup.sh --agent --complete-nativeInstall integrations/codex/hooks.json.example in the approved Codex config
layer and replace /ABSOLUTE/PATH. The hook returns at most three memories in
a 320-character packet with an additional 80-estimated-token ceiling, rejects weak heat-dominated matches, includes no IDs,
scores, or provenance metadata, and uses no model-visible tool call. Disable
an older registration with mcp_servers.mindmory.enabled=false.
Hosts that need the MCP compatibility surface can still run:
./setup.sh --agent --complete-mcpThe bridge discovers the protected mindmory-config.sh beside the package, so
tokens do not need to appear in agent configuration. Credentials are never
returned through MCP.
The default compact profile advertises one mindmory gateway instead of
thirteen separate tools, materially reducing the schema carried by every
agent session. Calls use {"action":"memory_search","args":{...}} (and the
same action names as the legacy tools). Retrieval is on demand; Mindmory no
longer asks the host to fetch context at session start. Set
MINDMORY_MCP_PROFILE=full only when an older client requires separate tool
names. The compact gateway's help action loads an operation's argument
contract only when needed.
Release archives also include integrations/codex/,
integrations/claude-code/, and integrations/generic/. Codex uses its hooks
for direct retrieval and two-sided checkpointing. Claude Code uses the same
adapter for checkpointing while retaining MCP for explicit retrieval and
mutation tools. Its adapter and MCP bridge share one unscoped continuity
session so evidence can be validated. Native Codex and DeepSeek Harness
sessions are separate: merely enabling their optional MCP bridge supports read
operations but does not transfer current-turn mutation authority.
The DeepSeek Harness package includes an equivalent zero-schema relay. It
retrieves at agent/pre-step, records the sourced recall message in Harness's
canonical log, and archives assembled assistant/message events. It does not
archive partial streaming chunks or synthetic context injections.
- Operational recovery: docs/lite/HARDENING_AND_RECOVERY.md
- Retrieval experiment: docs/lite/SEMANTIC_RETRIEVAL_EXPERIMENT_2026-08-27.md
- SQLite read architecture: docs/lite/SQLITE_READ_PROJECTION.md
- Release process: RELEASING.md
- Security reporting: SECURITY.md
- Contribution guide: CONTRIBUTING.md
Copyright OOI YC and KELE Research. Licensed under the MIT License.
Complete upstream terms for modules compiled into release binaries are indexed
in THIRD_PARTY_NOTICES.md and reproduced in
THIRD_PARTY_LICENSES.txt.
An optional aliases.json in the configured data directory extends the built-in
vocabulary. Set MINDMORY_ALIAS_FILE to select another file; relative overrides
resolve against MINDMORY_ROOT_DIR. Restart the daemon after edits.
[{"canonical":"青岚计划","aliases":["blue mist project"]}]Entries sharing a canonical name append case-insensitively deduplicated aliases; built-ins remain available. A missing file is optional. Invalid or unreadable files produce a warning and retain the built-ins. The loader accepts JSON arrays up to 1 MiB, with up to 1,000 entries and 100 phrases per entry.
CJK names and aliases can match inside sentences. Overlapping canonical names use the longest occurrence; a shorter name mentioned separately still matches. Reverse paraphrases expand only for standalone canonical names. Cross-language coverage depends on the configured vocabulary; this is not general translation.
See multilingual validation for the 100-case regression gate and the limitations of older benchmark results.