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.
- mnemofish-0.2.0/.gitignore +17 -0
- mnemofish-0.2.0/DESIGN.md +294 -0
- mnemofish-0.2.0/LICENSE +21 -0
- mnemofish-0.2.0/PKG-INFO +243 -0
- mnemofish-0.2.0/README.md +209 -0
- mnemofish-0.2.0/docs/assets/logo.svg +142 -0
- mnemofish-0.2.0/docs/mcp.md +56 -0
- mnemofish-0.2.0/hooks/README.md +55 -0
- mnemofish-0.2.0/hooks/settings.example.json +17 -0
- mnemofish-0.2.0/pyproject.toml +54 -0
- mnemofish-0.2.0/src/mnemo/__init__.py +10 -0
- mnemofish-0.2.0/src/mnemo/cli.py +236 -0
- mnemofish-0.2.0/src/mnemo/config.py +32 -0
- mnemofish-0.2.0/src/mnemo/daily.py +29 -0
- mnemofish-0.2.0/src/mnemo/embed.py +50 -0
- mnemofish-0.2.0/src/mnemo/index.py +205 -0
- mnemofish-0.2.0/src/mnemo/note.py +75 -0
- mnemofish-0.2.0/src/mnemo/portability.py +126 -0
- mnemofish-0.2.0/src/mnemo/recall.py +71 -0
- mnemofish-0.2.0/src/mnemo/search.py +78 -0
- mnemofish-0.2.0/src/mnemo/server.py +94 -0
- mnemofish-0.2.0/src/mnemo/vault.py +68 -0
- mnemofish-0.2.0/src/mnemo/writer.py +128 -0
- mnemofish-0.2.0/tests/test_core.py +171 -0
- mnemofish-0.2.0/tests/test_f2.py +97 -0
- mnemofish-0.2.0/tests/test_f3_server.py +26 -0
- mnemofish-0.2.0/tests/test_f4_portability.py +108 -0
- mnemofish-0.2.0/tests/test_f5.py +76 -0
- mnemofish-0.2.0/tests/test_f6_marker.py +40 -0
- mnemofish-0.2.0/uv.lock +2128 -0
|
@@ -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.
|
mnemofish-0.2.0/LICENSE
ADDED
|
@@ -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.
|
mnemofish-0.2.0/PKG-INFO
ADDED
|
@@ -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
|
+
[](https://www.python.org/)
|
|
47
|
+
[](https://modelcontextprotocol.io/)
|
|
48
|
+
[](#license)
|
|
49
|
+
[](#status)
|
|
50
|
+
[](#contributing)
|
|
51
|
+
[](#)
|
|
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>
|