mnemofish 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ *.egg-info/
5
+ .pytest_cache/
6
+ dist/
7
+ build/
8
+ .venv/
9
+ venv/
10
+
11
+ # mnemo derived index (rebuildable — never commit)
12
+ .mnemo/
13
+ *.sqlite
14
+ *.sqlite-*
15
+
16
+ # embedding model cache
17
+ .cache/
@@ -0,0 +1,294 @@
1
+ # mnemo — Tasarım Dokümanı
2
+
3
+ > Çalışma adı: **mnemo** (Mnemosyne — hafıza). Değiştirilebilir.
4
+ > Bu dosya iç tasarım/çalışma dokümanıdır (Türkçe). Public README ayrıca İngilizce yazılacak.
5
+ > Durum: TASLAK v0.1 — scope dondurma aşaması.
6
+
7
+ Kişisel, projeler-arası, AI-arası **kalıcı hafıza (persistent memory)** sistemi.
8
+ Markdown vault üstünde çalışan bir **MCP memory server** + **CLI** + **Claude Code hook**'ları.
9
+
10
+ ---
11
+
12
+ ## 1. Problem
13
+
14
+ Mevcut hafıza araçları (ör. claude-mem) **depolamayı** çözüyor ama **geri-çağırmayı (retrieval)** çözmüyor.
15
+
16
+ > Yaşanan: "Kaydet" deniyor, kaydediliyor — ama AI doğru anıyı doğru anda **okumuyor**.
17
+
18
+ Asıl darboğaz: bilgiyi yazmak değil, **ilgili alt kümeyi doğru anda modelin context'ine otomatik enjekte etmek.**
19
+
20
+ İkinci problem: bilgi büyüdükçe token tüketimi ve bilgi kalabalığı artar. Her şeyi yüklemek sürdürülemez.
21
+
22
+ ---
23
+
24
+ ## 2. Temel İlkeler
25
+
26
+ 1. **Retrieval-first.** Sistem "yazma"ya değil, "doğru anıyı otomatik getirme"ye göre tasarlanır.
27
+ 2. **Push > Pull.** MCP tool (pull) modelin çağırmasını bekler — claude-mem'in patladığı yer. Gerçek otomasyon **hook** (push) ile: AI sormadan ilgili not context'e enjekte edilir.
28
+ 3. **Vault = tek kaynak.** Markdown dosyalar tek gerçek. Index (sqlite/embedding) türetilmiştir, her an silinip yeniden üretilebilir.
29
+ 4. **Sadece türetilemeyeni sakla.** Dosya ağacı/fonksiyon imzaları AI tarafından bulunabilir → saklama. Kararlar, ilişkiler, sözleşmeler, hatalar, niyet → sakla.
30
+ 5. **Harita önce, düğüm sonra.** Token'ı sabit tutmak için: önce küçük index (MOC) yüklenir, sadece ilgili atomik not genişletilir. Asla "her şey".
31
+ 6. **Atomik notlar.** Bir not = bir karar/gerçek/hata. Küçük → tek tek ucuz yüklenir, çakışma minimum, embedding chunking gereksiz.
32
+
33
+ ### Türetilebilir vs türetilemez
34
+
35
+ | AI kendi bulabilir (SAKLAMA) | AI bulamaz (SAKLA) |
36
+ |---|---|
37
+ | Dosya ağacı (`glob`) | Topoloji: ne nereye konuşuyor |
38
+ | Vendor kod (HAL/CMSIS, node_modules) | Ortak protokol/sözleşmeler |
39
+ | Fonksiyon imzaları | Neden bu karar alındı |
40
+ | Hangi dosya var | Şu an ne yapılıyor / gotcha / hatalar |
41
+
42
+ ---
43
+
44
+ ## 3. Mimari
45
+
46
+ **Çekirdek kütüphane + iki ön-yüz.** Bu ayrım belkemiğidir — auto-recall'ı mümkün kılar.
47
+
48
+ ```
49
+ ┌──────────────────────────────────────────┐
50
+ │ Vault (markdown + frontmatter) │ ← tek kaynak, Obsidian'da da düzenlenir
51
+ └───────────────────┬──────────────────────┘
52
+ │ parse (incremental, mtime/hash)
53
+ ┌──────────▼───────────┐
54
+ │ ÇEKİRDEK LİB │ index.sqlite (FTS5 + vektör)
55
+ │ parse / index / │ ← türetilmiş, .gitignore, rebuild
56
+ │ search / write │
57
+ └─────┬───────────┬────┘
58
+ ┌────────────▼──┐ ┌───▼─────────────────┐
59
+ │ CLI ön-yüz │ │ MCP ön-yüz │
60
+ │ (PUSH) │ │ (PULL) │
61
+ │ Claude hook │ │ tüm MCP-uyumlu AI │
62
+ │ oturum başı │ │ konuşma içi tool │
63
+ │ recall enjekte│ │ çağrısı │
64
+ └────────────────┘ └─────────────────────┘
65
+ ```
66
+
67
+ - **Çekirdek lib:** parse + index + search + write. Tek mantık burada.
68
+ - **CLI ön-yüz:** hook'lardan çağrılır (push). Oturum başında ilgili MOC + top-N notu basıp context'e enjekte eder. `mnemo search/write/init/sync/...`.
69
+ - **MCP ön-yüz:** aynı çekirdeği MCP tool'ları olarak sunar → Claude Code, Cursor ve diğer MCP istemcileri aynı aramayı kullanır.
70
+
71
+ ---
72
+
73
+ ## 4. Vault Yapısı
74
+
75
+ Vault düz bir klasör (= private GitHub reposu). Önerilen layout:
76
+
77
+ ```
78
+ my-memory/ ← private repo
79
+ ├── daily/ günlük notlar, todo, "bugün ne yaptım"
80
+ │ └── 2026-06-23.md
81
+ ├── projects/
82
+ │ └── <proje>/
83
+ │ ├── _moc.md proje haritası (Map of Content) — index notu
84
+ │ └── <atomik>.md tek karar/gerçek
85
+ ├── lessons/ hatalar, dersler (tag'le retrieval)
86
+ ├── protocol/ teknik sözleşmeler (ör. RF v2)
87
+ ├── reference/ kalıcı bilgi (URL, dashboard, ticket)
88
+ ├── .gitignore index.sqlite + .cache hariç
89
+ └── .mnemo/ (gitignore) index.sqlite, embedding cache
90
+ ```
91
+
92
+ `projects/`, `lessons/` vb. **sabit değil** — kullanıcı kendi taksonomisini kurabilir; sistem `type` frontmatter'a göre çalışır, klasör adına değil.
93
+
94
+ ---
95
+
96
+ ## 5. Not Şeması (frontmatter)
97
+
98
+ Her not = markdown + YAML frontmatter:
99
+
100
+ ```markdown
101
+ ---
102
+ id: 20260623-rf-uid-sequential # kararlı kimlik (tarih-slug)
103
+ type: decision # decision | lesson | daily | project | reference | note
104
+ title: RF güncellemesi sıralı yapılır
105
+ project: stm32-rf-ota # opsiyonel
106
+ tags: [rf, protocol, stm32]
107
+ created: 2026-06-23
108
+ updated: 2026-06-23
109
+ summary: Cihazlar tek tek güncellenir; eşzamanlı değil — sistem kilitlenmesini önler.
110
+ links: [20260623-rf-uid-identity] # [[wikilink]] de desteklenir
111
+ ---
112
+
113
+ Sıralı güncelleme: id1 biter, id2 başlar. Avantaj: tüm cihazlar aynı anda
114
+ bootloader'a düşmez, sistem ayakta kalır...
115
+ ```
116
+
117
+ - `summary` zorunlu ve **kısa** → index/MOC bunu gösterir, gövdeyi değil. Token disiplini buradan gelir.
118
+ - `type` retrieval filtresini sağlar (teknik görevde `daily` notları boğmaz).
119
+ - `links` ilişki grafiğini kurar (MOC + backlink + AI traversal).
120
+
121
+ ---
122
+
123
+ ## 6. MOC (Map of Content)
124
+
125
+ `_moc.md` = bir projenin/konunun **haritası**. Atomiklere link + tek satır özet.
126
+
127
+ ```markdown
128
+ ---
129
+ type: project
130
+ title: STM32 RF OTA — MOC
131
+ project: stm32-rf-ota
132
+ ---
133
+ # STM32 RF OTA
134
+
135
+ ## Kararlar
136
+ - [[20260623-rf-uid-identity]] — kimlik = 96-bit STM32 UID, hash yok
137
+ - [[20260623-rf-uid-sequential]] — güncelleme sıralı, eşzamanlı değil
138
+
139
+ ## Bileşenler
140
+ - Sender STM32 (RF gateway), PC Uploader (Python/Qt), MobileUploader (Flutter)
141
+ - Alıcılar: stpm, stpm_fc (bootloader) + app'leri
142
+
143
+ ## Açık işler
144
+ - [ ] DISCOVER_ACK 7→18 byte (UID) geçişi
145
+ ```
146
+
147
+ Recall akışı: **MOC önce yüklenir** → AI ilgili linki görür → sadece o atomik notu `get` ile açar. Vault 10.000 nota çıksa bile bir görev = 1 MOC + birkaç atomik.
148
+
149
+ ---
150
+
151
+ ## 7. Index Katmanı
152
+
153
+ - **Store:** vault markdown. **Index:** `.mnemo/index.sqlite` (atılabilir).
154
+ - **Lexical:** SQLite **FTS5** (keyword/tag araması, deterministik, model gerektirmez).
155
+ - **Semantic:** lokal embedding (sentence-transformers) → `sqlite-vec` ile vektör araması (paraphrase/eşanlam yakalar).
156
+ - **Hybrid:** FTS5 + vektör sonuçları birleştirilir (rerank).
157
+ - **Incremental:** dosya başına mtime/hash → sadece değişeni yeniden parse+embed. Tüm vault'u her seferinde işleme yok.
158
+ - **Embedding lokal:** API yok, offline, gizli. (API opsiyonel eklenebilir.)
159
+
160
+ ---
161
+
162
+ ## 8. Retrieval (token disiplini)
163
+
164
+ `search` **özet + path + skor** döndürür, **tam gövde değil.** Map-then-expand sözleşme seviyesinde gömülü.
165
+
166
+ ```
167
+ search("rf güncelleme sırası", type=decision, k=5)
168
+ → [{id, title, summary, path, score}, ...] # ~5 satır, ucuz
169
+ get(path) # sadece gerekirse tam gövde
170
+ ```
171
+
172
+ Böylece bilgi büyüdükçe görev başına token **sabit** kalır.
173
+
174
+ ---
175
+
176
+ ## 9. MCP Tool API
177
+
178
+ | Tool | Girdi | Çıktı | Not |
179
+ |---|---|---|---|
180
+ | `memory_search` | query, type?, project?, tags?, k=5 | özet+path+skor listesi | gövde DÖNMEZ |
181
+ | `memory_get` | path/id | tam not | on-demand |
182
+ | `memory_moc` | project | proje haritası | "harita" |
183
+ | `memory_write` | type, title, body, tags, links | yeni/güncellenmiş not | **yazmadan-önce-ara** (dedup) |
184
+ | `memory_link` | id_a, id_b | — | düğümleri bağla |
185
+
186
+ Notlar MCP **resource** olarak da sunulabilir (opsiyonel).
187
+
188
+ ---
189
+
190
+ ## 10. CLI Komutları
191
+
192
+ | Komut | İş |
193
+ |---|---|
194
+ | `mnemo init [--remote <github-url>]` | vault'u (git reposu olarak) kur |
195
+ | `mnemo reindex` | index'i sıfırdan kur (taşıma sonrası) |
196
+ | `mnemo search <query> [--type --project -k]` | hook/manuel arama |
197
+ | `mnemo write ...` | not ekle (dedup'lı) |
198
+ | `mnemo recall [--project]` | oturum-başı enjeksiyon bloğu üret (hook bunu basar) |
199
+ | `mnemo sync` | git pull + push |
200
+ | `mnemo clone <github-url>` | yeni makine: klonla + reindex |
201
+ | `mnemo export <file>` / `import <file>` | tek-parça taşıma (Drive vb.) |
202
+ | `mnemo compact` | dedup/çürüme temizliği |
203
+
204
+ ---
205
+
206
+ ## 11. Hook Akışı (Claude Code — PUSH)
207
+
208
+ Auto-recall'ı mümkün kılan kısım. `settings.json` hook'ları:
209
+
210
+ - **SessionStart:** `mnemo recall --project <cwd>` → ilgili MOC + son kararlar/dersler context'e enjekte edilir. AI **sormadan** geçmişi bilerek başlar.
211
+ - **UserPromptSubmit (opsiyonel):** prompt'tan keyword/embedding → top-N not enjekte (göreve özel recall).
212
+ - **Stop / SessionEnd:** oturumdan karar/hata/yapılanı çıkar → `mnemo write` (auto-capture, v3).
213
+
214
+ > Bu, claude-mem'in çözemediği "okuma döngüsü"nü kapatır.
215
+
216
+ ---
217
+
218
+ ## 12. Cross-AI
219
+
220
+ - **MCP-uyumlu** (Claude Code, Cursor, ...): aynı MCP server'a bağlanır → aynı arama/recall.
221
+ - **MCP-suz** (düz ChatGPT web vb.): MCP kullanamaz → ya `mnemo export` ile parça yapıştırma, ya vault'u elle okutma. Dürüst sınır.
222
+ - Store evrensel (markdown), retrieval-wiring araç-başına.
223
+
224
+ ---
225
+
226
+ ## 13. Taşınabilirlik — GitHub omurgası
227
+
228
+ - **Vault = private GitHub reposu.** Sadece markdown commit'lenir; `index.sqlite` + embedding cache `.gitignore`.
229
+ - **Yeni makine / yeni AI:** `mnemo clone <github-url>` → klonla + reindex → her şeyi bilerek gelir. ("Hafızayı çek.")
230
+ - **Avantaj:** versiyonlu bilgi (ne zaman öğrendim/değiştirdim), bedava sync, merge, yedek.
231
+ - **Drive/Dropbox:** opsiyonel; vault düz klasör olduğu için çalışır ama versiyon/merge vermez. `export/import` tek-parça taşıma için.
232
+ - Atomik notlar → git merge çakışması minimum.
233
+
234
+ ---
235
+
236
+ ## 14. Çürüme Önleme (claude-mem'in ölüm sebebi)
237
+
238
+ - **Yazmadan-önce-ara:** `write` önce benzer not arar; varsa yeni açmaz → günceller/ekler.
239
+ - **`compact`:** periyodik dedup + ölü link temizliği.
240
+ - **summary zorunlu:** her not özetlenebilir olmalı; özetlenemeyen not = kötü not.
241
+
242
+ ---
243
+
244
+ ## 15. Gizlilik / Güvenlik
245
+
246
+ - **İki repo, karıştırma:**
247
+ - **PUBLIC** (OSS): `mnemo` yazılımı. Generic, vault-path config, kişisel veri YOK.
248
+ - **PRIVATE**: kullanıcının vault'u (notlar, kararlar, hatalar).
249
+ - Araç remote'un **public** göründüğünü sezerse uyarır (notların yanlışlıkla yayınlanmasını önle).
250
+ - Lokal embedding → veri makineden çıkmaz (API opsiyonel ve açıkça opt-in).
251
+
252
+ ---
253
+
254
+ ## 16. Teknoloji
255
+
256
+ - **Dil:** Python. Dağıtım: `uvx` (npx kadar kolay).
257
+ - **Bağımlılıklar:** `mcp` (SDK), `python-frontmatter`, `sentence-transformers`, `sqlite-vec`, SQLite FTS5 (stdlib).
258
+ - **Store:** vault markdown + `.mnemo/index.sqlite` (sidecar, atılabilir).
259
+
260
+ ---
261
+
262
+ ## 17. İnşa Yol Haritası (bağımlılık sırası — hepsi tam sürümde)
263
+
264
+ | Faz | Çıktı | Kanıt | Durum |
265
+ |---|---|---|---|
266
+ | **F1 — Çekirdek** | parse + frontmatter + FTS5 + incremental index | `search` doğru notu döndürür | ✅ |
267
+ | **F2 — CLI + Hook** | `recall/search/write` + Claude SessionStart hook (push) | AI sormadan geçmişi bilerek başlar | ✅ |
268
+ | **F3 — MCP** | `memory_search/get/moc/write` server | Cursor/Claude aynı vault'ta arar | ✅ |
269
+ | **F4 — Taşıma** | `init/sync/clone/export/import` (GitHub) | yeni makinede klonla+reindex çalışır | ✅ |
270
+ | **F5 — Semantic + daily** | fastembed+sqlite-vec hybrid (RRF), içerik dedup, `daily` journaling | paraphrase araması FTS'in kaçırdığını bulur | ✅ |
271
+
272
+ F2 sonunda **okuma döngüsü kapandı** → claude-mem'i geçer. 24 test geçiyor.
273
+
274
+ **Embedding backend kararı (çözüldü):** fastembed (ONNX) + `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2` (384-dim, çok-dilli, Türkçe). torch yok → hafif/hızlı cold-start. SessionStart hook (`recall`) embedding YÜKLEMEZ (sadece SQL) → hızlı kalır; model yalnız `search/serve/write/reindex`'te lazy yüklenir.
275
+
276
+ **Sonraki (F5+ / opsiyonel):** transcript'ten otomatik yakalama (rot riski yüksek — bilerek ertelendi; şimdilik recall footer modeli `memory_write`'a yönlendiriyor), `compact` (dedup/ölü-link temizliği), MOC yarı-otomatik üretimi.
277
+
278
+ ---
279
+
280
+ ## 18. Kararlar + Açık Sorular
281
+
282
+ ### Verilen kararlar (2026-06-23)
283
+ 1. **Embedding modeli:** hız + kararlılık öncelik. Notlar **Türkçe** → çok-dilli MiniLM (`paraphrase-multilingual-MiniLM-L12-v2`) varsayılan. FTS5 keyword zaten dilden bağımsız; embedding katmanı çok-dilli.
284
+ 2. **Proje tespiti:** **git remote slug → yoksa klasör adı** fallback.
285
+ 3. **İsim:** `mnemo` kalır.
286
+
287
+ ### Açık (sonra)
288
+ - **Auto-capture tetiği:** her oturum sonu mu, commit'te mi, manuel onaylı mı? (F5)
289
+ - **MOC üretimi:** elle mi, yarı-otomatik mi (atomiklerden link toplama)? (F3+)
290
+ - **Embedding backend:** sentence-transformers (torch, ağır) vs ONNX/fastembed (hızlı cold-start — hook için önemli). F1'de modül pluggable; dağıtımda ONNX'e geçiş değerlendirilecek.
291
+
292
+ ---
293
+
294
+ > Sonraki adım: bu DESIGN onaylanınca → public repo iskeleti + `pyproject.toml` + F1 çekirdek.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Emir Furkan Sarı
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,243 @@
1
+ Metadata-Version: 2.4
2
+ Name: mnemofish
3
+ Version: 0.2.0
4
+ Summary: Persistent, portable, cross-AI memory over a markdown vault — with push-based auto-recall (MCP + CLI).
5
+ Project-URL: Homepage, https://github.com/Emirfs/mnemo
6
+ Project-URL: Repository, https://github.com/Emirfs/mnemo
7
+ Project-URL: Issues, https://github.com/Emirfs/mnemo/issues
8
+ Author: Emir Furkan Sarı
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai,auto-recall,claude,claude-code,llm,mcp,memory,model-context-protocol,obsidian,persistent-memory,rag
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Classifier: Topic :: Software Development :: Libraries
23
+ Classifier: Topic :: Text Processing :: Indexing
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: python-frontmatter>=1.1.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=8.0; extra == 'dev'
28
+ Provides-Extra: embed
29
+ Requires-Dist: fastembed>=0.4; extra == 'embed'
30
+ Requires-Dist: sqlite-vec>=0.1.6; extra == 'embed'
31
+ Provides-Extra: mcp
32
+ Requires-Dist: mcp>=1.2.0; extra == 'mcp'
33
+ Description-Content-Type: text/markdown
34
+
35
+ <div align="center">
36
+
37
+ <img src="https://raw.githubusercontent.com/Emirfs/mnemo/master/docs/assets/logo.svg" alt="mnemo pixel-art clownfish" width="220" />
38
+
39
+ # mnemo
40
+
41
+ ### Your AI has goldfish memory. 🐠 mnemo gives it an elephant's. 🐘
42
+
43
+ **Persistent, portable, cross-AI memory** over a plain markdown vault —
44
+ with **push-based auto-recall** so the model remembers your past work *without being asked.*
45
+
46
+ [![Python](https://img.shields.io/badge/python-3.10+-3776ab?logo=python&logoColor=white)](https://www.python.org/)
47
+ [![MCP](https://img.shields.io/badge/MCP-compatible-7c3aed)](https://modelcontextprotocol.io/)
48
+ [![License: MIT](https://img.shields.io/badge/license-MIT-22c55e.svg)](#license)
49
+ [![Tests](https://img.shields.io/badge/tests-28%20passing-22c55e.svg)](#status)
50
+ [![PRs welcome](https://img.shields.io/badge/PRs-welcome-ff8a3d.svg)](#contributing)
51
+ [![Vibe](https://img.shields.io/badge/just%20keep-swimming-1e90ff.svg)](#)
52
+
53
+ </div>
54
+
55
+ > [!NOTE]
56
+ > **P. Sherman, 42 Wallaby Way, Sydney.**
57
+ > Dory could *say* the address. She just couldn't *recall* it when it mattered.
58
+ > That's your AI. That's every memory tool that only does storage. mnemo is the one that remembers at the right moment.
59
+
60
+ ---
61
+
62
+ ## 🫧 The problem (you've lived this)
63
+
64
+ ```
65
+ You: "remember we decided X yesterday"
66
+ AI: "i have no memory of that, what is X"
67
+ You: *re-explains the entire project for the 9th time*
68
+ ```
69
+
70
+ New chat → instant amnesia. The decision from yesterday? Gone. The bug you already
71
+ killed? It's back, baby. The contract two repos share? Never heard of her.
72
+
73
+ Most "memory" tools only solve **storage** — they save notes the model never reads back.
74
+ Cool, you wrote down Nemo's address on a fridge he can't reach. 🧲 The actual hard part
75
+ is **retrieval**: getting the *right* memory into context at the *right* moment.
76
+
77
+ > Storage was never the hard part. **Retrieval is.** 🎯
78
+
79
+ ## 🐠 How mnemo keeps finding Nemo
80
+
81
+ Two currents. Same ocean.
82
+
83
+ | | | |
84
+ |---|---|---|
85
+ | **🌊 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 |
86
+ | **🪝 PULL — the net** | an MCP server lets any MCP-capable AI search the same vault mid-chat | Claude Code, Cursor, whatever — same brain |
87
+
88
+ Nemo never stays lost. *He just keeps swimming back.*
89
+
90
+ ## ✨ Why it actually slaps
91
+
92
+ - **🗂️ Vault = source of truth.** Plain markdown + YAML frontmatter. Edit it in Obsidian,
93
+ your editor, or a cave with a stick. The index (SQLite FTS5 + vectors) is *derived* and
94
+ rebuildable — never committed.
95
+ - **🧮 Map, then expand.** Search returns *summaries + paths*, not full bodies. Token cost
96
+ stays **flat** whether your vault has 10 notes or 10,000. Your context window stays unbothered.
97
+ - **🧠 Store only what can't be re-derived.** File trees and function signatures? The AI can
98
+ find those itself. Decisions, gotchas, contracts, *why-the-hell-did-we-do-it-this-way*? Saved.
99
+ - **🔍 Hybrid search.** Keyword (FTS5) **+** semantic (local embeddings, RRF-fused) — catches
100
+ the paraphrase keyword search fumbles. Runs **100% local**: offline, private, zero API spend.
101
+ - **🚚 Portable AF.** Your vault is a private git repo. New machine, new AI?
102
+ `mnemo clone <url>` → reindex → it knows everything. Memory that survives a laptop death.
103
+ - **🔗 Shared across repos.** Drop a `.mnemo-project` marker and many repos feed one project brain.
104
+
105
+ ## 🚀 Quick start
106
+
107
+ ```bash
108
+ # zero-install run (recommended)
109
+ uvx mnemofish --vault ./my-vault init
110
+
111
+ # or install it (ships the `mnemo` command)
112
+ pip install "mnemofish[embed,mcp]" # everything: semantic search + MCP server
113
+ pip install mnemofish # core only (FTS5 keyword search)
114
+ ```
115
+
116
+ > 📦 PyPI package is **`mnemofish`**; the CLI command is **`mnemo`** (the alias `mnemofish` also works).
117
+
118
+ <details>
119
+ <summary>From source (dev)</summary>
120
+
121
+ ```bash
122
+ uv venv
123
+ uv pip install -e ".[dev]" # core (FTS5 keyword search)
124
+ uv pip install -e ".[dev,embed,mcp]" # + semantic search + MCP server
125
+ ```
126
+ </details>
127
+
128
+ ```bash
129
+ uv run mnemo --vault ./my-vault init
130
+ uv run mnemo --vault ./my-vault write \
131
+ --type decision --title "RF update is sequential" \
132
+ --summary "Devices update one at a time, not concurrently — prevents system lockup."
133
+ uv run mnemo --vault ./my-vault search "rf update order"
134
+ uv run mnemo --vault ./my-vault daily "what I shipped today"
135
+ ```
136
+
137
+ ## 🪝 Auto-recall in 30 seconds
138
+
139
+ Wire the `SessionStart` hook and your AI greets you with the relevant Map of Content +
140
+ recent decisions — *automatically, every time.*
141
+
142
+ ```jsonc
143
+ // .claude/settings.json (full example: hooks/settings.example.json)
144
+ {
145
+ "hooks": {
146
+ "SessionStart": [
147
+ { "matcher": "startup", "hooks": [{
148
+ "type": "command",
149
+ "command": "mnemo --vault \"/path/to/my-memory\" recall --hook --reindex --project-dir \"$CLAUDE_PROJECT_DIR\""
150
+ }]}
151
+ ]
152
+ }
153
+ }
154
+ ```
155
+
156
+ For MCP clients, run the server and point your client at it:
157
+
158
+ ```bash
159
+ uv run mnemo --vault ./my-vault serve # exposes memory_search / get / moc / write
160
+ ```
161
+
162
+ ## 🧭 How it works
163
+
164
+ ```
165
+ ┌──────────────────────────────────────────┐
166
+ │ Vault (markdown + frontmatter) │ ← single source of truth (Obsidian-friendly)
167
+ └───────────────────┬──────────────────────┘
168
+ │ parse (incremental: mtime/hash)
169
+ ┌──────────▼───────────┐
170
+ │ CORE LIBRARY │ index.sqlite (FTS5 + vectors)
171
+ │ parse / index / │ ← derived, .gitignored, rebuildable
172
+ │ search / write │
173
+ └─────┬───────────┬────┘
174
+ ┌────────────▼──┐ ┌───▼─────────────────┐
175
+ │ CLI + hook │ │ MCP server │
176
+ │ (PUSH) │ │ (PULL) │
177
+ │ session-start │ │ any MCP-capable AI │
178
+ │ auto-recall │ │ in-chat tool calls │
179
+ └────────────────┘ └─────────────────────┘
180
+ ```
181
+
182
+ A task = **1 MOC + a few atomic notes**, no matter how big the vault gets. Flat tokens. 📉
183
+
184
+ ## 📓 A note looks like this
185
+
186
+ ```markdown
187
+ ---
188
+ id: 20260623-rf-uid-sequential
189
+ type: decision # decision | lesson | daily | project | reference | note
190
+ title: RF update is sequential
191
+ project: stm32-rf-ota
192
+ tags: [rf, protocol, stm32]
193
+ summary: Devices update one at a time, not concurrently — prevents system lockup.
194
+ links: [20260623-rf-uid-identity]
195
+ ---
196
+
197
+ Sequential update: id1 finishes, id2 begins. All devices don't drop into the
198
+ bootloader at once, so the system stays alive...
199
+ ```
200
+
201
+ `summary` is required and short — the index shows *that*, not the body. That's where the
202
+ token discipline comes from. (No `summary` = bad note. The fish judges you. 🐠)
203
+
204
+ ## 🛠️ Commands
205
+
206
+ | Command | What it does |
207
+ |---|---|
208
+ | `init` / `sync` / `clone` | manage the vault as a private git repo |
209
+ | `write` / `daily` | add notes (deduped) / append journal entries |
210
+ | `search` / `get` | hybrid search (summaries) / fetch one full note |
211
+ | `reindex` | rebuild the derived index from scratch |
212
+ | `recall --hook` | emit the SessionStart recall block (push) |
213
+ | `serve` | run the MCP server (pull, cross-AI) |
214
+ | `export` / `import` | zip the vault for one-shot transfer (Drive, etc.) |
215
+
216
+ ## 📊 Status
217
+
218
+ Working. **F1–F6 shipped, 28 tests green.** ✅ See [`DESIGN.md`](./DESIGN.md) for
219
+ architecture and roadmap.
220
+
221
+ - **F1** — core: markdown/frontmatter parse, FTS5, incremental index
222
+ - **F2** — `recall` + `write` + SessionStart hook (push auto-recall) — [`hooks/`](./hooks)
223
+ - **F3** — MCP server (`memory_search/get/moc/write`) — [`docs/mcp.md`](./docs/mcp.md)
224
+ - **F4** — portability: `init` / `sync` / `clone` / `export` / `import`
225
+ - **F5** — semantic hybrid search (fastembed + sqlite-vec, RRF), content dedup, `daily` journaling
226
+ - **F6** — `.mnemo-project` marker for shared cross-repo project memory
227
+
228
+ ## 🔒 Privacy
229
+
230
+ Two repos, never mixed: the **public** one is this software (generic, zero personal data);
231
+ your **private** one is your vault. Embeddings run locally, so your notes never leave your
232
+ machine. 🏠 (API embeddings are opt-in only.)
233
+
234
+ ## 🤝 Contributing
235
+
236
+ PRs and issues welcome. Small Python codebase — `core library + two frontends`.
237
+ Run the suite with `pytest`, keep notes atomic, and *just keep swimming.* 🐠
238
+
239
+ ## License
240
+
241
+ [MIT](#license) © Emir Furkan Sarı
242
+
243
+ <div align="center"><sub><i>mnemo /ˈniːmoʊ/ — from Mnemosyne (memory) ⋅ also a small orange fish who refuses to be forgotten.</i></sub></div>