Skip to main content

memstrand

Local-first memory for AI agents. Typed, scoped, and it never leaks one task into another.

PyPI Python versions License: MIT CI

Quickstart · Docs · Integrations

memstrand 30-second demo

Why memstrand

Flat vector memory has three failure modes, and every agent hits all three:

  • No types — a preference, a decision, and a guess all look the same to cosine similarity.
  • No scope — a fact learned while testing Playwright leaks into an unrelated Mac disk-cleanup session. (This actually happened. It's why this exists.)
  • No provenance — nobody knows whether a memory was said, inferred, or corrected, or how confident the agent was.

memstrand fixes all three: every memory is typed (13 categories), scoped (session/task/host, a hard filter — not a ranking signal), and carries provenance (how it was learned, confidence, expiry). One daemon (memstrand serve) shares all of that across Claude Code, Cursor, Open WebUI, and your own scripts — over MCP, REST, and an OpenAI-compatible proxy — backed by an embedded, on-disk store. No Docker, no cloud, no API keys.

Quickstart

pip install memstrand
from memstrand import Category, Memory, Provenance

mem = Memory.in_memory()

# A fact scoped to one task...
mem.remember(
    "Playwright installed as an agent-testing task dependency",
    category=Category.fact,
    provenance=Provenance.explicit_statement,
    task_id="playwright-test",
)

# ...and a global preference
mem.remember(
    "Chiran prefers a natural, unstylized look in AI portraits",
    category=Category.preference,
    provenance=Provenance.explicit_statement,
    confidence=0.95,
)

# An unrelated session asks about testing setup.
# The Playwright fact does NOT leak across the task boundary:
for hit in mem.recall("testing setup"):
    print(hit["category"], "-", hit["content"])
# preference - Chiran prefers a natural, unstylized look in AI portraits

# Same query WITH the task scope sees it:
for hit in mem.recall("testing setup", task_id="playwright-test"):
    print(hit["category"], "-", hit["content"])
# fact - Playwright installed as an agent-testing task dependency

Memory.in_memory() runs Qdrant in :memory: mode and the graph/session/ keyword stores in a temp SQLite file — nothing touches disk and nothing persists past the process. Embeddings are local ONNX (fastembed) by default, downloaded once on first use.

Make it your second brain

memstrand serve                                                    # one daemon: MCP + REST + web UI + OpenAI proxy
claude mcp add --transport http memstrand http://127.0.0.1:7777/mcp  # Claude Code
# Open WebUI -> Admin Settings -> Connections -> OpenAI API -> Base URL http://127.0.0.1:7777/v1
memstrand ingest ~/notes --watch                                   # keep your notes/Obsidian vault synced in

Full setup recipes (Ollama/llama.cpp/LM Studio, Cursor, launchd/systemd autostart, cron backups) are in docs/integrations.md.

Features

  • 100% local, zero API keys — embedded Qdrant + SQLite, local ONNX embeddings by default
  • Typed (13 categories) + full provenance (how it was learned, confidence, expiry)
  • Hard scope isolation — session/task/host is a filter applied before ranking, not a signal
  • Hybrid search (dense + BM25) with absolute, non-normalized relevance + optional reranking
  • Learns from your sessions — Claude Code hooks + OpenAI-proxy distillation, not just manual writes
  • Ingests notes, Obsidian vaults, and PDFs, with --watch for continuous sync
  • Web UI for browsing, searching, and editing memories
  • MCP + REST + OpenAI-compatible proxy, all from one daemon
  • Contradictions and corrections are edges, never deletes — old memories stay queryable
  • export / import / backup / restore for full portability

How it compares

memstrand Mem0 Cognee raw vector RAG
Local-first, no API keys ✅ OSS self-host option ✅ ✅
Typed memory schema ✅ 13 categories ✅ notes ✅ ontology ❌
Scope enforcement (hard filter) ✅ ❌ ❌ ❌
Graph + vector joint writes ✅ ✅ ✅ ❌
Contradictions as edges, not deletes ✅ ❌ ✅ ❌
Hybrid (dense + BM25) retrieval, built in ✅ — — ❌
One daemon shared across tools (MCP + REST + OpenAI proxy) ✅ — — ❌

How it works

flowchart LR
    Clients["Claude Code · Cursor · Open WebUI · scripts"] -->|MCP / REST / v1 proxy| Daemon["memstrand serve"]
    Daemon --> Vector[(Vector\nQdrant)]
    Daemon --> Graph[(Graph\nSQLite/Kuzu)]
    Daemon --> Keyword[(Keyword\nFTS5)]
    Daemon --> Session[(Session\nSQLite)]

Write (remember()) embeds once and writes vector+graph+keyword under one scope-aware content-hash id. Distill (improve()) extracts typed atoms from raw session turns via your local LLM and promotes them with supersedes/contradicts edges. Read (recall()) applies the hard scope filter first, then blends hybrid relevance with confidence, recency, provenance, and access frequency. Consolidate expires, decays, dedups, and replays on a schedule. Full detail, including the ranking formula and FSRS/Hebbian dynamics, in docs/architecture.md.

Docs

Acceptance test

Any memory system should pass these three before you trust it (rubric adapted from a Cognee ad, because it was right):

  1. Remember me in a brand-new chat without re-pasting anything.
  2. Search by meaning, not keywords.
  3. Connect facts across sessions — and don't leak facts across unrelated tasks (the Playwright test).

examples/quickstart.py runs all three against a persistent store; tests/test_memory_flow.py runs the same rubric in CI.

Roadmap

  • Typed schema, scoped retrieval, provenance ledger
  • Session-commit distillation (extract → dedup → judge → promote)
  • Graph neighbor hydration, Hebbian strengthen/decay, FSRS + replay consolidation
  • One daemon: MCP + REST + web UI + OpenAI-compatible memory-injecting proxy
  • Hybrid (dense + BM25) retrieval + optional cross-encoder reranking
  • Markdown/Obsidian/PDF ingestion with --watch
  • Claude Code hooks, export/import/backup/restore
  • Automated migration tooling from 0.1.x's working-directory layout — see CHANGELOG.md (good first issue)
  • Multi-user auth beyond a single shared bearer token (good first issue)

Contributions welcome — see CONTRIBUTING.md for dev setup, test philosophy, and how to add a store backend.

Acknowledgments

Standing on shoulders, with credit:

  • Memanto (moorcheh-ai/memanto) — the 13-category typed schema, provenance, and confidence model. Their product is cloud-only; this is the schema reimplemented local-first.
  • Cognee (topoteretes/cognee) — the pipeline patterns: fast session cache → distillation, joint graph+vector writes, contradictions as additive edges.
  • ZenBrain (zensation-ai/zenbrain) — per-fact FSRS, deterministic write routing, replay consolidation, Hebbian edges.
  • Mem0 — the ADD/UPDATE/DELETE/NONE extraction resolution pattern.

License

MIT — see LICENSE.


If memstrand saves you from re-explaining yourself to your agent, a ⭐ helps others find it.

Metadata

Release files for memstrand 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for memstrand 0.2.1
File Size Uploaded
memstrand-0.2.1.tar.gz 214.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for memstrand 0.2.1
File Interpreter ABI Platform
memstrand-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 310.1 kB

Release files / memstrand-0.2.1.tar.gz

Download URL memstrand-0.2.1.tar.gz
Size 214.0 kB
Tags Source
SHA-256 checksum
How to use checksums
24d736c68203dab3060d7cb25ee6fee2269fa93be83c488ddaf3d93b40b79be1
BLAKE2b-256 checksum
How to use checksums
130a382c8822a0bc8acf8966dccc8b457a4ab3894f6241a11bc88fd45d274200
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / memstrand-0.2.1-py3-none-any.whl

Download URL memstrand-0.2.1-py3-none-any.whl
Size 96.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dc76fb52d6528ad1fd019c05b0b78d94a453a5d67266031c0beb3c79c4d59522
BLAKE2b-256 checksum
How to use checksums
be8bff1bddd3614e594782912a097ab387d22acc731475b8051c51ffcac669cf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

1 release file

0.1.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page