Skip to main content
oneMEM Logo

oneMEM

One memory. Every AI. You own it.

Local, structured memory for AI agents — in one SQLite file on your machine.

PyPI Python License: MIT Downloads Tests MCP Claude


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 → same result, always. Inspectable with SQL.
🔗 Append-only Events are never overwritten. Facts are only ever added. Corrections = 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 &lt;command&gt;"]
        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["① ingest_event()<br/>chunk → dedup by content hash → store"]
        EXTRACT["② extract_entities()<br/>LLM reads event → atomic facts + named entities"]
        RECONCILE["③ reconcile + store<br/>normalize entities → link fact_entity_edges → store facts"]
        EMBED_W["④ 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["① LLM param extraction<br/>question → topic keywords + date range"]
        RETRIEVE["② 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["③ Adaptive Cut<br/>score-curve ratio, bounded [10, limit]"]
        COLLAPSE["Source Collapse<br/>if facts ≥ raw event tokens → return raw"]
        SYNTH["④ 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

flowchart LR
    START(["🧠 User has a thought"])

    subgraph WRITE ["✍️ Write"]
        direction TB
        ADD["onemem add<br/>'note'"]
        IMPORT["onemem import<br/>./docs/"]
        WATCH2["onemem watch<br/>(background capture)"]
        MCP_LOG["onemem_log<br/>(invisible agent write)"]
    end

    subgraph PROCESS ["⚙️ Process"]
        direction TB
        LLM_EXTRACT["LLM distills<br/>facts + entities"]
        RECON["Entity reconciliation<br/>normalize + deduplicate"]
        LOCAL_EMBED["Local embedding<br/>bge-base 768-d"]
    end

    subgraph STORE ["📦 Store"]
        SQLITE[("SQLite<br/>events → facts<br/>→ embeddings<br/>→ FTS5 index")]
    end

    subgraph READ ["📖 Read"]
        direction TB
        ASK["onemem ask<br/>'question'"]
        MCP_RECALL["onemem_recall<br/>(AI agent call)"]
        SQL["onemem sql<br/>'SELECT...'"]
        LIST["onemem list events"]
    end

    START --> WRITE
    WRITE --> PROCESS
    PROCESS --> STORE
    STORE --> READ
    READ --> ANSWER(["✨ User gets answer"])

    style WRITE fill:#dcfce7,stroke:#16a34a,color:#15803d
    style PROCESS fill:#fef9c3,stroke:#ca8a04,color:#a16207
    style STORE fill:#e0e7ff,stroke:#4f46e5,color:#4338ca
    style READ fill:#dbeafe,stroke:#2563eb,color:#1d4ed8

⚡ All Commands — Visual Reference

oneMEM 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

onemem-0.1.5.tar.gz (12.6 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

onemem-0.1.5-py3-none-any.whl (72.3 kB view details)

Uploaded Python 3

File details

Details for the file onemem-0.1.5.tar.gz.

File metadata

  • Download URL: onemem-0.1.5.tar.gz
  • Upload date:
  • Size: 12.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.7

File hashes

Hashes for onemem-0.1.5.tar.gz
Algorithm Hash digest
SHA256 7e3c31082c55086e87d3cd8c738545eeab882e53cc83b9e50f980c306280a87e
MD5 792a069e43b653833d7c6591bc494934
BLAKE2b-256 5f836e12fcff4e34c953c9828682e63ff41ec8a213a53094fef1f4be27478f1d

See more details on using hashes here.

File details

Details for the file onemem-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: onemem-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 72.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.7

File hashes

Hashes for onemem-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 013b98e2b852630aed8716ba547cfdf7acb6f6ac84c019c9a54883880bd76052
MD5 e8a1224c6222c1f63d445067b398f89d
BLAKE2b-256 3245471202e071cd69c06781bb4a2146d98cde1badefd6d84508aa0f9198bcc4

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.7

2 files

0.1.6

2 files

This release

0.1.5 This release

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

1 file

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page