Skip to main content

Persistent, portable, cross-AI memory over a markdown vault — with push-based auto-recall (MCP + CLI).

Project description

mnemo pixel-art clownfish

mnemo

Your AI has goldfish memory. 🐠 mnemo gives it an elephant's. 🐘

Persistent, portable, cross-AI memory over a plain markdown vault — with push-based auto-recall so the model remembers your past work without being asked.

Python MCP License: MIT Tests PRs welcome Vibe

[!NOTE] P. Sherman, 42 Wallaby Way, Sydney. Dory could say the address. She just couldn't recall it when it mattered. That's your AI. That's every memory tool that only does storage. mnemo is the one that remembers at the right moment.


🫧 The problem (you've lived this)

You:  "remember we decided X yesterday"
AI:   "i have no memory of that, what is X"
You:  *re-explains the entire project for the 9th time*

New chat → instant amnesia. The decision from yesterday? Gone. The bug you already killed? It's back, baby. The contract two repos share? Never heard of her.

Most "memory" tools only solve storage — they save notes the model never reads back. Cool, you wrote down Nemo's address on a fridge he can't reach. 🧲 The actual hard part is retrieval: getting the right memory into context at the right moment.

Storage was never the hard part. Retrieval is. 🎯

🐠 How mnemo keeps finding Nemo

Two currents. Same ocean.

🌊 PUSH — the rescue a SessionStart hook injects the relevant notes into context before you type a word the AI starts every session already knowing your history
🪝 PULL — the net an MCP server lets any MCP-capable AI search the same vault mid-chat Claude Code, Cursor, whatever — same brain

Nemo never stays lost. He just keeps swimming back.

✨ Why it actually slaps

  • 🗂️ Vault = source of truth. Plain markdown + YAML frontmatter. Edit it in Obsidian, your editor, or a cave with a stick. The index (SQLite FTS5 + vectors) is derived and rebuildable — never committed.
  • 🧮 Map, then expand. Search returns summaries + paths, not full bodies. Token cost stays flat whether your vault has 10 notes or 10,000. Your context window stays unbothered.
  • 🧠 Store only what can't be re-derived. File trees and function signatures? The AI can find those itself. Decisions, gotchas, contracts, why-the-hell-did-we-do-it-this-way? Saved.
  • 🔍 Hybrid search. Keyword (FTS5) + semantic (local embeddings, RRF-fused) — catches the paraphrase keyword search fumbles. Runs 100% local: offline, private, zero API spend.
  • 🚚 Portable AF. Your vault is a private git repo. New machine, new AI? mnemo clone <url> → reindex → it knows everything. Memory that survives a laptop death.
  • 🔗 Shared across repos. Drop a .mnemo-project marker and many repos feed one project brain.

🚀 Quick start

# zero-install run (recommended)
uvx mnemofish --vault ./my-vault init

# or install it (ships the `mnemo` command)
pip install "mnemofish[embed,mcp]"    # everything: semantic search + MCP server
pip install mnemofish                  # core only (FTS5 keyword search)

📦 PyPI package is mnemofish; the CLI command is mnemo (the alias mnemofish also works).

From source (dev)
uv venv
uv pip install -e ".[dev]"            # core (FTS5 keyword search)
uv pip install -e ".[dev,embed,mcp]"  # + semantic search + MCP server
uv run mnemo --vault ./my-vault init
uv run mnemo --vault ./my-vault write \
  --type decision --title "RF update is sequential" \
  --summary "Devices update one at a time, not concurrently — prevents system lockup."
uv run mnemo --vault ./my-vault search "rf update order"
uv run mnemo --vault ./my-vault daily "what I shipped today"

🪝 Auto-recall in 30 seconds

Wire the SessionStart hook and your AI greets you with the relevant Map of Content + recent decisions — automatically, every time.

// .claude/settings.json  (full example: hooks/settings.example.json)
{
  "hooks": {
    "SessionStart": [
      { "matcher": "startup", "hooks": [{
        "type": "command",
        "command": "mnemo --vault \"/path/to/my-memory\" recall --hook --reindex --project-dir \"$CLAUDE_PROJECT_DIR\""
      }]}
    ]
  }
}

For MCP clients, run the server and point your client at it:

uv run mnemo --vault ./my-vault serve   # exposes memory_search / get / moc / write

🧭 How it works

        ┌──────────────────────────────────────────┐
        │  Vault (markdown + frontmatter)          │  ← single source of truth (Obsidian-friendly)
        └───────────────────┬──────────────────────┘
                            │ parse (incremental: mtime/hash)
                 ┌──────────▼───────────┐
                 │   CORE LIBRARY       │   index.sqlite (FTS5 + vectors)
                 │  parse / index /     │   ← derived, .gitignored, rebuildable
                 │  search / write      │
                 └─────┬───────────┬────┘
          ┌────────────▼──┐    ┌───▼─────────────────┐
          │  CLI + hook    │    │   MCP server         │
          │  (PUSH)        │    │   (PULL)             │
          │  session-start │    │   any MCP-capable AI │
          │  auto-recall   │    │   in-chat tool calls │
          └────────────────┘    └─────────────────────┘

A task = 1 MOC + a few atomic notes, no matter how big the vault gets. Flat tokens. 📉

📓 A note looks like this

---
id: 20260623-rf-uid-sequential
type: decision           # decision | lesson | daily | project | reference | note
title: RF update is sequential
project: stm32-rf-ota
tags: [rf, protocol, stm32]
summary: Devices update one at a time, not concurrently — prevents system lockup.
links: [20260623-rf-uid-identity]
---

Sequential update: id1 finishes, id2 begins. All devices don't drop into the
bootloader at once, so the system stays alive...

summary is required and short — the index shows that, not the body. That's where the token discipline comes from. (No summary = bad note. The fish judges you. 🐠)

🛠️ Commands

Command What it does
init / sync / clone manage the vault as a private git repo
write / daily add notes (deduped) / append journal entries
search / get hybrid search (summaries) / fetch one full note
reindex rebuild the derived index from scratch
recall --hook emit the SessionStart recall block (push)
serve run the MCP server (pull, cross-AI)
export / import zip the vault for one-shot transfer (Drive, etc.)

📊 Status

Working. F1–F6 shipped, 28 tests green. ✅ See DESIGN.md for architecture and roadmap.

  • F1 — core: markdown/frontmatter parse, FTS5, incremental index
  • F2recall + write + SessionStart hook (push auto-recall) — hooks/
  • F3 — MCP server (memory_search/get/moc/write) — docs/mcp.md
  • F4 — portability: init / sync / clone / export / import
  • F5 — semantic hybrid search (fastembed + sqlite-vec, RRF), content dedup, daily journaling
  • F6.mnemo-project marker for shared cross-repo project memory

🔒 Privacy

Two repos, never mixed: the public one is this software (generic, zero personal data); your private one is your vault. Embeddings run locally, so your notes never leave your machine. 🏠 (API embeddings are opt-in only.)

🤝 Contributing

PRs and issues welcome. Small Python codebase — core library + two frontends. Run the suite with pytest, keep notes atomic, and just keep swimming. 🐠

License

MIT © Emir Furkan Sarı

mnemo /ˈniːmoʊ/ — from Mnemosyne (memory) ⋅ also a small orange fish who refuses to be forgotten.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mnemofish-0.2.0.tar.gz (168.4 kB view details)

Uploaded Source

Built Distribution

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

mnemofish-0.2.0-py3-none-any.whl (23.5 kB view details)

Uploaded Python 3

File details

Details for the file mnemofish-0.2.0.tar.gz.

File metadata

  • Download URL: mnemofish-0.2.0.tar.gz
  • Upload date:
  • Size: 168.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.5 {"installer":{"name":"uv","version":"0.11.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mnemofish-0.2.0.tar.gz
Algorithm Hash digest
SHA256 bf9bdb655c88e1584a4d7141f599c7015d8bdb3fefdc771093000f2b5d568d58
MD5 ee81a001178b63a411b0bdc3b2b4268b
BLAKE2b-256 2fcb9c36f1169287160ab27aed6260cbe3aec018afb5afd5cf9a83b404443314

See more details on using hashes here.

File details

Details for the file mnemofish-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: mnemofish-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 23.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.5 {"installer":{"name":"uv","version":"0.11.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mnemofish-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7b5255271718bc7996185e6eecd89aa7ef7d9d5487443b64bb1db9c0d213f45d
MD5 77a64a4ecaf922ee5c8ebe00f626ac2c
BLAKE2b-256 99185506063132638abcad95baf025afcf8014a9a2c2bb1e44b16fab1c2af48f

See more details on using hashes here.

Supported by

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