oneMEM
One memory. Every AI. You own it.
Local, structured memory for AI agents — in one SQLite file on your machine.
oneMEM gives AI tools a shared local memory. It distills useful context into compact atomic facts and surfaces the minimum memory sufficient for a query. Every connected agent reads and writes the same SQLite file.
AI agents ───┐
Code editors ┼── MCP ── oneMEM ── ~/.onemem/onemem.db
Local tools ─┘
Why oneMEM?
| Local & private | One SQLite file. No server, no cloud, no account. Back it up by copying a file. |
| Deterministic retrieval | No LLM in the read path. Same query returns the same result, always. Inspectable with SQL. |
| Append-only | Events are never overwritten. Facts are only ever added. Corrections are new events. |
| MCP-native | Two tools (onemem_recall + onemem_log) — works with Claude Code, Codex, Cursor, Windsurf. |
| BYOLLM | OpenRouter, OpenAI, Anthropic, Gemini, Groq, xAI, Hugging Face, Ollama, or any OpenAI-compatible endpoint. |
| Local embeddings | bge-base-en-v1.5 (768-d) runs locally. No embedding API, no extra key, no latency. |
Quick Start
Requires Python 3.11+ and an API key for any LLM provider. Embeddings run locally.
# Install
uv tool install "onemem[all]"
# Setup (walks you through provider, key, model, capture, MCP wiring)
onemem init
# Try it
onemem add "Chose SQLite because it needs zero operations and one-file backups."
onemem ask "What storage did I choose, and why?"
Architecture
graph TB
subgraph INPUTS ["Inputs"]
CLI["CLI<br/>onemem <command>"]
MCP["MCP Server<br/>onemem-mcp"]
API["HTTP API<br/>FastAPI /events"]
WATCH["Watch<br/>Claude Code / Codex transcripts"]
end
subgraph WRITE ["Write Path"]
INTAKE["1. ingest_event()<br/>chunk - dedup by content hash - store"]
EXTRACT["2. extract_entities()<br/>LLM reads event - atomic facts + named entities"]
RECONCILE["3. reconcile + store<br/>normalize entities - link fact_entity_edges - store facts"]
EMBED_W["4. embed_facts()<br/>bge-base-en-v1.5 768-d local embedding"]
end
subgraph SQLITE ["SQLite - ~/.onemem/onemem.db"]
EVENTS[("events<br/>raw content, append-only")]
EXTR[("extractions<br/>provenance ledger")]
FACTS[("facts<br/>atomic claims")]
ENTITIES[("entities<br/>canonical names")]
EDGES[("fact_entity_edges<br/>which entities each fact mentions")]
EMBED[("fact_embeddings<br/>sqlite-vec vec0, cosine")]
FTS[("facts_fts<br/>FTS5 keyword index")]
end
subgraph READ ["Read Path"]
PARAMS["1. LLM param extraction<br/>question - topic keywords + date range"]
RETRIEVE["2. Deterministic Retrieval"]
VECTOR["Vector Door<br/>cosine similarity"]
KEYWORD["Keyword Door<br/>FTS5 BM25"]
ENTITY_D["Entity Door<br/>fact_entity_edges"]
FUSION["Fusion<br/>magnitude noisy-OR"]
CUT["3. Adaptive Cut<br/>score-curve ratio, bounded 10 to limit"]
COLLAPSE["Source Collapse<br/>if facts - raw event tokens - return raw"]
SYNTH["4. LLM Synthesis<br/>optional natural-language answer"]
end
CLI --> INTAKE
MCP --> INTAKE
API --> INTAKE
WATCH --> INTAKE
INTAKE --> EVENTS
EVENTS --> EXTRACT
EXTRACT --> FACTS
EXTRACT --> ENTITIES
EXTRACT --> EXTR
RECONCILE --> EDGES
EMBED_W --> EMBED
FACTS --> FTS
CLI --> PARAMS
MCP --> PARAMS
PARAMS --> RETRIEVE
RETRIEVE --> VECTOR
RETRIEVE --> KEYWORD
RETRIEVE --> ENTITY_D
VECTOR --> FUSION
KEYWORD --> FUSION
ENTITY_D --> FUSION
FUSION --> CUT
CUT --> COLLAPSE
COLLAPSE --> SYNTH
EMBED --> VECTOR
FTS --> KEYWORD
EDGES --> ENTITY_D
Key design principles:
- Append-only — raw events are never overwritten; facts are only ever added
- Deterministic retrieval — no LLM in the read path; same query always returns the same result
- Small models at the edges — LLM only at write time (distill) and optionally at read time (synthesize)
User Flow
%%{ init: { 'theme': 'dark', 'themeVariables': { 'actorBkg': '#7C3AED', 'actorTextColor': '#fff', 'actorBorder': '#9F67FF', 'signalColor': '#E2E8F0', 'signalTextColor': '#E2E8F0', 'noteBkgColor': '#1E293B', 'noteTextColor': '#E2E8F0', 'noteBorderColor': '#475569', 'rectBkgColor': '#0F172A', 'rectBorderColor': '#334155', 'rectTextColor': '#E2E8F0', 'sequenceNumberColor': '#fff' } }%%
sequenceDiagram
actor User
participant CLI as CLI / MCP
participant Core as oneMEM Core
participant LLM as LLM Provider
participant DB as SQLite
rect rgb(15, 23, 42)
Note over User, DB: Write — ingest and distill
User ->> CLI: onemem add "note"
CLI ->> Core: ingest_event()
Core ->> DB: store raw event
Core ->> LLM: extract facts + entities
LLM -->> Core: ExtractionResult
Core ->> DB: store facts, entities, edges
Core ->> Core: embed facts (768-d, local)
Core -->> CLI: event_ids
end
rect rgb(15, 23, 42)
Note over User, DB: Read — retrieve and answer
User ->> CLI: onemem ask "question?"
CLI ->> LLM: extract search params
LLM -->> CLI: {text, start, end}
CLI ->> Core: retrieve(text, start, end)
Core ->> DB: vector + keyword + entity search
DB -->> Core: matched facts
Core ->> Core: fusion then adaptive cut
Core -->> CLI: facts with scores
CLI ->> LLM: synthesize answer from facts
LLM -->> CLI: AskAnswer
CLI -->> User: natural language answer
end
rect rgb(15, 23, 42)
Note over User, DB: MCP — agent background write
User ->> CLI: AI agent conversation
CLI ->> Core: onemem_log(content)
Core ->> DB: store raw event
Note right of Core: background processor<br/>extracts facts later
end
Command Flow
Commands
| Command | Purpose | Path |
|---|---|---|
onemem init |
Interactive setup wizard (provider, key, model, capture, MCP) | -- |
onemem add "text" |
Store a note directly | write |
onemem ask "question" |
Retrieve matching facts + optional LLM synthesis | read |
onemem import <path> |
Bulk-import .txt / .md files (parallel batch) |
write |
onemem process |
Process all pending events (extract facts) | write |
onemem watch |
Capture Claude Code / Codex sessions in real-time | write |
onemem watch --start |
Start background capture service | write |
onemem watch --stop |
Stop background capture service | write |
onemem status |
Event / fact / entity counts + staleness detection | read |
onemem doctor |
Health check (DB, sqlite-vec, LLM, write path) | read |
onemem list events |
Browse events (--since, --until, --source) |
read |
onemem show event N |
Full event detail + extraction provenance | read |
onemem sql "SELECT..." |
Read-only SQL query against the memory | read |
onemem tables |
List all DB tables with row counts | read |
onemem config set |
Interactively change provider, API key, model | config |
onemem config show |
Show active config safely (never exposes full key) | read |
MCP Setup
oneMEM works with any MCP client that supports local stdio servers.
# Claude Code
claude mcp add --scope user onemem -- "$(command -v onemem-mcp)"
# Codex
codex mcp add onemem -- "$(command -v onemem-mcp)"
onemem init automatically detects and wires Claude Code and Codex during setup.
MCP Tools
| Tool | Purpose |
|---|---|
onemem_recall |
The ONE read entry point — topic search, time window, session reconstruction, or raw source lookup |
onemem_log |
Invisible background write — silently logs conversations. No announcement, no permission, no waiting. |
Supported Providers
| Provider | Key Env Var | Notes |
|---|---|---|
| OpenRouter | OPENROUTER_API_KEY |
One key, hundreds of models |
| OpenAI | OPENAI_API_KEY |
Direct GPT access |
| Anthropic | ANTHROPIC_API_KEY |
Native Claude API |
| Google Gemini | GEMINI_API_KEY |
Direct Gemini access |
| Groq | GROQ_API_KEY |
Fast inference, open-weight models |
| xAI | XAI_API_KEY |
Grok access |
| Hugging Face | HF_TOKEN |
Open-weight models via Inference Providers |
| Ollama | no key needed | Free, runs locally |
| Custom | base_url + api_key_env |
Any OpenAI-compatible endpoint |
Embeddings always use bge-base-en-v1.5 (768-d) running locally — no API key needed.
Benchmarks
Measured on a 100-instance stratified sample of LongMemEval-S:
| Metric | Result |
|---|---|
| Retrieval recall | 0.89 |
| Context reduction | 99.1% |
| End-to-end answer accuracy | 72% |
Configuration
Edit ~/.onemem/config.toml (or use onemem config set):
[model]
provider = "openrouter"
model = "google/gemini-3.5-flash-lite"
[spend]
max_run_cost_usd = 20.0 # hard ceiling per batch import
[retrieval]
default_limit = 30 # max facts returned per recall
neighbour_max = 20 # neighbour facts gathered around a match
[ingestion]
concurrency = 20 # parallel LLM workers during bulk import
Where data lives
| Path | Contents |
|---|---|
~/.onemem/onemem.db |
Events, facts, entities, embeddings — back this up |
~/.onemem/config.toml |
Active provider, model, runtime settings |
~/.onemem/.env |
Provider API keys |
Development
git clone https://github.com/shashank-tomar0/onemem.git
cd onemem
uv sync --all-extras
uv run pytest -q # 144 passing
./scripts/dev-onemem doctor # run with isolated dev home
Project Structure
onemem/
├── cli/ # Click CLI (init, add, ask, watch, ...)
├── api/ # FastAPI HTTP API
├── providers/ # LLM + embedding implementations
│ ├── openai_compat.py # OpenAI-compatible endpoints
│ ├── anthropic.py # Anthropic native API
│ └── local_embedding.py # bge-base-en-v1.5
├── mcp_server.py # MCP server (onemem_recall + onemem_log)
├── fact_retrieval.py # Deterministic hybrid search
├── pipeline.py # Ingest + process orchestration
├── entity_extractor.py # LLM-based entity + fact extraction
├── schema.sql # SQLite schema
└── config.py # All tunable settings
License
MIT — Based on Meniscus by magic_bubblez.
oneMEM — Your memory, your machine, your AI.
Get Started · Report Bug · View Design · PyPI
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file onemem-0.1.7.tar.gz.
File metadata
- Download URL: onemem-0.1.7.tar.gz
- Upload date:
- Size: 13.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
396df6e97ba0d3ed6e93a0c6e92c9392ce933917bc70d1ccefd0724ce17afe65
|
|
| MD5 |
a6b1e60fef56c146bb70ad67e7b49c00
|
|
| BLAKE2b-256 |
526feb9a8fefddb964e9417b6583320bced1ef85bd3a76ae6c166e208b5acef6
|
File details
Details for the file onemem-0.1.7-py3-none-any.whl.
File metadata
- Download URL: onemem-0.1.7-py3-none-any.whl
- Upload date:
- Size: 72.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c045e57834a97bd6950493c74214963824a3f5b8158244b43f36fffe6331b709
|
|
| MD5 |
add00b2b2a558d8b1cb68d4678971d49
|
|
| BLAKE2b-256 |
bd32b572708494cf1a51d989fef19cafebc3b0468f025122f7a4c35f8e357e69
|