nano-brain 2026.7.13 → 2026.7.102
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.
- package/README.md +399 -902
- package/npm/postinstall.js +308 -0
- package/npm/postinstall.test.js +345 -0
- package/npm/run.js +41 -0
- package/package.json +24 -49
- package/.opencode/command/nano-brain-init.md +0 -47
- package/.opencode/command/nano-brain-reindex.md +0 -56
- package/.opencode/command/nano-brain-status.md +0 -49
- package/.opencode/command/opsx-apply.md +0 -149
- package/.opencode/command/opsx-archive.md +0 -154
- package/.opencode/command/opsx-explore.md +0 -170
- package/.opencode/command/opsx-propose.md +0 -103
- package/.opencode/skills/openspec-apply-change/SKILL.md +0 -156
- package/.opencode/skills/openspec-archive-change/SKILL.md +0 -114
- package/.opencode/skills/openspec-explore/SKILL.md +0 -288
- package/.opencode/skills/openspec-propose/SKILL.md +0 -110
- package/AGENTS.md +0 -90
- package/AGENTS_SNIPPET.md +0 -48
- package/SKILL.md +0 -145
- package/bin/cli.js +0 -48
- package/config.default.yml +0 -34
- package/dist/bandits.d.ts +0 -36
- package/dist/bandits.d.ts.map +0 -1
- package/dist/bandits.js +0 -117
- package/dist/bandits.js.map +0 -1
- package/dist/bench.d.ts +0 -3
- package/dist/bench.d.ts.map +0 -1
- package/dist/bench.js +0 -897
- package/dist/bench.js.map +0 -1
- package/dist/cache.d.ts +0 -20
- package/dist/cache.d.ts.map +0 -1
- package/dist/cache.js +0 -44
- package/dist/cache.js.map +0 -1
- package/dist/categorizer.d.ts +0 -2
- package/dist/categorizer.d.ts.map +0 -1
- package/dist/categorizer.js +0 -56
- package/dist/categorizer.js.map +0 -1
- package/dist/chunker.d.ts +0 -15
- package/dist/chunker.d.ts.map +0 -1
- package/dist/chunker.js +0 -464
- package/dist/chunker.js.map +0 -1
- package/dist/codebase.d.ts +0 -48
- package/dist/codebase.d.ts.map +0 -1
- package/dist/codebase.js +0 -725
- package/dist/codebase.js.map +0 -1
- package/dist/collections.d.ts +0 -27
- package/dist/collections.d.ts.map +0 -1
- package/dist/collections.js +0 -213
- package/dist/collections.js.map +0 -1
- package/dist/connection-graph.d.ts +0 -13
- package/dist/connection-graph.d.ts.map +0 -1
- package/dist/connection-graph.js +0 -37
- package/dist/connection-graph.js.map +0 -1
- package/dist/consolidation-worker.d.ts +0 -23
- package/dist/consolidation-worker.d.ts.map +0 -1
- package/dist/consolidation-worker.js +0 -93
- package/dist/consolidation-worker.js.map +0 -1
- package/dist/consolidation.d.ts +0 -56
- package/dist/consolidation.d.ts.map +0 -1
- package/dist/consolidation.js +0 -363
- package/dist/consolidation.js.map +0 -1
- package/dist/db/corruption-recovery.d.ts +0 -85
- package/dist/db/corruption-recovery.d.ts.map +0 -1
- package/dist/db/corruption-recovery.js +0 -217
- package/dist/db/corruption-recovery.js.map +0 -1
- package/dist/embeddings.d.ts +0 -29
- package/dist/embeddings.d.ts.map +0 -1
- package/dist/embeddings.js +0 -419
- package/dist/embeddings.js.map +0 -1
- package/dist/entity-extraction.d.ts +0 -21
- package/dist/entity-extraction.d.ts.map +0 -1
- package/dist/entity-extraction.js +0 -93
- package/dist/entity-extraction.js.map +0 -1
- package/dist/entity-merger.d.ts +0 -25
- package/dist/entity-merger.d.ts.map +0 -1
- package/dist/entity-merger.js +0 -191
- package/dist/entity-merger.js.map +0 -1
- package/dist/event-store.d.ts +0 -16
- package/dist/event-store.d.ts.map +0 -1
- package/dist/event-store.js +0 -58
- package/dist/event-store.js.map +0 -1
- package/dist/expansion.d.ts +0 -12
- package/dist/expansion.d.ts.map +0 -1
- package/dist/expansion.js +0 -42
- package/dist/expansion.js.map +0 -1
- package/dist/extraction.d.ts +0 -23
- package/dist/extraction.d.ts.map +0 -1
- package/dist/extraction.js +0 -173
- package/dist/extraction.js.map +0 -1
- package/dist/flow-detection.d.ts +0 -31
- package/dist/flow-detection.d.ts.map +0 -1
- package/dist/flow-detection.js +0 -173
- package/dist/flow-detection.js.map +0 -1
- package/dist/fts-client.d.ts +0 -7
- package/dist/fts-client.d.ts.map +0 -1
- package/dist/fts-client.js +0 -119
- package/dist/fts-client.js.map +0 -1
- package/dist/fts-worker.d.ts +0 -2
- package/dist/fts-worker.d.ts.map +0 -1
- package/dist/fts-worker.js +0 -206
- package/dist/fts-worker.js.map +0 -1
- package/dist/graph.d.ts +0 -26
- package/dist/graph.d.ts.map +0 -1
- package/dist/graph.js +0 -581
- package/dist/graph.js.map +0 -1
- package/dist/harvester.d.ts +0 -51
- package/dist/harvester.d.ts.map +0 -1
- package/dist/harvester.js +0 -696
- package/dist/harvester.js.map +0 -1
- package/dist/host.d.ts +0 -3
- package/dist/host.d.ts.map +0 -1
- package/dist/host.js +0 -30
- package/dist/host.js.map +0 -1
- package/dist/importance.d.ts +0 -21
- package/dist/importance.d.ts.map +0 -1
- package/dist/importance.js +0 -74
- package/dist/importance.js.map +0 -1
- package/dist/index.d.ts +0 -22
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -3673
- package/dist/index.js.map +0 -1
- package/dist/intent-classifier.d.ts +0 -16
- package/dist/intent-classifier.d.ts.map +0 -1
- package/dist/intent-classifier.js +0 -41
- package/dist/intent-classifier.js.map +0 -1
- package/dist/llm-categorizer.d.ts +0 -12
- package/dist/llm-categorizer.d.ts.map +0 -1
- package/dist/llm-categorizer.js +0 -75
- package/dist/llm-categorizer.js.map +0 -1
- package/dist/llm-provider.d.ts +0 -35
- package/dist/llm-provider.d.ts.map +0 -1
- package/dist/llm-provider.js +0 -115
- package/dist/llm-provider.js.map +0 -1
- package/dist/logger.d.ts +0 -22
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -134
- package/dist/logger.js.map +0 -1
- package/dist/memory-graph.d.ts +0 -25
- package/dist/memory-graph.d.ts.map +0 -1
- package/dist/memory-graph.js +0 -156
- package/dist/memory-graph.js.map +0 -1
- package/dist/metrics.d.ts +0 -52
- package/dist/metrics.d.ts.map +0 -1
- package/dist/metrics.js +0 -79
- package/dist/metrics.js.map +0 -1
- package/dist/preference-model.d.ts +0 -17
- package/dist/preference-model.d.ts.map +0 -1
- package/dist/preference-model.js +0 -106
- package/dist/preference-model.js.map +0 -1
- package/dist/providers/qdrant.d.ts +0 -26
- package/dist/providers/qdrant.d.ts.map +0 -1
- package/dist/providers/qdrant.js +0 -235
- package/dist/providers/qdrant.js.map +0 -1
- package/dist/providers/sqlite-vec.d.ts +0 -17
- package/dist/providers/sqlite-vec.d.ts.map +0 -1
- package/dist/providers/sqlite-vec.js +0 -200
- package/dist/providers/sqlite-vec.js.map +0 -1
- package/dist/pruning.d.ts +0 -21
- package/dist/pruning.d.ts.map +0 -1
- package/dist/pruning.js +0 -53
- package/dist/pruning.js.map +0 -1
- package/dist/reranker.d.ts +0 -12
- package/dist/reranker.d.ts.map +0 -1
- package/dist/reranker.js +0 -74
- package/dist/reranker.js.map +0 -1
- package/dist/search.d.ts +0 -75
- package/dist/search.d.ts.map +0 -1
- package/dist/search.js +0 -563
- package/dist/search.js.map +0 -1
- package/dist/sequence-analyzer.d.ts +0 -51
- package/dist/sequence-analyzer.d.ts.map +0 -1
- package/dist/sequence-analyzer.js +0 -360
- package/dist/sequence-analyzer.js.map +0 -1
- package/dist/server.d.ts +0 -79
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -3739
- package/dist/server.js.map +0 -1
- package/dist/service-installer.d.ts +0 -25
- package/dist/service-installer.d.ts.map +0 -1
- package/dist/service-installer.js +0 -220
- package/dist/service-installer.js.map +0 -1
- package/dist/storage.d.ts +0 -17
- package/dist/storage.d.ts.map +0 -1
- package/dist/storage.js +0 -232
- package/dist/storage.js.map +0 -1
- package/dist/store.d.ts +0 -44
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js +0 -3130
- package/dist/store.js.map +0 -1
- package/dist/symbol-graph.d.ts +0 -167
- package/dist/symbol-graph.d.ts.map +0 -1
- package/dist/symbol-graph.js +0 -465
- package/dist/symbol-graph.js.map +0 -1
- package/dist/symbols.d.ts +0 -13
- package/dist/symbols.d.ts.map +0 -1
- package/dist/symbols.js +0 -474
- package/dist/symbols.js.map +0 -1
- package/dist/telemetry.d.ts +0 -24
- package/dist/telemetry.d.ts.map +0 -1
- package/dist/telemetry.js +0 -95
- package/dist/telemetry.js.map +0 -1
- package/dist/treesitter.d.ts +0 -44
- package/dist/treesitter.d.ts.map +0 -1
- package/dist/treesitter.js +0 -730
- package/dist/treesitter.js.map +0 -1
- package/dist/types.d.ts +0 -818
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -204
- package/dist/types.js.map +0 -1
- package/dist/vector-store.d.ts +0 -50
- package/dist/vector-store.d.ts.map +0 -1
- package/dist/vector-store.js +0 -23
- package/dist/vector-store.js.map +0 -1
- package/dist/wake-up.d.ts +0 -20
- package/dist/wake-up.d.ts.map +0 -1
- package/dist/wake-up.js +0 -81
- package/dist/wake-up.js.map +0 -1
- package/dist/watcher.d.ts +0 -61
- package/dist/watcher.d.ts.map +0 -1
- package/dist/watcher.js +0 -777
- package/dist/watcher.js.map +0 -1
- package/dist/web/assets/index-Dh0GlmPP.css +0 -1
- package/dist/web/assets/index-IH5W4yGw.js +0 -236
- package/dist/web/index.html +0 -13
- package/dist/web/src/api/client.d.ts +0 -180
- package/dist/web/src/api/client.d.ts.map +0 -1
- package/dist/web/src/api/client.js +0 -65
- package/dist/web/src/api/client.js.map +0 -1
- package/dist/web/src/lib/colors.d.ts +0 -21
- package/dist/web/src/lib/colors.d.ts.map +0 -1
- package/dist/web/src/lib/colors.js +0 -70
- package/dist/web/src/lib/colors.js.map +0 -1
- package/dist/web/src/lib/graph-adapter.d.ts +0 -35
- package/dist/web/src/lib/graph-adapter.d.ts.map +0 -1
- package/dist/web/src/lib/graph-adapter.js +0 -308
- package/dist/web/src/lib/graph-adapter.js.map +0 -1
- package/dist/web/src/store/app.d.ts +0 -7
- package/dist/web/src/store/app.d.ts.map +0 -1
- package/dist/web/src/store/app.js +0 -6
- package/dist/web/src/store/app.js.map +0 -1
- package/dist/web/vite.config.d.ts +0 -3
- package/dist/web/vite.config.d.ts.map +0 -1
- package/dist/web/vite.config.js +0 -18
- package/dist/web/vite.config.js.map +0 -1
- package/dist/workspace-profile.d.ts +0 -26
- package/dist/workspace-profile.d.ts.map +0 -1
- package/dist/workspace-profile.js +0 -51
- package/dist/workspace-profile.js.map +0 -1
- package/docker-compose.yml +0 -59
- package/opencode-mcp.json +0 -9
- package/src/bandits.ts +0 -144
- package/src/bench.ts +0 -1133
- package/src/cache.ts +0 -59
- package/src/categorizer.ts +0 -61
- package/src/chunker.ts +0 -553
- package/src/codebase.ts +0 -876
- package/src/collections.ts +0 -279
- package/src/connection-graph.ts +0 -50
- package/src/consolidation-worker.ts +0 -109
- package/src/consolidation.ts +0 -436
- package/src/db/corruption-recovery.ts +0 -285
- package/src/embeddings.ts +0 -490
- package/src/entity-extraction.ts +0 -124
- package/src/entity-merger.ts +0 -267
- package/src/event-store.ts +0 -75
- package/src/expansion.ts +0 -61
- package/src/extraction.ts +0 -234
- package/src/flow-detection.ts +0 -250
- package/src/fts-client.ts +0 -138
- package/src/fts-worker.ts +0 -238
- package/src/graph.ts +0 -710
- package/src/harvester.ts +0 -858
- package/src/host.ts +0 -31
- package/src/importance.ts +0 -101
- package/src/index.ts +0 -3988
- package/src/intent-classifier.ts +0 -56
- package/src/llm-categorizer.ts +0 -99
- package/src/llm-provider.ts +0 -140
- package/src/logger.ts +0 -141
- package/src/memory-graph.ts +0 -192
- package/src/metrics.ts +0 -98
- package/src/preference-model.ts +0 -142
- package/src/providers/qdrant.ts +0 -281
- package/src/providers/sqlite-vec.ts +0 -227
- package/src/pruning.ts +0 -83
- package/src/reranker.ts +0 -104
- package/src/search.ts +0 -758
- package/src/sequence-analyzer.ts +0 -422
- package/src/server.ts +0 -4167
- package/src/storage.ts +0 -269
- package/src/store.ts +0 -3648
- package/src/symbol-graph.ts +0 -704
- package/src/symbols.ts +0 -556
- package/src/telemetry.ts +0 -105
- package/src/treesitter.ts +0 -861
- package/src/types.ts +0 -921
- package/src/vector-store.ts +0 -84
- package/src/wake-up.ts +0 -122
- package/src/watcher.ts +0 -874
- package/src/web/index.html +0 -12
- package/src/web/package-lock.json +0 -3209
- package/src/web/package.json +0 -36
- package/src/web/src/App.tsx +0 -29
- package/src/web/src/api/client.ts +0 -233
- package/src/web/src/components/EntityDetailPanel.tsx +0 -94
- package/src/web/src/components/ErrorBoundary.tsx +0 -49
- package/src/web/src/components/Layout.tsx +0 -99
- package/src/web/src/components/NodeDetail.tsx +0 -27
- package/src/web/src/components/QueryStatus.tsx +0 -65
- package/src/web/src/components/ReactFlowGraph.tsx +0 -112
- package/src/web/src/components/SearchResult.tsx +0 -44
- package/src/web/src/components/Skeleton.tsx +0 -45
- package/src/web/src/components/nodes/DocumentNode.tsx +0 -31
- package/src/web/src/components/nodes/EntityNode.tsx +0 -43
- package/src/web/src/components/nodes/FileNode.tsx +0 -33
- package/src/web/src/components/nodes/SymbolNode.tsx +0 -37
- package/src/web/src/index.css +0 -81
- package/src/web/src/lib/colors.ts +0 -83
- package/src/web/src/lib/graph-adapter.ts +0 -349
- package/src/web/src/main.tsx +0 -29
- package/src/web/src/store/app.ts +0 -11
- package/src/web/src/views/CodeGraph.tsx +0 -109
- package/src/web/src/views/ConnectionsView.tsx +0 -217
- package/src/web/src/views/Dashboard.tsx +0 -159
- package/src/web/src/views/FlowsView.tsx +0 -191
- package/src/web/src/views/GraphExplorer.tsx +0 -198
- package/src/web/src/views/InfrastructureView.tsx +0 -199
- package/src/web/src/views/Search.tsx +0 -82
- package/src/web/src/views/SymbolGraph.tsx +0 -134
- package/src/web/tsconfig.json +0 -20
- package/src/web/tsconfig.tsbuildinfo +0 -1
- package/src/web/vite.config.ts +0 -18
- package/src/workspace-profile.ts +0 -64
package/README.md
CHANGED
|
@@ -1,1064 +1,561 @@
|
|
|
1
1
|
# nano-brain
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Built for agents. Not humans.**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
A persistent memory server for AI coding agents. It solves the #1 problem with AI assistants: **they forget everything between sessions.**
|
|
5
|
+
Agent-oriented memory and code intelligence. AI agents don't read docs — they need structured context, impact analysis, and call chains. nano-brain provides exactly that via MCP.
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
[](https://go.dev/)
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://github.com/nano-step/nano-brain)
|
|
10
|
+
[](https://www.npmjs.com/package/@nano-step/nano-brain)
|
|
11
|
+
[](https://hub.docker.com/r/nano-step/nano-brain)
|
|
12
|
+
[](https://discord.gg/nano-brain)
|
|
10
13
|
|
|
11
|
-
## Key Features
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
- **Code intelligence** — symbol graph, call flow detection, impact analysis, change detection via Tree-sitter AST
|
|
15
|
-
- **Automatic data ingestion** — session harvesting (2min poll), file watching (chokidar), codebase indexing
|
|
16
|
-
- **Multi-workspace isolation** — per-workspace SQLite databases, cross-workspace search with `--scope=all`
|
|
17
|
-
- **Flexible embedding providers** — VoyageAI, Ollama, OpenAI-compatible
|
|
18
|
-
- **Dual vector stores** — Qdrant (production) or sqlite-vec (embedded)
|
|
19
|
-
- **Privacy-first** — 100% local processing option, your code never leaves your machine
|
|
20
|
-
- **MCP + CLI** — stdio/HTTP/SSE transports for local or containerized environments
|
|
21
|
-
- **Automatic corruption recovery** — detects & recovers from database corruption on startup with zero user intervention
|
|
22
|
-
- **Self-learning system** — Thompson Sampling tunes search parameters, preference learning personalizes results
|
|
23
|
-
- **Knowledge graph** — LLM-extracted entities and relationships, graph traversal, temporal queries
|
|
24
|
-
- **Memory intelligence** — LLM categorization, entity pruning, proactive suggestions
|
|
25
|
-
|
|
26
|
-
Inspired by [QMD](https://github.com/tobi/qmd) and [OpenClaw](https://github.com/openclaw/openclaw).
|
|
15
|
+
### Install
|
|
27
16
|
|
|
28
|
-
|
|
17
|
+
```bash
|
|
18
|
+
# Via npm (recommended)
|
|
19
|
+
npm install -g @nano-step/nano-brain
|
|
29
20
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
│
|
|
33
|
-
▼
|
|
34
|
-
┌─────────────────┐
|
|
35
|
-
│ Query Expansion │ ← (currently stubbed, planned)
|
|
36
|
-
│ (optional) │ generates 2-3 query variants
|
|
37
|
-
└────────┬────────┘
|
|
38
|
-
│
|
|
39
|
-
┌────┴────┐
|
|
40
|
-
▼ ▼
|
|
41
|
-
┌────────┐ ┌──────────┐
|
|
42
|
-
│ BM25 │ │ Vector │
|
|
43
|
-
│ (FTS5) │ │ (Qdrant │
|
|
44
|
-
│ │ │ or │
|
|
45
|
-
│ │ │ sqlite- │
|
|
46
|
-
│ │ │ vec) │
|
|
47
|
-
└───┬────┘ └────┬─────┘
|
|
48
|
-
│ │
|
|
49
|
-
▼ ▼
|
|
50
|
-
┌─────────────────┐
|
|
51
|
-
│ RRF Fusion │ ← k=60, original query 2× weight
|
|
52
|
-
│ │
|
|
53
|
-
└────────┬────────┘
|
|
54
|
-
│
|
|
55
|
-
▼
|
|
56
|
-
┌─────────────────┐
|
|
57
|
-
│ PageRank Boost │ ← Centrality from file dependency graph
|
|
58
|
-
│ │ weight: 0.1 (default)
|
|
59
|
-
└────────┬────────┘
|
|
60
|
-
│
|
|
61
|
-
▼
|
|
62
|
-
┌─────────────────┐
|
|
63
|
-
│ Supersede │ ← 0.3× demotion for replaced documents
|
|
64
|
-
│ Demotion │
|
|
65
|
-
└────────┬────────┘
|
|
66
|
-
│
|
|
67
|
-
▼
|
|
68
|
-
┌─────────────────┐
|
|
69
|
-
│ Neural Reranking│ ← VoyageAI rerank-2.5-lite
|
|
70
|
-
│ (optional) │
|
|
71
|
-
└────────┬────────┘
|
|
72
|
-
│
|
|
73
|
-
▼
|
|
74
|
-
┌─────────────────┐
|
|
75
|
-
│ Position-Aware │ ← top 3: 75/25, 4-10: 60/40, 11+: 40/60
|
|
76
|
-
│ Blending │ (RRF weight / rerank weight)
|
|
77
|
-
└────────┬────────┘
|
|
78
|
-
│
|
|
79
|
-
▼
|
|
80
|
-
Final Results
|
|
21
|
+
# Or build from source
|
|
22
|
+
CGO_ENABLED=0 go build -o nano-brain ./cmd/nano-brain
|
|
81
23
|
```
|
|
82
24
|
|
|
83
|
-
###
|
|
25
|
+
### Start
|
|
84
26
|
|
|
85
|
-
```
|
|
86
|
-
Memory Write
|
|
87
|
-
│
|
|
88
|
-
▼
|
|
89
|
-
┌─────────────────┐
|
|
90
|
-
│ Save to File │ → ~/.nano-brain/memory/
|
|
91
|
-
│ Hash + DB Insert │ → documents + content tables
|
|
92
|
-
│ FTS5 Index │ → documents_fts (auto-trigger)
|
|
93
|
-
└────────┬────────┘
|
|
94
|
-
│
|
|
95
|
-
┌────┴────┐
|
|
96
|
-
▼ ▼
|
|
97
|
-
┌────────┐ ┌──────────┐
|
|
98
|
-
│Keyword │ │ Async │ (fire-and-forget)
|
|
99
|
-
│Categorize│ │ Processes│
|
|
100
|
-
│auto:* │ │ │
|
|
101
|
-
└────────┘ ├──────────┤
|
|
102
|
-
│ LLM │ → llm:* tags
|
|
103
|
-
│ Categorize│
|
|
104
|
-
├──────────┤
|
|
105
|
-
│ Entity │ → knowledge graph
|
|
106
|
-
│ Extract │
|
|
107
|
-
└──────────┘
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## Search Pipeline (3 Tiers)
|
|
111
|
-
|
|
112
|
-
**`memory_search`** — BM25 only (fast, exact keyword matching)
|
|
113
|
-
|
|
114
|
-
**`memory_vsearch`** — Vector only (semantic similarity via embeddings)
|
|
115
|
-
|
|
116
|
-
**`memory_query`** — Full hybrid pipeline with 6 ranking signals:
|
|
117
|
-
|
|
118
|
-
1. **BM25 full-text scoring** — SQLite FTS5 with porter stemming
|
|
119
|
-
2. **Vector cosine similarity** — Qdrant or sqlite-vec embeddings
|
|
120
|
-
3. **RRF fusion** — k=60, original query weighted 2×
|
|
121
|
-
4. **PageRank centrality boost** — from file dependency graph (weight: 0.1)
|
|
122
|
-
5. **Supersede demotion** — 0.3× penalty for replaced documents
|
|
123
|
-
6. **VoyageAI neural reranking** — rerank-2.5-lite with position-aware blending:
|
|
124
|
-
- Top 3 results: 75% RRF / 25% rerank
|
|
125
|
-
- Ranks 4-10: 60% RRF / 40% rerank
|
|
126
|
-
- Ranks 11+: 40% RRF / 60% rerank
|
|
127
|
-
|
|
128
|
-
Query expansion generates 2-3 query variants before search. The pipeline supports it, but no expansion provider is currently active.
|
|
129
|
-
|
|
130
|
-
## Code Intelligence
|
|
131
|
-
|
|
132
|
-
Built on Tree-sitter AST parsing for TypeScript, JavaScript, and Python:
|
|
133
|
-
|
|
134
|
-
**`code_context`** — 360° view of a code symbol:
|
|
135
|
-
- Direct callers and callees
|
|
136
|
-
- Transitive call flows (upstream/downstream)
|
|
137
|
-
- File location, definition, and references
|
|
138
|
-
- Centrality score (PageRank) and cluster membership
|
|
139
|
-
|
|
140
|
-
**`code_impact`** — Change impact analysis:
|
|
141
|
-
- Upstream dependencies (what calls this?)
|
|
142
|
-
- Downstream dependencies (what does this call?)
|
|
143
|
-
- BFS traversal with configurable depth
|
|
144
|
-
- Risk assessment for refactoring
|
|
145
|
-
|
|
146
|
-
**`code_detect_changes`** — Map git diff to affected symbols:
|
|
147
|
-
- Parses `git diff` output
|
|
148
|
-
- Identifies modified symbols via Tree-sitter
|
|
149
|
-
- Returns symbol names, types, and file locations
|
|
150
|
-
- Scope: `staged`, `unstaged`, or `all`
|
|
151
|
-
|
|
152
|
-
**`memory_focus`** — File dependency context:
|
|
153
|
-
- Import/export graph for a file
|
|
154
|
-
- Centrality score (PageRank)
|
|
155
|
-
- Cluster membership (Louvain algorithm)
|
|
156
|
-
- Direct dependencies and dependents
|
|
157
|
-
|
|
158
|
-
**`memory_graph_stats`** — Dependency graph overview:
|
|
159
|
-
- Total files, symbols, edges
|
|
160
|
-
- Cycle detection
|
|
161
|
-
- Clustering coefficient
|
|
162
|
-
- Top central files
|
|
163
|
-
|
|
164
|
-
**Symbol tracking** — Cross-repo symbol queries:
|
|
165
|
-
- Redis keys, PubSub channels
|
|
166
|
-
- MySQL tables, columns
|
|
167
|
-
- API endpoints (Express, FastAPI)
|
|
168
|
-
- Bull/BullMQ queues
|
|
169
|
-
- GraphQL types, queries, mutations
|
|
170
|
-
|
|
171
|
-
## Data Ingestion
|
|
172
|
-
|
|
173
|
-
All data sources are indexed automatically:
|
|
174
|
-
|
|
175
|
-
**Session harvesting** — Converts OpenCode JSON sessions into searchable markdown:
|
|
176
|
-
- Polls `~/.opencode/sessions/` every 2 minutes
|
|
177
|
-
- Extracts user queries, assistant responses, tool calls
|
|
178
|
-
- Incremental append (hash-based deduplication)
|
|
179
|
-
|
|
180
|
-
**File watching** — Monitors collections for changes:
|
|
181
|
-
- Chokidar watches configured directories
|
|
182
|
-
- Dirty-flag tracking for incremental updates
|
|
183
|
-
- Reindexes every 5 minutes if changes detected
|
|
184
|
-
|
|
185
|
-
**Codebase indexing** — Tree-sitter AST → symbol graph:
|
|
186
|
-
- Parses TS/JS/Python files
|
|
187
|
-
- Extracts functions, classes, methods, variables
|
|
188
|
-
- Builds call graph (caller → callee edges)
|
|
189
|
-
- Computes PageRank centrality
|
|
190
|
-
- Detects clusters via Louvain algorithm
|
|
191
|
-
- Identifies call flows (entry points → leaf functions)
|
|
192
|
-
|
|
193
|
-
**Incremental behavior**:
|
|
194
|
-
- Hash-based file skipping (SHA-256 content addressing)
|
|
195
|
-
- Adaptive embedding backoff (exponential retry)
|
|
196
|
-
- Batch processing for large codebases
|
|
197
|
-
|
|
198
|
-
## Background Jobs
|
|
199
|
-
|
|
200
|
-
nano-brain runs 9 background jobs to keep your memory fresh and intelligent:
|
|
201
|
-
|
|
202
|
-
| Job | Interval | What It Does |
|
|
203
|
-
|-----|----------|-------------|
|
|
204
|
-
| File reindex | 5 min | Watch collections, reindex changed files |
|
|
205
|
-
| Session harvest | 2 min | Convert OpenCode sessions → searchable markdown |
|
|
206
|
-
| Embedding | 60s (adaptive) | Generate vector embeddings for new docs |
|
|
207
|
-
| Learning cycle | 10 min | Thompson Sampling + preference weight updates |
|
|
208
|
-
| Consolidation | 1 hour | LLM summarizes related memories |
|
|
209
|
-
| Importance | 30 min | Rescore document importance from usage |
|
|
210
|
-
| Sequence analysis | 30 min | Detect query patterns for proactive suggestions |
|
|
211
|
-
| Pruning (soft) | 6 hours | Soft-delete contradicted/orphan entities |
|
|
212
|
-
| Pruning (hard) | 7 days | Permanently delete old soft-deleted entities |
|
|
213
|
-
|
|
214
|
-
## Chunking Strategy
|
|
215
|
-
|
|
216
|
-
Heading-aware markdown chunking that respects document structure:
|
|
217
|
-
|
|
218
|
-
- **Target size:** 900 tokens (~3600 characters)
|
|
219
|
-
- **Overlap:** 15% between chunks (~540 characters)
|
|
220
|
-
- **Respects boundaries:** Code fences, headings, paragraphs
|
|
221
|
-
- **Break point scoring:** h1=100, h2=90, h3=80, code-fence=80, hr=60, blank-line=40
|
|
222
|
-
- **Content-addressed storage:** SHA-256 hash deduplication
|
|
223
|
-
|
|
224
|
-
## Storage & Infrastructure
|
|
225
|
-
|
|
226
|
-
**SQLite** (via better-sqlite3):
|
|
227
|
-
- `documents` — metadata, content, embeddings
|
|
228
|
-
- `chunks` — heading-aware markdown chunks (900 tokens, 15% overlap)
|
|
229
|
-
- `fts_index` — FTS5 virtual table with porter stemming
|
|
230
|
-
- `vec_index` — sqlite-vec extension (cosine distance)
|
|
231
|
-
- `symbols` — code symbols (functions, classes, variables)
|
|
232
|
-
- `call_edges` — caller → callee relationships
|
|
233
|
-
- `file_deps` — import/export graph
|
|
234
|
-
- `clusters` — Louvain clustering results
|
|
235
|
-
- `flows` — detected call flows (entry → leaf)
|
|
236
|
-
|
|
237
|
-
**Qdrant** (optional, production vector store):
|
|
238
|
-
- Included in `nano-brain docker start` compose stack, or managed standalone via `qdrant up/down/status` commands
|
|
239
|
-
- Automatic migration from sqlite-vec
|
|
240
|
-
- Verification and cleanup tools
|
|
241
|
-
|
|
242
|
-
**Embedding providers**:
|
|
243
|
-
- **VoyageAI** — voyage-code-3 (1024 dims, code-optimized)
|
|
244
|
-
- **Ollama** — local models (nomic-embed-text, etc.)
|
|
245
|
-
- **OpenAI-compatible** — Azure, LM Studio, custom endpoints
|
|
246
|
-
|
|
247
|
-
**Reranking**:
|
|
248
|
-
- **VoyageAI** — rerank-2.5-lite (neural reranking)
|
|
249
|
-
|
|
250
|
-
**Storage management**:
|
|
251
|
-
- Per-workspace SQLite databases (isolated)
|
|
252
|
-
- Content-addressed storage (SHA-256 deduplication)
|
|
253
|
-
- Retention policies (maxSize budget, auto-cleanup)
|
|
254
|
-
- Disk space checks before indexing
|
|
255
|
-
|
|
256
|
-
## Database Schema
|
|
257
|
-
|
|
258
|
-
nano-brain uses 18 SQLite tables organized into 5 functional groups:
|
|
259
|
-
|
|
260
|
-
| Table | Purpose |
|
|
261
|
-
|-------|---------|
|
|
262
|
-
| **Core Documents** | |
|
|
263
|
-
| `documents` | Document metadata, content, embeddings |
|
|
264
|
-
| `chunks` | Heading-aware markdown chunks (900 tokens, 15% overlap) |
|
|
265
|
-
| `content` | Raw content storage (content-addressed) |
|
|
266
|
-
| **Search Indexes** | |
|
|
267
|
-
| `documents_fts` | FTS5 full-text search index (porter stemming) |
|
|
268
|
-
| `vec_index` | sqlite-vec vector index (cosine distance) |
|
|
269
|
-
| **Code Intelligence** | |
|
|
270
|
-
| `symbols` | Code symbols (functions, classes, variables) |
|
|
271
|
-
| `call_edges` | Caller → callee relationships |
|
|
272
|
-
| `file_deps` | Import/export graph |
|
|
273
|
-
| `clusters` | Louvain clustering results |
|
|
274
|
-
| `flows` | Detected call flows (entry → leaf) |
|
|
275
|
-
| **Knowledge Graph** | |
|
|
276
|
-
| `entities` | LLM-extracted entities (people, concepts, tools) |
|
|
277
|
-
| `relationships` | Entity-to-entity connections |
|
|
278
|
-
| **Learning & Intelligence** | |
|
|
279
|
-
| `telemetry` | Search queries, results, expand feedback |
|
|
280
|
-
| `bandit_variants` | Thompson Sampling search parameter tuning |
|
|
281
|
-
| `config_versions` | Search config version history |
|
|
282
|
-
| `consolidations` | LLM-generated memory summaries |
|
|
283
|
-
| `query_sequences` | Query pattern detection for proactive suggestions |
|
|
284
|
-
| `category_preferences` | Per-workspace category weights from expand patterns |
|
|
285
|
-
|
|
286
|
-
## Database Reliability & Corruption Recovery
|
|
287
|
-
|
|
288
|
-
**Why corruption happens**:
|
|
289
|
-
SQLite databases can become corrupted due to:
|
|
290
|
-
- Unexpected process termination during write operations
|
|
291
|
-
- Filesystem crashes or power loss during WAL (Write-Ahead Log) checkpoint
|
|
292
|
-
- Disk I/O errors or hardware faults
|
|
293
|
-
- Rare race conditions in concurrent access (even with better-sqlite3 serialization)
|
|
294
|
-
|
|
295
|
-
**Automatic corruption detection**:
|
|
296
|
-
nano-brain automatically detects database corruption on startup via `PRAGMA integrity_check`:
|
|
297
|
-
- Runs before any database operations in `createStore()`
|
|
298
|
-
- Checks database file integrity without modifying data
|
|
299
|
-
- Takes 50-500ms depending on database size
|
|
300
|
-
|
|
301
|
-
**Automatic recovery**:
|
|
302
|
-
When corruption is detected:
|
|
303
|
-
1. **Backup corrupted file** — Renamed to `.corrupted.{ISO-timestamp}` for forensics/recovery
|
|
304
|
-
2. **Clear WAL/SHM files** — Removes Write-Ahead Log and shared memory files
|
|
305
|
-
3. **Initialize fresh database** — Creates clean SQLite database from scratch
|
|
306
|
-
4. **Verify fresh database** — Runs integrity check to confirm recovery succeeded
|
|
307
|
-
5. **Emit metric** — `database_corruption_detected` counter for monitoring/alerting
|
|
308
|
-
|
|
309
|
-
**Why this works**:
|
|
310
|
-
The database is a **cache/index** — all data is re-derivable from source files. Recovery involves:
|
|
311
|
-
- Session harvesting (re-ingests from session logs)
|
|
312
|
-
- Codebase reindexing (rescan source files)
|
|
313
|
-
- Memory re-embedding (regenerates vectors)
|
|
314
|
-
- Call graph rebuilding (reparses symbols)
|
|
315
|
-
|
|
316
|
-
**Automatic restart with launchd**:
|
|
317
|
-
On macOS, nano-brain runs as a launchd service (`com.tamlh.nano-brain`):
|
|
318
|
-
- If corruption causes a fatal error, process exits
|
|
319
|
-
- launchd automatically restarts it after 10-second throttle
|
|
320
|
-
- On restart, `checkAndRecoverDB()` detects corruption and recovers
|
|
321
|
-
- Service comes back online automatically with fresh database
|
|
322
|
-
|
|
323
|
-
**Installation (macOS)**:
|
|
324
27
|
```bash
|
|
325
|
-
#
|
|
326
|
-
|
|
28
|
+
# Start PostgreSQL
|
|
29
|
+
docker run -d --name nanobrain-pg -p 5432:5432 \
|
|
30
|
+
-e POSTGRES_USER=nanobrain -e POSTGRES_PASSWORD=nanobrain -e POSTGRES_DB=nanobrain_dev \
|
|
31
|
+
pgvector/pgvector:pg17
|
|
327
32
|
|
|
328
|
-
#
|
|
329
|
-
|
|
33
|
+
# Start nano-brain
|
|
34
|
+
nano-brain serve -d
|
|
330
35
|
|
|
331
|
-
#
|
|
332
|
-
|
|
36
|
+
# Register your project
|
|
37
|
+
nano-brain init --root=/path/to/your/project
|
|
333
38
|
```
|
|
39
|
+
---
|
|
334
40
|
|
|
335
|
-
|
|
336
|
-
Check for corruption metrics in your monitoring/alerting system:
|
|
337
|
-
- Counter: `database_corruption_detected`
|
|
338
|
-
- Alert threshold: > 3 events per 24 hours (indicates underlying hardware/filesystem issue)
|
|
41
|
+
## Why Star This Project?
|
|
339
42
|
|
|
340
|
-
**
|
|
341
|
-
If corruption happens frequently:
|
|
342
|
-
1. Check system logs for disk I/O errors: `log stream --predicate 'eventMessage contains[c] "I/O error"'`
|
|
343
|
-
2. Verify filesystem health: `diskutil verifyVolume /` (macOS)
|
|
344
|
-
3. Check disk space: `df -h ~/.nano-brain/`
|
|
345
|
-
4. Review database size: `ls -lh ~/.nano-brain/index.db`
|
|
346
|
-
5. Consider moving database to a different drive if corruption persists
|
|
43
|
+
**If you've ever wished your AI agent stopped flying blind in your codebase.**
|
|
347
44
|
|
|
348
|
-
**
|
|
349
|
-
Corrupted backups are kept for analysis:
|
|
350
|
-
- Located at: `~/.nano-brain/index.db.corrupted.{ISO-timestamp}`
|
|
351
|
-
- Last 5 backups are kept by default; older ones are auto-cleaned
|
|
352
|
-
- File size indicates when corruption occurred (if truncated vs intact)
|
|
45
|
+
Most memory tools optimize for conversation recall. nano-brain optimizes for **agent comprehension** — the ability to understand codebases, trace dependencies, and predict the blast radius of changes.
|
|
353
46
|
|
|
354
|
-
|
|
47
|
+
nano-brain is:
|
|
355
48
|
|
|
356
|
-
|
|
49
|
+
- **Agent-oriented** — Built around how agents actually work: impact analysis before edits, call chain tracing, symbol lookup. Not a document store with MCP slapped on top.
|
|
50
|
+
- **Self-hosted** — Your data stays on your server. No cloud dependency.
|
|
51
|
+
- **Works everywhere** — OpenCode, Claude Code, Cursor, any MCP client.
|
|
52
|
+
- **Actually useful** — Not a toy demo. Production-ready with 16 MCP tools, hybrid search, code intelligence, and agent-oriented benchmarks.
|
|
53
|
+
- **Built for developers** — Go binary, PostgreSQL, zero magic. You can read the code.
|
|
54
|
+
- **Beating competitors** — P@5 of 80% vs LlamaIndex's 55% and Qdrant's 27% on real-world queries.
|
|
357
55
|
|
|
358
|
-
|
|
359
|
-
|------|-------------|
|
|
360
|
-
| `memory_search` | BM25 keyword search (fast, exact matching) |
|
|
361
|
-
| `memory_vsearch` | Semantic vector search (embeddings) |
|
|
362
|
-
| `memory_query` | Full hybrid search (BM25 + vector + RRF + reranking) |
|
|
363
|
-
| `memory_get` | Retrieve document by path or docid (#abc123) |
|
|
364
|
-
| `memory_multi_get` | Batch retrieve by glob pattern |
|
|
56
|
+
Star it if you want agents that understand your code, not just search it.
|
|
365
57
|
|
|
366
|
-
|
|
58
|
+
---
|
|
367
59
|
|
|
368
|
-
|
|
369
|
-
|------|-------------|
|
|
370
|
-
| `memory_write` | Write to daily log (supports tags, supersedes) |
|
|
371
|
-
| `memory_tags` | List all tags with document counts |
|
|
372
|
-
| `memory_status` | Index health, collections, model status, graph stats |
|
|
373
|
-
| `memory_update` | Trigger reindex of all collections |
|
|
374
|
-
| `memory_consolidate` | Trigger LLM memory consolidation |
|
|
375
|
-
| `memory_suggestions` | Proactive next-query predictions based on patterns |
|
|
60
|
+
## What It Does
|
|
376
61
|
|
|
377
|
-
|
|
62
|
+
nano-brain is an **agent-oriented infrastructure layer** that sits between your AI agent and your codebase.
|
|
378
63
|
|
|
379
|
-
|
|
380
|
-
|------|-------------|
|
|
381
|
-
| `code_context` | 360° view of a code symbol (callers, callees, flows, centrality) |
|
|
382
|
-
| `code_impact` | Change impact analysis (upstream/downstream BFS) |
|
|
383
|
-
| `code_detect_changes` | Map git diff to affected symbols (staged/unstaged/all) |
|
|
384
|
-
| `memory_index_codebase` | Index codebase files in current workspace (Tree-sitter AST) |
|
|
64
|
+
It solves two problems agents have:
|
|
385
65
|
|
|
386
|
-
|
|
66
|
+
1. **Session amnesia** — Agents forget everything when the session ends. nano-brain persists context across sessions via harvesting, indexing, and retrieval.
|
|
67
|
+
2. **Codebase blindness** — Agents can't trace dependencies, measure blast radius, or understand control flow. nano-brain builds a live code graph and exposes it via 16 MCP tools.
|
|
387
68
|
|
|
388
|
-
|
|
389
|
-
|------|-------------|
|
|
390
|
-
| `memory_focus` | File dependency context (imports/exports, centrality, cluster) |
|
|
391
|
-
| `memory_graph_stats` | Dependency graph overview (files, symbols, edges, cycles) |
|
|
392
|
-
| `memory_symbols` | Cross-repo symbol query (Redis, MySQL, API endpoints, queues) |
|
|
393
|
-
| `memory_impact` | Cross-repo impact analysis (writers vs readers) |
|
|
394
|
-
| `memory_graph_query` | BFS traversal from entity through knowledge graph |
|
|
395
|
-
| `memory_related` | Find related memories via entity graph connections |
|
|
396
|
-
| `memory_timeline` | Temporal view of entity changes over time |
|
|
69
|
+
**Why MCP?** Because agents don't read docs. They call tools. Every capability is a tool call — no REST API ceremony, no JSON parsing, no manual file reading.
|
|
397
70
|
|
|
398
|
-
|
|
71
|
+
### How agents use it
|
|
399
72
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
73
|
+
| Agent needs to... | Tool | What it returns |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| Understand a feature | `memory_query` | Hybrid search results with context |
|
|
76
|
+
| Check what breaks before editing | `memory_impact` | Blast radius — all dependent files |
|
|
77
|
+
| Trace an execution path | `memory_trace` | Call chain from entry point |
|
|
78
|
+
| Find a function definition | `memory_symbols` | Symbol location + kind |
|
|
79
|
+
| Recall a past decision | `memory_query` | Past session context |
|
|
80
|
+
| Save a discovery | `memory_write` | Persisted for future sessions |
|
|
81
|
+
|
|
82
|
+
---
|
|
403
83
|
|
|
404
|
-
|
|
405
|
-
npx nano-brain init --root=/path/to/your/project
|
|
84
|
+
## Architecture
|
|
406
85
|
|
|
407
|
-
|
|
408
|
-
|
|
86
|
+
```mermaid
|
|
87
|
+
graph LR
|
|
88
|
+
A[Your AI Agent] -->|MCP Protocol| B[nano-brain]
|
|
89
|
+
B --> C[PostgreSQL + pgvector]
|
|
90
|
+
B --> D[Session Harvesting]
|
|
91
|
+
B --> E[Code Intelligence]
|
|
92
|
+
B --> F[Hybrid Search]
|
|
93
|
+
|
|
94
|
+
D --> D1[OpenCode Sessions]
|
|
95
|
+
D --> D2[Claude Code Sessions]
|
|
96
|
+
|
|
97
|
+
E --> E1[Symbol Graph]
|
|
98
|
+
E --> E2[Flow Diagrams]
|
|
99
|
+
E --> E3[Impact Analysis]
|
|
100
|
+
|
|
101
|
+
F --> F1[BM25 Full-Text]
|
|
102
|
+
F --> F2[Vector Similarity]
|
|
103
|
+
F --> F3[RRF Fusion]
|
|
409
104
|
```
|
|
410
105
|
|
|
411
|
-
|
|
106
|
+
---
|
|
412
107
|
|
|
413
|
-
|
|
108
|
+
## Agent-Oriented Design
|
|
414
109
|
|
|
415
|
-
|
|
416
|
-
# Start nano-brain + Qdrant containers
|
|
417
|
-
npx nano-brain docker start
|
|
110
|
+
nano-brain isn't a memory tool with MCP bolted on. It's designed from the ground up around **how agents actually behave**.
|
|
418
111
|
|
|
419
|
-
|
|
420
|
-
npx nano-brain docker status
|
|
112
|
+
### The agent workflow loop
|
|
421
113
|
|
|
422
|
-
|
|
423
|
-
|
|
114
|
+
```
|
|
115
|
+
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
|
|
116
|
+
│ Agent │────▶│ memory_query │────▶│ Context │
|
|
117
|
+
│ receives │ │ /impact/trace│ │ window │
|
|
118
|
+
│ task │ │ │ │ filled │
|
|
119
|
+
└─────────────┘ └──────────────┘ └──────┬──────┘
|
|
120
|
+
│
|
|
121
|
+
┌──────▼──────┐
|
|
122
|
+
│ Agent │
|
|
123
|
+
│ implements │
|
|
124
|
+
│ change │
|
|
125
|
+
└──────┬──────┘
|
|
126
|
+
│
|
|
127
|
+
┌──────▼──────┐
|
|
128
|
+
│ memory_write │
|
|
129
|
+
│ (persist) │
|
|
130
|
+
└─────────────┘
|
|
424
131
|
```
|
|
425
132
|
|
|
426
|
-
|
|
133
|
+
### Why agent behavior matters
|
|
427
134
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
135
|
+
| Human workflow | Agent workflow | nano-brain response |
|
|
136
|
+
|---|---|---|
|
|
137
|
+
| Opens file, reads it | `memory_get` or `memory_search` | Returns structured content, not raw bytes |
|
|
138
|
+
| Traces call chain manually | `memory_trace` | Returns function-by-function chain with line numbers |
|
|
139
|
+
| Greps for callers | `memory_graph(direction="in")` | Returns all callers in one call |
|
|
140
|
+
| Thinks "what breaks?" | `memory_impact` | Returns full blast radius in <50ms |
|
|
141
|
+
| Remembers past decisions | `memory_query` | Returns cross-session context |
|
|
432
142
|
|
|
433
|
-
|
|
143
|
+
### The 50ms rule
|
|
434
144
|
|
|
435
|
-
|
|
436
|
-
|----------|--------|-------------|
|
|
437
|
-
| `/health` | GET | Health check |
|
|
438
|
-
| `/api/status` | GET | Index health, collections, model status |
|
|
439
|
-
| `/api/query` | POST | Hybrid search (body: `{query, tags, scope, limit}`) |
|
|
440
|
-
| `/api/search` | POST | BM25 keyword search (body: `{query, limit}`) |
|
|
441
|
-
| `/api/write` | POST | Write memory (body: `{content, tags, supersedes}`) |
|
|
442
|
-
| `/api/reindex` | POST | Trigger reindex (body: `{root}`) |
|
|
443
|
-
| `/mcp` | — | MCP endpoint (for AI agent integration) |
|
|
444
|
-
| `/sse` | — | SSE transport (for MCP remote clients) |
|
|
145
|
+
At 50ms latency, agents run impact analysis on every edit. At 500ms, they skip it. nano-brain is designed for the 50ms world — every code intelligence tool call is sub-50ms, making it practical for agents to use them on every operation.
|
|
445
146
|
|
|
446
|
-
###
|
|
147
|
+
### What agents actually need
|
|
447
148
|
|
|
448
|
-
|
|
149
|
+
Research from 15+ production code intelligence tools shows:
|
|
449
150
|
|
|
450
|
-
**
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
"mcp": {
|
|
454
|
-
"nano-brain": {
|
|
455
|
-
"type": "remote",
|
|
456
|
-
"url": "http://host.docker.internal:3100/mcp",
|
|
457
|
-
"enabled": true
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
Start the server via Docker:
|
|
464
|
-
```bash
|
|
465
|
-
npx nano-brain docker start # Start nano-brain + Qdrant containers
|
|
466
|
-
npx nano-brain docker status # Check if running
|
|
467
|
-
npx nano-brain docker stop # Stop containers
|
|
468
|
-
```
|
|
469
|
-
|
|
470
|
-
**Local mode (stdio, for development):**
|
|
471
|
-
```json
|
|
472
|
-
{
|
|
473
|
-
"mcp": {
|
|
474
|
-
"nano-brain": {
|
|
475
|
-
"type": "local",
|
|
476
|
-
"command": ["npx", "nano-brain", "mcp"],
|
|
477
|
-
"enabled": true
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
```
|
|
151
|
+
1. **Impact analysis is #1** — "What breaks if I change this?" is the most common agent query
|
|
152
|
+
2. **Call chains > control flow** — Agents trace across files (inter-procedural), not within functions (intra-procedural)
|
|
153
|
+
3. **Component composition > internal logic** — For frontend frameworks, "who uses this component?" matters more than "what does the template do?"
|
|
482
154
|
|
|
483
|
-
|
|
484
|
-
```json
|
|
485
|
-
{
|
|
486
|
-
"mcpServers": {
|
|
487
|
-
"nano-brain": {
|
|
488
|
-
"command": "npx",
|
|
489
|
-
"args": ["mcp-remote", "http://localhost:3100/sse"]
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
```
|
|
155
|
+
nano-brain optimizes for exactly these three patterns.
|
|
494
156
|
|
|
495
|
-
|
|
157
|
+
---
|
|
496
158
|
|
|
497
|
-
|
|
159
|
+
## Key Features
|
|
498
160
|
|
|
499
|
-
|
|
500
|
-
# Collections (directories to index)
|
|
501
|
-
collections:
|
|
502
|
-
memory:
|
|
503
|
-
path: ~/.nano-brain/memory
|
|
504
|
-
pattern: "**/*.md"
|
|
505
|
-
update: auto
|
|
506
|
-
sessions:
|
|
507
|
-
path: ~/.nano-brain/sessions
|
|
508
|
-
pattern: "**/*.md"
|
|
509
|
-
update: auto
|
|
510
|
-
|
|
511
|
-
# Vector store (qdrant or sqlite-vec)
|
|
512
|
-
vector:
|
|
513
|
-
provider: qdrant
|
|
514
|
-
url: http://localhost:6333
|
|
515
|
-
collection: nano_brain
|
|
516
|
-
# OR: provider: sqlite-vec (embedded, no external service)
|
|
517
|
-
|
|
518
|
-
# Embedding provider
|
|
519
|
-
embedding:
|
|
520
|
-
provider: openai # 'ollama' or 'openai' (OpenAI-compatible)
|
|
521
|
-
url: https://api.voyageai.com # VoyageAI, Azure, LM Studio, etc.
|
|
522
|
-
model: voyage-code-3
|
|
523
|
-
apiKey: ${VOYAGE_API_KEY}
|
|
524
|
-
dimensions: 1024 # Output dimensions (default: 1024); omit to use model default
|
|
525
|
-
# OR: provider: ollama, url: http://localhost:11434, model: nomic-embed-text
|
|
526
|
-
|
|
527
|
-
# Reranker (uses embedding.apiKey if not set separately)
|
|
528
|
-
reranker:
|
|
529
|
-
model: rerank-2.5-lite
|
|
530
|
-
# apiKey: ${VOYAGE_API_KEY} # optional, falls back to embedding.apiKey
|
|
531
|
-
|
|
532
|
-
# Codebase indexing
|
|
533
|
-
codebase:
|
|
534
|
-
enabled: true
|
|
535
|
-
languages: [typescript, javascript, python]
|
|
536
|
-
exclude: [node_modules, dist, build, .git]
|
|
537
|
-
maxFileSize: 1048576 # 1MB
|
|
538
|
-
|
|
539
|
-
# File watcher
|
|
540
|
-
watcher:
|
|
541
|
-
enabled: true
|
|
542
|
-
debounce: 300 # ms
|
|
543
|
-
reindexInterval: 300 # seconds (5 minutes)
|
|
544
|
-
|
|
545
|
-
# Search configuration
|
|
546
|
-
search:
|
|
547
|
-
rrf_k: 60
|
|
548
|
-
top_k: 30
|
|
549
|
-
expansion:
|
|
550
|
-
enabled: true
|
|
551
|
-
weight: 1
|
|
552
|
-
reranking:
|
|
553
|
-
enabled: true
|
|
554
|
-
blending:
|
|
555
|
-
top3:
|
|
556
|
-
rrf: 0.75
|
|
557
|
-
rerank: 0.25
|
|
558
|
-
mid:
|
|
559
|
-
rrf: 0.60
|
|
560
|
-
rerank: 0.40
|
|
561
|
-
tail:
|
|
562
|
-
rrf: 0.40
|
|
563
|
-
rerank: 0.60
|
|
564
|
-
centrality_weight: 0.1
|
|
565
|
-
supersede_demotion: 0.3
|
|
566
|
-
|
|
567
|
-
# Polling intervals
|
|
568
|
-
intervals:
|
|
569
|
-
sessionHarvest: 120 # seconds (2 minutes)
|
|
570
|
-
healthCheck: 60 # seconds
|
|
571
|
-
|
|
572
|
-
# Storage management
|
|
573
|
-
storage:
|
|
574
|
-
maxSize: 10737418240 # 10GB
|
|
575
|
-
retention:
|
|
576
|
-
sessions: 90 # days
|
|
577
|
-
logs: 30 # days
|
|
578
|
-
|
|
579
|
-
# Workspaces
|
|
580
|
-
workspaces:
|
|
581
|
-
isolation: true # Per-workspace SQLite databases
|
|
582
|
-
defaultScope: current # or 'all' for cross-workspace search
|
|
583
|
-
|
|
584
|
-
# Entity pruning (Memory Intelligence v2)
|
|
585
|
-
pruning:
|
|
586
|
-
enabled: true
|
|
587
|
-
interval_ms: 21600000 # 6 hours
|
|
588
|
-
contradicted_ttl_days: 30
|
|
589
|
-
orphan_ttl_days: 90
|
|
590
|
-
batch_size: 100
|
|
591
|
-
hard_delete_after_days: 30
|
|
592
|
-
|
|
593
|
-
# LLM categorization (Memory Intelligence v2)
|
|
594
|
-
categorization:
|
|
595
|
-
llm_enabled: true
|
|
596
|
-
confidence_threshold: 0.6
|
|
597
|
-
max_content_length: 2000
|
|
598
|
-
|
|
599
|
-
# Preference learning (Memory Intelligence v2)
|
|
600
|
-
preferences:
|
|
601
|
-
enabled: true
|
|
602
|
-
min_queries: 20
|
|
603
|
-
weight_min: 0.5
|
|
604
|
-
weight_max: 2.0
|
|
605
|
-
baseline_expand_rate: 0.1
|
|
606
|
-
|
|
607
|
-
# Logging
|
|
608
|
-
logging:
|
|
609
|
-
level: info # debug, info, warn, error
|
|
610
|
-
file: ~/.nano-brain/logs/nano-brain.log
|
|
611
|
-
maxSize: 10485760 # 10MB
|
|
612
|
-
maxFiles: 5
|
|
613
|
-
```
|
|
161
|
+
### Hybrid Search
|
|
614
162
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
└── logs/ # Application logs
|
|
163
|
+
```mermaid
|
|
164
|
+
graph LR
|
|
165
|
+
Q[Query] --> BM25[BM25 Full-Text]
|
|
166
|
+
Q --> Vector[Vector Similarity]
|
|
167
|
+
BM25 --> RRF[RRF Fusion]
|
|
168
|
+
Vector --> RRF
|
|
169
|
+
RRF --> Results[Ranked Results]
|
|
623
170
|
```
|
|
624
171
|
|
|
625
|
-
|
|
172
|
+
BM25 full-text + pgvector HNSW cosine similarity + Reciprocal Rank Fusion + recency decay.
|
|
626
173
|
|
|
627
|
-
###
|
|
174
|
+
### Code Intelligence
|
|
628
175
|
|
|
629
|
-
```
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
176
|
+
```mermaid
|
|
177
|
+
graph TD
|
|
178
|
+
A[Entry Point] --> B[Function Call]
|
|
179
|
+
B --> C[Method Call]
|
|
180
|
+
B --> D[Database Query]
|
|
181
|
+
C --> E[External Service]
|
|
182
|
+
D --> F[Redis Cache]
|
|
633
183
|
```
|
|
634
184
|
|
|
635
|
-
|
|
185
|
+
- **Symbol extraction** — Functions, types, interfaces, constants
|
|
186
|
+
- **Call chain tracing** — Follow execution paths across files
|
|
187
|
+
- **Impact analysis** — "What breaks if I change this?"
|
|
188
|
+
- **Flow diagrams** — Mermaid flowcharts and sequence diagrams
|
|
636
189
|
|
|
637
|
-
|
|
638
|
-
nano-brain mcp # Start MCP server (stdio)
|
|
639
|
-
nano-brain mcp --http --port=3100 --host=0.0.0.0 # Start MCP server (HTTP/SSE)
|
|
640
|
-
```
|
|
190
|
+
### Session Harvesting
|
|
641
191
|
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
nano-brain serve --port=8080 # Custom port
|
|
192
|
+
```mermaid
|
|
193
|
+
graph LR
|
|
194
|
+
S1[OpenCode DB] --> H[Harvester]
|
|
195
|
+
S2[Claude Code JSONL] --> H
|
|
196
|
+
H --> L[LLM Summarizer]
|
|
197
|
+
L --> I[Indexer]
|
|
198
|
+
I --> DB[PostgreSQL]
|
|
650
199
|
```
|
|
651
200
|
|
|
652
|
-
|
|
201
|
+
Auto-ingest from OpenCode and Claude Code sessions. Map-reduce LLM summarization. Incremental harvest with dedup.
|
|
653
202
|
|
|
654
|
-
|
|
655
|
-
nano-brain docker start # Start nano-brain + Qdrant via docker compose
|
|
656
|
-
nano-brain docker status # Check container status
|
|
657
|
-
nano-brain docker stop # Stop containers
|
|
658
|
-
```
|
|
203
|
+
### 16 MCP Tools
|
|
659
204
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
205
|
+
| Tool | Description |
|
|
206
|
+
|------|-------------|
|
|
207
|
+
| `memory_query` | Hybrid search — default first tool for broad questions |
|
|
208
|
+
| `memory_search` | BM25 keyword search for exact text/errors |
|
|
209
|
+
| `memory_vsearch` | Vector similarity for fuzzy concepts |
|
|
210
|
+
| `memory_get` | Get document by path or ID |
|
|
211
|
+
| `memory_write` | Write/update document |
|
|
212
|
+
| `memory_graph` | One-hop callers/callees/imports |
|
|
213
|
+
| `memory_trace` | Downstream call chain trace |
|
|
214
|
+
| `memory_impact` | Pre-change blast radius analysis |
|
|
215
|
+
| `memory_symbols` | Symbol search (functions, types, interfaces) |
|
|
216
|
+
| `memory_flow` | HTTP route execution flow |
|
|
217
|
+
| `memory_flowchart` | Function-level control-flow graph |
|
|
218
|
+
| `memory_workspaces_resolve` | Resolve path to workspace hash |
|
|
219
|
+
| `memory_tags` | List tags with counts |
|
|
220
|
+
| `memory_status` | Server and queue health |
|
|
221
|
+
| `memory_update` | Trigger re-embedding |
|
|
222
|
+
| `memory_wake_up` | Session-start workspace briefing |
|
|
663
223
|
|
|
664
|
-
|
|
665
|
-
- `NANO_BRAIN_APP` — Path to nano-brain source (default: current directory)
|
|
666
|
-
- `NANO_BRAIN_HOME` — Path to data directory (default: `~/.nano-brain`)
|
|
667
|
-
- `NANO_BRAIN_WORKSPACE` — Path to your project workspace to index as codebase (mounted read-only, passed as `--root`)
|
|
224
|
+
---
|
|
668
225
|
|
|
669
|
-
|
|
226
|
+
## Quick Start
|
|
670
227
|
|
|
671
|
-
|
|
672
|
-
nano-brain search "query" # BM25 keyword search
|
|
673
|
-
nano-brain vsearch "query" # Vector semantic search
|
|
674
|
-
nano-brain query "query" # Hybrid search (BM25 + vector + reranking)
|
|
675
|
-
nano-brain query "query" --tags=bug,fix # Filter by tags
|
|
676
|
-
nano-brain query "query" --scope=all # Cross-workspace search
|
|
677
|
-
```
|
|
228
|
+
### Prerequisites
|
|
678
229
|
|
|
679
|
-
|
|
230
|
+
- **Go 1.23+** OR pre-built binary
|
|
231
|
+
- **PostgreSQL 17** with **pgvector 0.8.2**
|
|
232
|
+
- **Ollama** (for embeddings) or any OpenAI-compatible provider
|
|
680
233
|
|
|
681
|
-
|
|
682
|
-
nano-brain write "content" # Write to daily log
|
|
683
|
-
nano-brain write "content" --tags=decision,architecture
|
|
684
|
-
nano-brain write "content" --supersedes=abc123 # Mark as replacement
|
|
685
|
-
nano-brain get <path> # Retrieve document by path
|
|
686
|
-
nano-brain get "#abc123" # Retrieve by docid
|
|
687
|
-
nano-brain tags # List all tags with counts
|
|
688
|
-
```
|
|
234
|
+
### Configure Your AI Agent
|
|
689
235
|
|
|
690
|
-
|
|
236
|
+
Add to your MCP client config (Claude Code, OpenCode, Cursor, etc.):
|
|
691
237
|
|
|
692
|
-
```
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
nano-brain
|
|
696
|
-
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"mcp": {
|
|
241
|
+
"nano-brain": {
|
|
242
|
+
"type": "http",
|
|
243
|
+
"url": "http://localhost:3100/mcp"
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
697
247
|
```
|
|
698
248
|
|
|
699
|
-
|
|
249
|
+
Optionally bind a default workspace to the connection by appending `?workspace=<name-or-hash>` to the URL (e.g. `"url": "http://localhost:3100/mcp?workspace=nano-brain"`) — tool calls can then omit the `workspace` argument. Run `nano-brain workspaces list` to see the registered name/hash for a project. An explicit `workspace` argument always overrides the connection default; the value must be a name or full hash, not `"all"`.
|
|
700
250
|
|
|
701
|
-
|
|
702
|
-
nano-brain collection add <name> <path> # Add collection
|
|
703
|
-
nano-brain collection remove <name> # Remove collection
|
|
704
|
-
nano-brain collection list # List collections
|
|
705
|
-
```
|
|
251
|
+
---
|
|
706
252
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
```bash
|
|
710
|
-
nano-brain rm --list # List all workspaces
|
|
711
|
-
nano-brain rm <workspace> --dry-run # Preview what would be deleted
|
|
712
|
-
nano-brain rm <workspace> # Remove workspace and all its data
|
|
713
|
-
# <workspace> can be: absolute path, hash prefix, or workspace name
|
|
714
|
-
```
|
|
253
|
+
## Demo
|
|
715
254
|
|
|
716
|
-
###
|
|
717
|
-
|
|
718
|
-
> **Note:** If using `nano-brain docker start`, Qdrant is already included in the compose stack. These commands manage a standalone Qdrant container separately.
|
|
255
|
+
### Query Your Codebase
|
|
719
256
|
|
|
720
257
|
```bash
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
nano-brain qdrant verify # Verify Qdrant data integrity
|
|
726
|
-
nano-brain qdrant activate # Switch to Qdrant (update config)
|
|
727
|
-
nano-brain qdrant cleanup # Remove orphaned vectors
|
|
258
|
+
# Search for authentication patterns
|
|
259
|
+
curl -X POST http://localhost:3100/api/v1/query \
|
|
260
|
+
-H "Content-Type: application/json" \
|
|
261
|
+
-d '{"workspace": "abc123", "query": "how does authentication work"}'
|
|
728
262
|
```
|
|
729
263
|
|
|
730
|
-
###
|
|
264
|
+
### Trace Call Chains
|
|
731
265
|
|
|
732
266
|
```bash
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
267
|
+
# Trace from entry point
|
|
268
|
+
curl -X POST http://localhost:3100/api/v1/graph/trace \
|
|
269
|
+
-H "Content-Type: application/json" \
|
|
270
|
+
-d '{"workspace": "abc123", "node": "main.go::main", "max_depth": 5}'
|
|
736
271
|
```
|
|
737
272
|
|
|
738
|
-
###
|
|
273
|
+
### Analyze Impact
|
|
739
274
|
|
|
740
275
|
```bash
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
276
|
+
# What breaks if I change this file?
|
|
277
|
+
curl -X POST http://localhost:3100/api/v1/graph/impact \
|
|
278
|
+
-H "Content-Type: application/json" \
|
|
279
|
+
-d '{"workspace": "abc123", "node": "src/auth/login.ts", "max_depth": 2}'
|
|
745
280
|
```
|
|
746
281
|
|
|
747
|
-
###
|
|
282
|
+
### Generate Flow Diagrams
|
|
748
283
|
|
|
749
284
|
```bash
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
nano-brain logs --clear # Delete all log files
|
|
755
|
-
nano-brain logs path # Print log directory path
|
|
285
|
+
# Get flow diagram for a controller
|
|
286
|
+
curl -X POST http://localhost:3100/api/v1/graph/flow \
|
|
287
|
+
-H "Content-Type: application/json" \
|
|
288
|
+
-d '{"workspace": "abc123", "entry": "POST /users"}'
|
|
756
289
|
```
|
|
757
290
|
|
|
758
|
-
|
|
291
|
+
Returns Mermaid flowchart:
|
|
759
292
|
|
|
760
|
-
```
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
├── vector-store.ts # Vector store abstraction (Qdrant + sqlite-vec)
|
|
767
|
-
├── search.ts # Hybrid search pipeline (RRF, reranking, blending)
|
|
768
|
-
├── chunker.ts # Heading-aware markdown chunking
|
|
769
|
-
├── collections.ts # YAML config, collection scanning
|
|
770
|
-
├── embeddings.ts # Embedding providers (VoyageAI, Ollama, OpenAI-compatible)
|
|
771
|
-
├── reranker.ts # VoyageAI reranker
|
|
772
|
-
├── expansion.ts # Query expansion (interface only, no active provider)
|
|
773
|
-
├── harvester.ts # OpenCode session → markdown converter
|
|
774
|
-
├── watcher.ts # File watcher (chokidar, dirty flags)
|
|
775
|
-
├── codebase.ts # Codebase indexing orchestrator
|
|
776
|
-
├── treesitter.ts # Tree-sitter AST parsing
|
|
777
|
-
├── symbols.ts # Symbol extraction (functions, classes, variables)
|
|
778
|
-
├── graph.ts # File dependency graph (imports/exports)
|
|
779
|
-
├── symbol-graph.ts # Symbol call graph (caller → callee)
|
|
780
|
-
├── flow-detection.ts # Call flow detection (entry → leaf)
|
|
781
|
-
├── types.ts # TypeScript interfaces
|
|
782
|
-
└── providers/ # Vector store implementations
|
|
783
|
-
├── qdrant.ts # Qdrant vector store
|
|
784
|
-
└── sqlite-vec.ts # sqlite-vec vector store
|
|
785
|
-
bin/
|
|
786
|
-
└── cli.js # CLI wrapper
|
|
787
|
-
|
|
788
|
-
test/
|
|
789
|
-
└── *.test.ts # 760+ tests (vitest)
|
|
790
|
-
SKILL.md # AI agent routing instructions (auto-loaded by OpenCode)
|
|
791
|
-
AGENTS_SNIPPET.md # Optional project-level AGENTS.md managed block
|
|
293
|
+
```mermaid
|
|
294
|
+
flowchart LR
|
|
295
|
+
POST_/users["POST /users"]
|
|
296
|
+
POST_/users --> UsersController#create
|
|
297
|
+
UsersController#create --> User.create
|
|
298
|
+
UsersController#create --> Mailer.welcome
|
|
792
299
|
```
|
|
793
300
|
|
|
794
|
-
|
|
301
|
+
---
|
|
795
302
|
|
|
796
|
-
|
|
797
|
-
- **better-sqlite3** + **sqlite-vec** for embedded storage
|
|
798
|
-
- **Qdrant** for production vector store (optional)
|
|
799
|
-
- **Tree-sitter** for AST parsing (TS, JS, Python)
|
|
800
|
-
- **@modelcontextprotocol/sdk** for MCP server (stdio/HTTP/SSE transports)
|
|
801
|
-
- **chokidar** for file watching
|
|
802
|
-
- **vitest** for testing (760+ tests)
|
|
303
|
+
## Use Cases
|
|
803
304
|
|
|
804
|
-
|
|
305
|
+
### Agent-assisted refactoring
|
|
306
|
+
Before refactoring, your agent calls `memory_impact` on the target function. Gets the full blast radius. Decides whether to split the change. After refactoring, runs affected tests only — not the full suite.
|
|
805
307
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
- **Ollama** — nomic-embed-text, mxbai-embed-large, etc. (local, free)
|
|
809
|
-
- **OpenAI-compatible** — Azure OpenAI, LM Studio, custom endpoints
|
|
308
|
+
### Multi-session feature development
|
|
309
|
+
Session 1: Agent explores the codebase, discovers patterns. `memory_write` saves findings. Session 2: Agent recalls session 1's discoveries via `memory_query`. No context lost between sessions.
|
|
810
310
|
|
|
811
|
-
|
|
812
|
-
|
|
311
|
+
### Legacy codebase onboarding
|
|
312
|
+
Index a 5-year-old codebase. Your agent can now answer "what does this function do?", "why does this class exist?", "if I change this file, what else breaks?" — without reading every file.
|
|
813
313
|
|
|
814
|
-
|
|
815
|
-
|
|
314
|
+
### Cross-service debugging
|
|
315
|
+
Agent traces a bug from frontend to backend. `memory_trace` follows the call chain across services. `memory_graph` shows which microservices depend on the failing endpoint.
|
|
816
316
|
|
|
817
|
-
|
|
317
|
+
### Team knowledge sharing
|
|
318
|
+
One server, whole team. Every developer's AI agent connects to the same PostgreSQL. Decisions, architecture notes, code intelligence — instantly shared. New hires get full context from day one.
|
|
818
319
|
|
|
819
|
-
|
|
820
|
-
|---|---|---|---|---|---|---|
|
|
821
|
-
| **Search** | Hybrid (BM25 + vector + 6 ranking signals) | Vector only | Graph traversal + vector | Semantic + BM25 | Agent-managed | Text file read |
|
|
822
|
-
| **Storage** | SQLite + Qdrant (optional) | PostgreSQL + Qdrant | Neo4j | SQLite | PostgreSQL / SQLite | Flat text files |
|
|
823
|
-
| **MCP Tools** | 22+ | 4-9 | 9-10 | 12 | 7 | 0 |
|
|
824
|
-
| **Code Intelligence** | Yes (Tree-sitter AST, symbol graph, impact analysis) | No | No | No | No | No |
|
|
825
|
-
| **Codebase Indexing** | Yes (AST → symbols → call graph → flows) | No | No | No | No | No |
|
|
826
|
-
| **Session Recall** | Yes (auto-harvests past sessions) | No | No | No | No | Limited (CLAUDE.md) |
|
|
827
|
-
| **Query Expansion** | Pipeline ready (no active provider) | No | No | No | No | No |
|
|
828
|
-
| **Neural Reranking** | Yes (VoyageAI rerank-2.5-lite) | No | No | No | No | No |
|
|
829
|
-
| **Local-First** | Yes (Ollama + sqlite-vec) | Requires OpenAI API key | Requires Docker + Neo4j | Yes | Yes | Yes |
|
|
830
|
-
| **Cloud Option** | Yes (VoyageAI, OpenAI-compatible) | Cloud API (OpenAI) | Cloud API | Local ONNX | Cloud API | None |
|
|
831
|
-
| **Privacy** | 100% local option available | Cloud API calls | Cloud or self-host | 100% local | Self-host or cloud | Local files |
|
|
832
|
-
| **Dependencies** | SQLite + embedding API (+ optional Qdrant) | Docker + PostgreSQL + Qdrant + OpenAI key | Docker + Neo4j | SQLite + ONNX | PostgreSQL | None |
|
|
833
|
-
| **Pricing** | Free (open source, MIT) | Free tier / Pro $249/mo | Free self-host / Cloud $25-475/mo | Free (Apache-2.0) | Free (Apache-2.0) | Free (with Claude) |
|
|
834
|
-
| **GitHub Stars** | New | ~47K | ~23K | ~25 | ~21K | N/A |
|
|
320
|
+
---
|
|
835
321
|
|
|
836
|
-
|
|
322
|
+
## Performance
|
|
837
323
|
|
|
838
|
-
|
|
839
|
-
- **Code intelligence** — Tree-sitter AST parsing, symbol graph, call flow detection, impact analysis
|
|
840
|
-
- **Codebase indexing** — index your source files with structural boundary detection, not just conversations
|
|
841
|
-
- **Session recall** — automatically harvests and indexes past AI coding sessions
|
|
842
|
-
- **Flexible deployment** — 100% local (Ollama + sqlite-vec) or cloud (VoyageAI + Qdrant)
|
|
843
|
-
- **Privacy-first** — local processing option, your code never leaves your machine
|
|
324
|
+
### Search Quality vs Competitors
|
|
844
325
|
|
|
845
|
-
|
|
326
|
+
| Metric | nano-brain | LlamaIndex | Qdrant/Mem0 | Cognee | GraphRAG | Zep |
|
|
327
|
+
|--------|------------|------------|-------------|--------|----------|-----|
|
|
328
|
+
| P@5 | **80%** | 55% | 27% | — | — | — |
|
|
329
|
+
| MRR | **95%** | — | — | — | — | — |
|
|
330
|
+
| Latency | **42ms** | — | — | — | — | — |
|
|
331
|
+
| Code Intelligence | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
332
|
+
| Symbol Graph | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
333
|
+
| Impact Analysis | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
334
|
+
| Flow Diagrams | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
846
335
|
|
|
847
|
-
-
|
|
848
|
-
- You want a full agent framework, not just memory (Letta)
|
|
849
|
-
- You need cloud-hosted memory shared across teams (Mem0 Cloud)
|
|
850
|
-
- You only need basic session notes (Claude native memory)
|
|
336
|
+
Tested on 60 domain-specific queries across 3 workspaces. nano-brain is the **only** solution with code intelligence — competitors focus on conversation memory and document retrieval.
|
|
851
337
|
|
|
852
|
-
|
|
338
|
+
### Competitive Landscape
|
|
853
339
|
|
|
854
|
-
|
|
340
|
+
**What competitors offer:**
|
|
341
|
+
- **Mem0 / Zep** — Conversation memory, temporal ranking, chat history recall
|
|
342
|
+
- **Cognee / GraphRAG** — Document-level knowledge graphs, multi-hop reasoning
|
|
343
|
+
- **LlamaIndex** — Flexible RAG pipelines, document retrieval
|
|
855
344
|
|
|
856
|
-
|
|
857
|
-
- **
|
|
858
|
-
- **
|
|
859
|
-
- **
|
|
345
|
+
**What nano-brain adds (agent-oriented):**
|
|
346
|
+
- **Impact analysis** — "What breaks if I change this?" — the #1 question agents ask. Pre-computed blast radius in <50ms.
|
|
347
|
+
- **Call chain tracing** — Follow execution paths across files. Agent gets a structured trace, not raw source.
|
|
348
|
+
- **Symbol graph** — Find definitions, callers, callees. `memory_symbols` + `memory_graph`.
|
|
349
|
+
- **Agent-oriented benchmarks** — Measures how well agents find context for domain tasks — not just search precision in isolation.
|
|
860
350
|
|
|
861
|
-
|
|
351
|
+
**The difference:** Competitors optimize for "did the agent find the right document?" nano-brain optimizes for "did the agent understand the codebase well enough to make the right change?"
|
|
862
352
|
|
|
863
|
-
|
|
353
|
+
At 50ms latency, agents run impact analysis on every edit. At 500ms, they skip it. nano-brain is designed for the 50ms world.
|
|
864
354
|
|
|
865
|
-
###
|
|
355
|
+
### Agent-Oriented Capability Benchmarks
|
|
866
356
|
|
|
867
|
-
|
|
357
|
+
nano-brain is built for agents. These benchmarks measure how well agents can **find relevant context for real-world domain tasks** using nano-brain's MCP tools — not just search quality in isolation.
|
|
868
358
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
359
|
+
Each benchmark runs a deterministic agent workflow:
|
|
360
|
+
1. **query_question** — natural-language domain question
|
|
361
|
+
2. **query_input** — optimized search query
|
|
362
|
+
3. **symbols_identifiers** — symbol lookup for known identifiers
|
|
872
363
|
|
|
873
|
-
This
|
|
364
|
+
This mimics how a real agent explores a codebase: broad understanding first, then targeted retrieval.
|
|
874
365
|
|
|
875
|
-
|
|
366
|
+
#### Scores
|
|
876
367
|
|
|
877
|
-
|
|
368
|
+
| Workspace | Domain | Overall | Multi-tool | Search-QA | Symbol-Lookup |
|
|
369
|
+
|-----------|--------|---------|------------|-----------|---------------|
|
|
370
|
+
| **nano-brain** | Go daemon | **1.000** | 1.000 | 1.000 | 1.000 |
|
|
371
|
+
| **TypeScript** | CS2 item trading | **0.885** | 1.000 | 0.817 | 1.000 |
|
|
372
|
+
| **Rails** | CS2 item trading | **0.795** | 1.000 | 0.726 | 0.667 |
|
|
878
373
|
|
|
879
|
-
|
|
374
|
+
**What this means:**
|
|
375
|
+
- **Multi-tool 1.000** — When agents combine search + symbols, they find every expected context item
|
|
376
|
+
- **Overall 0.885** — TypeScript workspace: agent finds 88.5% of expected domain artifacts
|
|
377
|
+
- **Fixed vs Agent** — Agent workflow improves recall by 15-40% over single-tool queries
|
|
378
|
+
- **Unique capability** — No competitor offers agent-oriented benchmarks or code intelligence
|
|
880
379
|
|
|
881
|
-
|
|
380
|
+
#### How to Run
|
|
882
381
|
|
|
883
|
-
|
|
382
|
+
```bash
|
|
383
|
+
# TypeScript workspace (CS2 item trading domain)
|
|
384
|
+
NANO_BRAIN_URL=http://localhost:3100 \
|
|
385
|
+
NANO_BRAIN_WORKSPACE=<your-workspace-hash> \
|
|
386
|
+
go test -v -tags=capbench -run TestCapabilityBenchmark \
|
|
387
|
+
./benchmarks/typescript/capability/
|
|
884
388
|
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
interval_ms: 3600000 # Consolidation interval (60 min)
|
|
897
|
-
model: gpt-4o-mini # LLM model for consolidation
|
|
898
|
-
endpoint: https://api.openai.com/v1 # OpenAI-compatible endpoint
|
|
899
|
-
apiKey: sk-... # API key (not required for Ollama)
|
|
900
|
-
provider: openai # 'openai' (default) or 'ollama'
|
|
901
|
-
|
|
902
|
-
extraction:
|
|
903
|
-
enabled: true # Enable fact extraction from sessions
|
|
904
|
-
model: gpt-4o-mini # LLM model for extraction
|
|
905
|
-
endpoint: https://api.openai.com/v1
|
|
906
|
-
apiKey: sk-...
|
|
907
|
-
maxFactsPerSession: 20 # Max facts to extract per session
|
|
908
|
-
|
|
909
|
-
importance:
|
|
910
|
-
enabled: true # Enable importance scoring
|
|
911
|
-
weight: 0.1 # Importance boost weight
|
|
912
|
-
decay_half_life_days: 30
|
|
913
|
-
|
|
914
|
-
intents:
|
|
915
|
-
enabled: true # Enable query intent classification
|
|
389
|
+
# Rails workspace (CS2 item trading domain)
|
|
390
|
+
NANO_BRAIN_URL=http://localhost:3100 \
|
|
391
|
+
NANO_BRAIN_WORKSPACE=<your-workspace-hash> \
|
|
392
|
+
go test -v -tags=capbench -run TestCapabilityBenchmark \
|
|
393
|
+
./benchmarks/rails/capability/
|
|
394
|
+
|
|
395
|
+
# nano-brain itself (Go daemon)
|
|
396
|
+
NANO_BRAIN_URL=http://localhost:3100 \
|
|
397
|
+
NANO_BRAIN_WORKSPACE=nano-brain \
|
|
398
|
+
go test -v -tags=capbench -run TestCapabilityBenchmark \
|
|
399
|
+
./benchmarks/capability/
|
|
916
400
|
```
|
|
917
401
|
|
|
918
|
-
|
|
402
|
+
#### Task Categories
|
|
919
403
|
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
404
|
+
| Category | What It Tests | Tools Used |
|
|
405
|
+
|----------|---------------|------------|
|
|
406
|
+
| **search-qa** | Domain concept retrieval via search | `query_question`, `query_input` |
|
|
407
|
+
| **symbol-lookup** | Known identifier resolution | `query_input`, `symbols_identifiers` |
|
|
408
|
+
| **multi-tool** | Cross-tool workflow (search → symbols) | All three tools in sequence |
|
|
925
409
|
|
|
926
|
-
|
|
410
|
+
See individual benchmark READMEs for full task breakdowns:
|
|
411
|
+
- [`benchmarks/typescript/capability/README.md`](benchmarks/typescript/capability/README.md)
|
|
412
|
+
- [`benchmarks/rails/capability/README.md`](benchmarks/rails/capability/README.md)
|
|
413
|
+
- [`benchmarks/capability/README.md`](benchmarks/capability/README.md)
|
|
927
414
|
|
|
928
|
-
|
|
929
|
-
- `nano-brain consolidate` — Trigger a manual consolidation cycle
|
|
415
|
+
---
|
|
930
416
|
|
|
931
|
-
|
|
417
|
+
## Ruby / Rails Support
|
|
932
418
|
|
|
933
|
-
-
|
|
934
|
-
- `memory_consolidation_status` — View consolidation queue stats and recent logs
|
|
935
|
-
- `memory_importance` — View document importance scores
|
|
936
|
-
- `memory_status` — View learning system status (telemetry records, bandit variants, config version)
|
|
419
|
+
nano-brain supports Ruby and Ruby on Rails code intelligence:
|
|
937
420
|
|
|
938
|
-
|
|
421
|
+
- **Rails routes** — `resources`, `get`/`post`/`patch`/`put`/`delete`, `namespace`
|
|
422
|
+
- **Control-flow graphs** — `if`/`else`, loops, `begin`/`rescue`, method defs
|
|
423
|
+
- **Cross-file resolution** — Class→file index, resolver, reconcile edges
|
|
424
|
+
- **Flow diagrams** — Controller→service→model chains (20-34 nodes)
|
|
939
425
|
|
|
940
|
-
|
|
426
|
+
Example flow for a Rails controller action:
|
|
941
427
|
|
|
942
|
-
|
|
428
|
+
```mermaid
|
|
429
|
+
flowchart LR
|
|
430
|
+
POST_/users["POST /users"]
|
|
431
|
+
POST_/users --> UsersController#create
|
|
432
|
+
UsersController#create --> User.create
|
|
433
|
+
UsersController#create --> Mailer.welcome
|
|
434
|
+
```
|
|
943
435
|
|
|
944
|
-
|
|
436
|
+
---
|
|
945
437
|
|
|
946
|
-
|
|
947
|
-
- Background job runs every 6 hours
|
|
948
|
-
- Soft-deletes contradicted entities after 30 days (when newer information supersedes them)
|
|
949
|
-
- Soft-deletes orphan entities after 90 days (entities with no relationships)
|
|
950
|
-
- Hard-deletes soft-deleted entities after 30-day retention period
|
|
951
|
-
- Processes in batches of 100 to avoid SQLite lock contention
|
|
438
|
+
## Tech Stack
|
|
952
439
|
|
|
953
|
-
**
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
440
|
+
- **Go 1.23** — Single static binary (`CGO_ENABLED=0`)
|
|
441
|
+
- **PostgreSQL 17** — Full-text search (tsvector/tsquery)
|
|
442
|
+
- **pgvector 0.8.2** — HNSW vector indexing
|
|
443
|
+
- **Echo v4** — HTTP framework
|
|
444
|
+
- **sqlc** — Type-safe SQL code generation
|
|
445
|
+
- **goose v3** — Database migrations
|
|
446
|
+
- **zerolog** — Structured JSON logging
|
|
447
|
+
- **koanf** — YAML + env configuration
|
|
448
|
+
- **fsnotify** — File system watching
|
|
449
|
+
|
|
450
|
+
---
|
|
963
451
|
|
|
964
|
-
|
|
452
|
+
## Configuration
|
|
965
453
|
|
|
966
|
-
|
|
454
|
+
Config file: `~/.nano-brain/config.yml`
|
|
967
455
|
|
|
968
|
-
|
|
456
|
+
```yaml
|
|
457
|
+
server:
|
|
458
|
+
host: localhost
|
|
459
|
+
port: 3100
|
|
969
460
|
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
- Uses the same LLM provider configured for consolidation (same endpoint/model/apiKey)
|
|
973
|
-
- Adds tags prefixed with `llm:` (e.g., `llm:architecture-decision`, `llm:debugging-insight`)
|
|
974
|
-
- Only processes documents under 2000 characters (configurable)
|
|
975
|
-
- Requires confidence threshold of 0.6 or higher (configurable)
|
|
461
|
+
database:
|
|
462
|
+
url: postgres://nanobrain:nanobrain@localhost:5432/nanobrain_dev
|
|
976
463
|
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
4. `llm:pattern` — Reusable code patterns, best practices
|
|
982
|
-
5. `llm:preference` — User preferences, workflow choices
|
|
983
|
-
6. `llm:context` — Background information, explanations
|
|
984
|
-
7. `llm:workflow` — Process documentation, how-to guides
|
|
464
|
+
embedding:
|
|
465
|
+
provider: ollama
|
|
466
|
+
url: http://localhost:11434
|
|
467
|
+
model: nomic-embed-text
|
|
985
468
|
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
confidence_threshold: 0.6 # Minimum confidence to apply a category
|
|
991
|
-
max_content_length: 2000 # Skip documents longer than this
|
|
469
|
+
search:
|
|
470
|
+
rrf_k: 60
|
|
471
|
+
recency_weight: 0.3
|
|
472
|
+
limit: 20
|
|
992
473
|
```
|
|
993
474
|
|
|
994
|
-
|
|
475
|
+
See [Configuration](docs/CONFIGURATION.md) for full options.
|
|
995
476
|
|
|
996
|
-
|
|
477
|
+
---
|
|
997
478
|
|
|
998
|
-
|
|
479
|
+
## Documentation
|
|
999
480
|
|
|
1000
|
-
|
|
1001
|
-
-
|
|
1002
|
-
-
|
|
1003
|
-
-
|
|
1004
|
-
-
|
|
1005
|
-
-
|
|
481
|
+
- [Getting Started](docs/GETTING_STARTED.md) — Step-by-step setup guide
|
|
482
|
+
- [Configuration](docs/CONFIGURATION.md) — All config options
|
|
483
|
+
- [REST API](docs/API.md) — HTTP endpoints
|
|
484
|
+
- [CLI Commands](docs/CLI.md) — Command reference
|
|
485
|
+
- [MCP Tools](docs/MCP.md) — Tool documentation
|
|
486
|
+
- [Architecture](docs/ARCHITECTURE.md) — System design
|
|
487
|
+
- [Changelog](CHANGELOG.md) — What's new
|
|
488
|
+
- [Roadmap](docs/ROADMAP.md) — What's planned
|
|
489
|
+
- [Feature Showcase](docs/FEATURES.md) — Visual examples
|
|
1006
490
|
|
|
1007
|
-
|
|
491
|
+
---
|
|
1008
492
|
|
|
1009
|
-
|
|
1010
|
-
```yaml
|
|
1011
|
-
preferences:
|
|
1012
|
-
enabled: true
|
|
1013
|
-
min_queries: 20 # Minimum queries before personalization kicks in
|
|
1014
|
-
weight_min: 0.5 # Minimum category weight (demotion)
|
|
1015
|
-
weight_max: 2.0 # Maximum category weight (boost)
|
|
1016
|
-
baseline_expand_rate: 0.1 # Expected expand rate (10%)
|
|
1017
|
-
```
|
|
493
|
+
## Contributing
|
|
1018
494
|
|
|
1019
|
-
|
|
495
|
+
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
1020
496
|
|
|
1021
|
-
|
|
497
|
+
### Development Setup
|
|
1022
498
|
|
|
1023
|
-
|
|
499
|
+
```bash
|
|
500
|
+
# Clone the repo
|
|
501
|
+
git clone https://github.com/nano-step/nano-brain.git
|
|
502
|
+
cd nano-brain
|
|
503
|
+
|
|
504
|
+
# Build
|
|
505
|
+
CGO_ENABLED=0 go build -o nano-brain ./cmd/nano-brain
|
|
1024
506
|
|
|
1025
|
-
|
|
507
|
+
# Run tests
|
|
508
|
+
go test -race -short ./...
|
|
1026
509
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
4. **Predictions**: When you ask about topic A, nano-brain predicts you'll need topic B next
|
|
510
|
+
# Run integration tests (requires PostgreSQL)
|
|
511
|
+
go test -race -tags=integration ./...
|
|
512
|
+
```
|
|
1031
513
|
|
|
1032
|
-
###
|
|
514
|
+
### Project Structure
|
|
1033
515
|
|
|
1034
|
-
```
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
516
|
+
```
|
|
517
|
+
nano-brain/
|
|
518
|
+
├── cmd/nano-brain/ # CLI dispatcher + server startup
|
|
519
|
+
├── internal/
|
|
520
|
+
│ ├── config/ # Configuration management
|
|
521
|
+
│ ├── server/ # HTTP server + handlers
|
|
522
|
+
│ ├── storage/ # PostgreSQL + sqlc
|
|
523
|
+
│ ├── search/ # Hybrid search pipeline
|
|
524
|
+
│ ├── embed/ # Embedding queue
|
|
525
|
+
│ ├── watcher/ # File system watcher
|
|
526
|
+
│ ├── harvest/ # Session harvesting
|
|
527
|
+
│ ├── mcp/ # MCP protocol tools
|
|
528
|
+
│ ├── graph/ # Code intelligence
|
|
529
|
+
│ └── ...
|
|
530
|
+
├── migrations/ # Database migrations
|
|
531
|
+
└── benchmarks/ # Performance benchmarks
|
|
1043
532
|
```
|
|
1044
533
|
|
|
1045
|
-
|
|
534
|
+
---
|
|
1046
535
|
|
|
1047
|
-
|
|
1048
|
-
- `context` (optional): Current query or topic
|
|
1049
|
-
- `workspace` (optional): Workspace path
|
|
1050
|
-
- `limit` (optional): Max suggestions (default 3)
|
|
536
|
+
## Community
|
|
1051
537
|
|
|
1052
|
-
|
|
538
|
+
- [GitHub Discussions](https://github.com/nano-step/nano-brain/discussions) — Ask questions, share ideas
|
|
539
|
+
- [Discord](https://discord.gg/nano-brain) — Real-time chat
|
|
540
|
+
- [Twitter](https://twitter.com/nano_brain) — Updates and announcements
|
|
1053
541
|
|
|
1054
|
-
|
|
542
|
+
---
|
|
1055
543
|
|
|
1056
|
-
|
|
544
|
+
## License
|
|
1057
545
|
|
|
1058
|
-
|
|
546
|
+
MIT — see [LICENSE](LICENSE) for details.
|
|
1059
547
|
|
|
1060
|
-
|
|
548
|
+
---
|
|
1061
549
|
|
|
1062
|
-
##
|
|
550
|
+
## Acknowledgments
|
|
1063
551
|
|
|
1064
|
-
|
|
552
|
+
Built with:
|
|
553
|
+
- [Go](https://go.dev/) — Fast, statically typed language
|
|
554
|
+
- [PostgreSQL](https://www.postgresql.org/) — The world's most advanced open source database
|
|
555
|
+
- [pgvector](https://github.com/pgvector/pgvector) — Open-source vector similarity search
|
|
556
|
+
- [Echo](https://echo.labstack.com/) — High performance, extensible, minimalist Go web framework
|
|
557
|
+
- [sqlc](https://sqlc.dev/) — Generate type-safe code from SQL
|
|
558
|
+
- [goose](https://github.com/pressly/goose) — Database migration tool
|
|
559
|
+
- [zerolog](https://github.com/rs/zerolog) — Zero allocation JSON logger
|
|
560
|
+
- [koanf](https://github.com/knadh/koanf) — Configuration manager
|
|
561
|
+
- [fsnotify](https://github.com/fsnotify/fsnotify) — Cross-platform file system notifications
|