@nano-step/nano-brain 2026.1.14

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.
Files changed (93) hide show
  1. package/.opencode/command/nano-brain-init.md +13 -0
  2. package/.opencode/command/nano-brain-reindex.md +11 -0
  3. package/.opencode/command/nano-brain-status.md +12 -0
  4. package/AGENTS.md +41 -0
  5. package/AGENTS_SNIPPET.md +44 -0
  6. package/CHANGELOG.md +186 -0
  7. package/README.md +298 -0
  8. package/SKILL.md +109 -0
  9. package/bin/cli.js +29 -0
  10. package/commands/nano-brain-init.md +36 -0
  11. package/commands/nano-brain-reindex.md +31 -0
  12. package/commands/nano-brain-status.md +32 -0
  13. package/index.html +929 -0
  14. package/nano-brain +4 -0
  15. package/opencode-mcp.json +9 -0
  16. package/openspec/changes/archive/2026-02-16-fix-mcp-server-bugs/.openspec.yaml +2 -0
  17. package/openspec/changes/archive/2026-02-16-fix-mcp-server-bugs/design.md +68 -0
  18. package/openspec/changes/archive/2026-02-16-fix-mcp-server-bugs/proposal.md +27 -0
  19. package/openspec/changes/archive/2026-02-16-fix-mcp-server-bugs/specs/mcp-integration-testing/spec.md +50 -0
  20. package/openspec/changes/archive/2026-02-16-fix-mcp-server-bugs/specs/mcp-server/spec.md +40 -0
  21. package/openspec/changes/archive/2026-02-16-fix-mcp-server-bugs/specs/search-pipeline/spec.md +29 -0
  22. package/openspec/changes/archive/2026-02-16-fix-mcp-server-bugs/tasks.md +37 -0
  23. package/openspec/changes/archive/2026-02-23-workspace-scoped-memory-and-storage-limits/.openspec.yaml +2 -0
  24. package/openspec/changes/archive/2026-02-23-workspace-scoped-memory-and-storage-limits/design.md +111 -0
  25. package/openspec/changes/archive/2026-02-23-workspace-scoped-memory-and-storage-limits/proposal.md +30 -0
  26. package/openspec/changes/archive/2026-02-23-workspace-scoped-memory-and-storage-limits/specs/mcp-server/spec.md +33 -0
  27. package/openspec/changes/archive/2026-02-23-workspace-scoped-memory-and-storage-limits/specs/storage-limits/spec.md +90 -0
  28. package/openspec/changes/archive/2026-02-23-workspace-scoped-memory-and-storage-limits/specs/workspace-scoping/spec.md +66 -0
  29. package/openspec/changes/archive/2026-02-23-workspace-scoped-memory-and-storage-limits/tasks.md +199 -0
  30. package/openspec/changes/codebase-indexing/.openspec.yaml +2 -0
  31. package/openspec/changes/codebase-indexing/design.md +169 -0
  32. package/openspec/changes/codebase-indexing/proposal.md +30 -0
  33. package/openspec/changes/codebase-indexing/specs/codebase-collection/spec.md +187 -0
  34. package/openspec/changes/codebase-indexing/specs/mcp-server/spec.md +36 -0
  35. package/openspec/changes/codebase-indexing/tasks.md +56 -0
  36. package/openspec/changes/fix-session-harvest-workspace-scoping/.openspec.yaml +2 -0
  37. package/openspec/changes/fix-session-harvest-workspace-scoping/design.md +84 -0
  38. package/openspec/changes/fix-session-harvest-workspace-scoping/proposal.md +26 -0
  39. package/openspec/changes/fix-session-harvest-workspace-scoping/specs/workspace-scoping/spec.md +65 -0
  40. package/openspec/changes/fix-session-harvest-workspace-scoping/tasks.md +33 -0
  41. package/openspec/changes/performance-and-search-quality/.openspec.yaml +2 -0
  42. package/openspec/changes/performance-and-search-quality/proposal.md +37 -0
  43. package/openspec/specs/mcp-integration-testing/spec.md +50 -0
  44. package/openspec/specs/mcp-server/spec.md +75 -0
  45. package/openspec/specs/search-pipeline/spec.md +29 -0
  46. package/openspec/specs/storage-limits/spec.md +94 -0
  47. package/openspec/specs/workspace-scoping/spec.md +70 -0
  48. package/package.json +37 -0
  49. package/site/build.js +66 -0
  50. package/site/partials/_api.html +83 -0
  51. package/site/partials/_compare.html +100 -0
  52. package/site/partials/_config.html +23 -0
  53. package/site/partials/_features.html +43 -0
  54. package/site/partials/_footer.html +6 -0
  55. package/site/partials/_hero.html +9 -0
  56. package/site/partials/_how-it-works.html +26 -0
  57. package/site/partials/_models.html +18 -0
  58. package/site/partials/_quick-start.html +15 -0
  59. package/site/partials/_stats.html +1 -0
  60. package/site/partials/_tech-stack.html +13 -0
  61. package/site/script.js +12 -0
  62. package/site/shell.html +44 -0
  63. package/site/styles.css +548 -0
  64. package/src/chunker.ts +427 -0
  65. package/src/codebase.ts +425 -0
  66. package/src/collections.ts +217 -0
  67. package/src/embeddings.ts +325 -0
  68. package/src/expansion.ts +79 -0
  69. package/src/harvester.ts +306 -0
  70. package/src/index.ts +778 -0
  71. package/src/reranker.ts +103 -0
  72. package/src/search.ts +294 -0
  73. package/src/server.ts +876 -0
  74. package/src/storage.ts +221 -0
  75. package/src/store.ts +653 -0
  76. package/src/types.ts +215 -0
  77. package/src/watcher.ts +389 -0
  78. package/test/chunker.test.ts +479 -0
  79. package/test/cli.test.ts +309 -0
  80. package/test/codebase-chunker.test.ts +446 -0
  81. package/test/codebase.test.ts +678 -0
  82. package/test/collections.test.ts +571 -0
  83. package/test/harvester.test.ts +636 -0
  84. package/test/integration.test.ts +219 -0
  85. package/test/llm.test.ts +322 -0
  86. package/test/search.test.ts +572 -0
  87. package/test/server.test.ts +541 -0
  88. package/test/storage.test.ts +302 -0
  89. package/test/store.test.ts +530 -0
  90. package/test/watcher.test.ts +717 -0
  91. package/test/workspace.test.ts +239 -0
  92. package/tsconfig.json +19 -0
  93. package/vitest.config.ts +16 -0
@@ -0,0 +1,70 @@
1
+ # workspace-scoping Specification
2
+
3
+ ## Purpose
4
+ TBD - created by archiving change workspace-scoped-memory-and-storage-limits. Update Purpose after archive.
5
+ ## Requirements
6
+ ### Requirement: Workspace detection from PWD
7
+ The MCP server SHALL compute a `projectHash` from `process.cwd()` at startup using `sha256(cwd).substring(0, 12)`. This hash SHALL be stored as `currentProjectHash` on the server context and used for all default search filtering.
8
+
9
+ #### Scenario: Server starts in a workspace directory
10
+ - **WHEN** the MCP server starts with `PWD=/Users/alice/projects/my-app`
11
+ - **THEN** `currentProjectHash` is set to the first 12 characters of `sha256("/Users/alice/projects/my-app")`
12
+ - **THEN** the hash is consistent across restarts in the same directory
13
+
14
+ #### Scenario: Hash matches harvester convention
15
+ - **WHEN** the MCP server computes `currentProjectHash` for a workspace
16
+ - **THEN** the hash matches the directory name used by the harvester for that workspace's sessions (`sessions/{projectHash}/*.md`)
17
+
18
+ ### Requirement: Document-level project tagging
19
+ The `documents` table SHALL have a `project_hash TEXT` column. Every document indexed from a session file SHALL be tagged with the projectHash extracted from its file path. Non-session documents (MEMORY.md, daily logs) SHALL be tagged with `'global'`.
20
+
21
+ #### Scenario: New document indexed from session file
22
+ - **WHEN** a document is indexed from path `sessions/abc123def456/session-title.md`
23
+ - **THEN** the document's `project_hash` column is set to `abc123def456`
24
+
25
+ #### Scenario: New document indexed from non-session file
26
+ - **WHEN** a document is indexed from `MEMORY.md` or a daily log file
27
+ - **THEN** the document's `project_hash` column is set to `'global'`
28
+
29
+ #### Scenario: Document path does not match session pattern
30
+ - **WHEN** a document is indexed from a path that does not match `sessions/{hash}/*.md`
31
+ - **THEN** the document's `project_hash` column is set to `'global'`
32
+
33
+ ### Requirement: Database migration for existing documents
34
+ On startup, the store SHALL add the `project_hash` column if it does not exist, then backfill existing documents by extracting the projectHash from their file paths.
35
+
36
+ #### Scenario: First startup after upgrade
37
+ - **WHEN** the store opens a database that lacks the `project_hash` column
38
+ - **THEN** the column is added via `ALTER TABLE documents ADD COLUMN project_hash TEXT DEFAULT 'global'`
39
+ - **THEN** existing documents with paths matching `sessions/{hash}/*.md` are updated with the correct projectHash
40
+ - **THEN** existing documents not matching the pattern retain `project_hash = 'global'`
41
+
42
+ #### Scenario: Subsequent startup
43
+ - **WHEN** the store opens a database that already has the `project_hash` column
44
+ - **THEN** no migration runs
45
+ - **THEN** no data is modified
46
+
47
+ ### Requirement: Default search scoping to current workspace
48
+ All search operations SHALL filter results to documents matching `currentProjectHash` or `'global'` by default. This ensures searches return only results relevant to the current workspace plus cross-project notes.
49
+
50
+ #### Scenario: Search without workspace parameter
51
+ - **WHEN** `memory_search` is called with `{"query": "authentication"}` and no `workspace` parameter
52
+ - **THEN** only documents with `project_hash = currentProjectHash` or `project_hash = 'global'` are returned
53
+ - **THEN** documents from other workspaces are excluded
54
+
55
+ #### Scenario: Global documents always included
56
+ - **WHEN** a search is performed with default workspace scoping
57
+ - **THEN** MEMORY.md entries and daily logs (tagged `'global'`) are included in results
58
+ - **THEN** session documents from other workspaces are excluded
59
+
60
+ ### Requirement: Cross-workspace search opt-in
61
+ All search tools SHALL accept an optional `workspace` parameter. When set to `"all"`, search results SHALL include documents from all workspaces. When set to a specific hash, results SHALL be filtered to that workspace plus `'global'`.
62
+
63
+ #### Scenario: Search with workspace="all"
64
+ - **WHEN** `memory_search` is called with `{"query": "auth", "workspace": "all"}`
65
+ - **THEN** documents from all workspaces are included in results
66
+
67
+ #### Scenario: Search with specific workspace hash
68
+ - **WHEN** `memory_search` is called with `{"query": "auth", "workspace": "abc123def456"}`
69
+ - **THEN** only documents with `project_hash = 'abc123def456'` or `project_hash = 'global'` are returned
70
+
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@nano-step/nano-brain",
3
+ "version": "2026.1.14",
4
+ "type": "module",
5
+ "bin": {
6
+ "nano-brain": "./bin/cli.js"
7
+ },
8
+ "main": "src/index.ts",
9
+ "scripts": {
10
+ "dev": "bun src/index.ts",
11
+ "start": "node bin/cli.js",
12
+ "mcp": "node bin/cli.js mcp",
13
+ "test": "vitest run",
14
+ "test:watch": "vitest",
15
+ "lint:esm": "! grep -r 'require(' src/ --include='*.ts'"
16
+ },
17
+ "dependencies": {
18
+ "@modelcontextprotocol/sdk": "^1.26.0",
19
+ "better-sqlite3": "^12.6.2",
20
+ "chokidar": "^5.0.0",
21
+ "fast-glob": "^3.3.3",
22
+ "node-llama-cpp": "^3.3.3",
23
+ "sqlite-vec": "^0.1.7-alpha.2",
24
+ "tsx": "^4.21.0",
25
+ "yaml": "^2.8.2",
26
+ "zod": "^4.3.6"
27
+ },
28
+ "devDependencies": {
29
+ "@types/better-sqlite3": "^7.6.13",
30
+ "bun-types": "^1.3.9",
31
+ "typescript": "^5.9.3",
32
+ "vitest": "^4.0.18"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ }
37
+ }
package/site/build.js ADDED
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { readFileSync, writeFileSync, readdirSync, watchFile, statSync } from 'node:fs'
4
+ import { join, dirname, resolve } from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+
7
+ const __filename = fileURLToPath(import.meta.url)
8
+ const __dirname = dirname(__filename)
9
+
10
+ const SITE_DIR = __dirname
11
+ const ROOT_DIR = resolve(SITE_DIR, '..')
12
+ const PARTIALS_DIR = join(SITE_DIR, 'partials')
13
+ const OUTPUT = join(ROOT_DIR, 'index.html')
14
+
15
+ function readFile(path) {
16
+ return readFileSync(path, 'utf-8')
17
+ }
18
+
19
+ function build() {
20
+ const start = Date.now()
21
+
22
+ let shell = readFile(join(SITE_DIR, 'shell.html'))
23
+ const styles = readFile(join(SITE_DIR, 'styles.css'))
24
+ const script = readFile(join(SITE_DIR, 'script.js'))
25
+
26
+ shell = shell.replace('{{styles}}', styles)
27
+ shell = shell.replace('{{script}}', script)
28
+
29
+ shell = shell.replace(/\{\{partial:([a-z0-9-]+)\}\}/g, (_match, name) => {
30
+ const partialPath = join(PARTIALS_DIR, `_${name}.html`)
31
+ try {
32
+ return readFile(partialPath).trimEnd()
33
+ } catch (err) {
34
+ console.error(` ❌ Missing partial: ${partialPath}`)
35
+ process.exit(1)
36
+ }
37
+ })
38
+
39
+ writeFileSync(OUTPUT, shell, 'utf-8')
40
+
41
+ const size = statSync(OUTPUT).size
42
+ const kb = (size / 1024).toFixed(1)
43
+ const ms = Date.now() - start
44
+ console.log(` ✅ Built index.html (${kb} KB) in ${ms}ms`)
45
+ }
46
+
47
+ console.log('🔨 Building nano-brain landing page...')
48
+ build()
49
+
50
+ if (process.argv.includes('--watch')) {
51
+ console.log('👀 Watching for changes...')
52
+
53
+ const watchTargets = [
54
+ join(SITE_DIR, 'shell.html'),
55
+ join(SITE_DIR, 'styles.css'),
56
+ join(SITE_DIR, 'script.js'),
57
+ ...readdirSync(PARTIALS_DIR).map((f) => join(PARTIALS_DIR, f)),
58
+ ]
59
+
60
+ for (const file of watchTargets) {
61
+ watchFile(file, { interval: 300 }, () => {
62
+ console.log(` 🔄 Changed: ${file.replace(ROOT_DIR + '/', '')}`)
63
+ build()
64
+ })
65
+ }
66
+ }
@@ -0,0 +1,83 @@
1
+ <section id="api" class="fade-in">
2
+ <h2 class="section-title">API Reference</h2>
3
+ <p class="section-subtitle">MCP tools for hybrid search, retrieval, and maintenance.</p>
4
+ <div class="grid api-grid">
5
+ <div class="api-card">
6
+ <h4><span class="chip">memory_search</span></h4>
7
+ <p>BM25 keyword search.</p>
8
+ <div class="params">
9
+ <span class="chip">query (required)</span>
10
+ <span class="chip">limit (default 10)</span>
11
+ <span class="chip">collection</span>
12
+ <span class="chip">workspace</span>
13
+ </div>
14
+ </div>
15
+ <div class="api-card">
16
+ <h4><span class="chip">memory_vsearch</span></h4>
17
+ <p>Semantic vector search using embeddings.</p>
18
+ <div class="params">
19
+ <span class="chip">query (required)</span>
20
+ <span class="chip">limit (default 10)</span>
21
+ <span class="chip">collection</span>
22
+ <span class="chip">workspace</span>
23
+ </div>
24
+ </div>
25
+ <div class="api-card">
26
+ <h4><span class="chip">memory_query</span></h4>
27
+ <p>Full hybrid search with query expansion, RRF fusion, and LLM reranking.</p>
28
+ <div class="params">
29
+ <span class="chip">query (required)</span>
30
+ <span class="chip">limit (default 10)</span>
31
+ <span class="chip">collection</span>
32
+ <span class="chip">minScore</span>
33
+ <span class="chip">workspace</span>
34
+ </div>
35
+ </div>
36
+ <div class="api-card">
37
+ <h4><span class="chip">memory_get</span></h4>
38
+ <p>Retrieve document by path or docid (#abc123).</p>
39
+ <div class="params">
40
+ <span class="chip">id (required)</span>
41
+ <span class="chip">fromLine</span>
42
+ <span class="chip">maxLines</span>
43
+ </div>
44
+ </div>
45
+ <div class="api-card">
46
+ <h4><span class="chip">memory_multi_get</span></h4>
47
+ <p>Batch retrieve by glob pattern.</p>
48
+ <div class="params">
49
+ <span class="chip">pattern (required)</span>
50
+ <span class="chip">maxBytes (default 50000)</span>
51
+ </div>
52
+ </div>
53
+ <div class="api-card">
54
+ <h4><span class="chip">memory_write</span></h4>
55
+ <p>Write to daily log or MEMORY.md.</p>
56
+ <div class="params">
57
+ <span class="chip">content (required)</span>
58
+ <span class="chip">target ("daily" or "memory")</span>
59
+ </div>
60
+ </div>
61
+ <div class="api-card">
62
+ <h4><span class="chip">memory_status</span></h4>
63
+ <p>Show index health, collections, model status.</p>
64
+ <div class="params">
65
+ <span class="chip">no params</span>
66
+ </div>
67
+ </div>
68
+ <div class="api-card">
69
+ <h4><span class="chip">memory_update</span></h4>
70
+ <p>Trigger immediate reindex of all collections.</p>
71
+ <div class="params">
72
+ <span class="chip">no params</span>
73
+ </div>
74
+ <div class="api-card">
75
+ <h4><span class="chip">memory_index_codebase</span></h4>
76
+ <p>Index source files in the current workspace.</p>
77
+ <div class="params">
78
+ <span class="chip">root (optional)</span>
79
+ </div>
80
+ </div>
81
+ </div>
82
+ </div>
83
+ </section>
@@ -0,0 +1,100 @@
1
+ <section id="compare" class="fade-in">
2
+ <h2 class="section-title">How nano-brain Compares</h2>
3
+ <p class="section-subtitle">The only MCP memory server with a full hybrid search pipeline — BM25 + vector + query expansion + LLM reranking. All local.</p>
4
+ <div class="compare-table-wrap">
5
+ <table class="compare-table">
6
+ <thead>
7
+ <tr>
8
+ <th>Feature</th>
9
+ <th class="highlight">nano-brain</th>
10
+ <th>Mem0</th>
11
+ <th>Zep</th>
12
+ <th>OMEGA</th>
13
+ <th>Letta</th>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <tr>
18
+ <td>Search</td>
19
+ <td class="highlight">BM25 + Vector + Reranking</td>
20
+ <td>Vector only</td>
21
+ <td>Graph + Vector</td>
22
+ <td>Semantic + BM25</td>
23
+ <td>Agent-managed</td>
24
+ </tr>
25
+ <tr>
26
+ <td>Storage</td>
27
+ <td class="highlight">SQLite (single file)</td>
28
+ <td>PostgreSQL + Qdrant</td>
29
+ <td>Neo4j</td>
30
+ <td>SQLite</td>
31
+ <td>PostgreSQL</td>
32
+ </tr>
33
+ <tr>
34
+ <td>Local AI Models</td>
35
+ <td class="highlight">GGUF (nomic + bge)</td>
36
+ <td>Cloud API</td>
37
+ <td>Cloud API</td>
38
+ <td>ONNX</td>
39
+ <td>Cloud API</td>
40
+ </tr>
41
+ <tr>
42
+ <td>Codebase Indexing</td>
43
+ <td class="highlight">&#10003;</td>
44
+ <td>&#10007;</td>
45
+ <td>&#10007;</td>
46
+ <td>&#10007;</td>
47
+ <td>&#10007;</td>
48
+ </tr>
49
+ <tr>
50
+ <td>Session Recall</td>
51
+ <td class="highlight">&#10003;</td>
52
+ <td>&#10007;</td>
53
+ <td>&#10007;</td>
54
+ <td>&#10007;</td>
55
+ <td>&#10007;</td>
56
+ </tr>
57
+ <tr>
58
+ <td>Query Expansion</td>
59
+ <td class="highlight">&#10003;</td>
60
+ <td>&#10007;</td>
61
+ <td>&#10007;</td>
62
+ <td>&#10007;</td>
63
+ <td>&#10007;</td>
64
+ </tr>
65
+ <tr>
66
+ <td>LLM Reranking</td>
67
+ <td class="highlight">&#10003;</td>
68
+ <td>&#10007;</td>
69
+ <td>&#10007;</td>
70
+ <td>&#10007;</td>
71
+ <td>&#10007;</td>
72
+ </tr>
73
+ <tr>
74
+ <td>Privacy</td>
75
+ <td class="highlight">100% local</td>
76
+ <td>Cloud API calls</td>
77
+ <td>Cloud / self-host</td>
78
+ <td>100% local</td>
79
+ <td>Self-host / cloud</td>
80
+ </tr>
81
+ <tr>
82
+ <td>External Deps</td>
83
+ <td class="highlight">None</td>
84
+ <td>Docker + PG + Qdrant</td>
85
+ <td>Docker + Neo4j</td>
86
+ <td>None</td>
87
+ <td>PostgreSQL</td>
88
+ </tr>
89
+ <tr>
90
+ <td>Pricing</td>
91
+ <td class="highlight">Free (MIT)</td>
92
+ <td>Free / $249/mo</td>
93
+ <td>Free / $25-475/mo</td>
94
+ <td>Free (Apache-2.0)</td>
95
+ <td>Free (Apache-2.0)</td>
96
+ </tr>
97
+ </tbody>
98
+ </table>
99
+ </div>
100
+ </section>
@@ -0,0 +1,23 @@
1
+ <section id="config" class="fade-in">
2
+ <h2 class="section-title">Configuration</h2>
3
+ <p class="section-subtitle">Drop this MCP config into your OpenCode settings.</p>
4
+ <pre class="codeblock"><code>{
5
+ <span class="token-string">"mcp"</span>: {
6
+ <span class="token-string">"nano-brain"</span>: {
7
+ <span class="token-string">"type"</span>: <span class="token-string">"local"</span>,
8
+ <span class="token-string">"command"</span>: [<span class="token-string">"node"</span>, <span class="token-string">"path/to/nano-brain/bin/cli.js"</span>, <span class="token-string">"mcp"</span>],
9
+ <span class="token-string">"enabled"</span>: <span class="token-boolean">true</span>
10
+ }
11
+ }
12
+ }</code></pre>
13
+ <pre class="codeblock"><code><span class="token-comment"># ~/.config/nano-brain/config.yml</span>
14
+ <span class="token-key">collections</span>:
15
+ <span class="token-key">memory</span>:
16
+ <span class="token-key">path</span>: <span class="token-string">~/.nano-brain</span>
17
+ <span class="token-key">pattern</span>: <span class="token-string">"**/*.md"</span>
18
+ <span class="token-key">update</span>: <span class="token-string">auto</span>
19
+ <span class="token-key">sessions</span>:
20
+ <span class="token-key">path</span>: <span class="token-string">~/.local/share/opencode/sessions</span>
21
+ <span class="token-key">pattern</span>: <span class="token-string">"**/*.json"</span>
22
+ <span class="token-key">update</span>: <span class="token-string">auto</span></code></pre>
23
+ </section>
@@ -0,0 +1,43 @@
1
+ <section id="features" class="fade-in">
2
+ <h2 class="section-title">Features</h2>
3
+ <p class="section-subtitle">
4
+ Premium local memory with a hybrid search pipeline, SQLite foundations, codebase indexing, and MCP-first ergonomics.
5
+ </p>
6
+ <div class="grid features">
7
+ <div class="card">
8
+ <div class="icon">🔍</div>
9
+ <h3>Hybrid Search Pipeline</h3>
10
+ <p>Query expansion → parallel BM25 + vector search → RRF fusion → LLM reranking</p>
11
+ </div>
12
+ <div class="card">
13
+ <div class="icon">🧠</div>
14
+ <h3>Local AI Models</h3>
15
+ <p>nomic-embed-text-v1.5, bge-reranker-v2-m3, qmd-query-expansion-1.7B — all GGUF, fully offline</p>
16
+ </div>
17
+ <div class="card">
18
+ <div class="icon">🗄️</div>
19
+ <h3>SQLite + sqlite-vec</h3>
20
+ <p>FTS5 for BM25 keyword search, sqlite-vec for vector similarity — single-file database</p>
21
+ </div>
22
+ <div class="card">
23
+ <div class="icon">🔌</div>
24
+ <h3>MCP Server</h3>
25
+ <p>10 tools via stdio transport, integrates with any MCP-compatible AI agent</p>
26
+ </div>
27
+ <div class="card">
28
+ <div class="icon">📚</div>
29
+ <h3>Multi-Collection</h3>
30
+ <p>Sessions, daily logs, curated memory — all indexed and searchable</p>
31
+ </div>
32
+ <div class="card">
33
+ <div class="icon">🔒</div>
34
+ <h3>Privacy First</h3>
35
+ <p>100% local processing, no cloud dependencies, your data stays on your machine</p>
36
+ </div>
37
+ <div class="card">
38
+ <div class="icon">🧬</div>
39
+ <h3>Codebase Indexing</h3>
40
+ <p>Index source files with structural boundary detection. Workspace-scoped search across sessions and code.</p>
41
+ </div>
42
+ </div>
43
+ </section>
@@ -0,0 +1,6 @@
1
+ <footer>
2
+ <div>MIT License · Inspired by <a href="https://github.com/tobi/qmd">QMD</a> & <a href="https://github.com/openclaw/openclaw">OpenClaw</a></div>
3
+ <div>
4
+ <a href="https://github.com/kokorolx/nano-brain">GitHub</a>
5
+ </div>
6
+ </footer>
@@ -0,0 +1,9 @@
1
+ <section class="hero fade-in" id="hero">
2
+ <span class="badge">v2026.1.0</span>
3
+ <h1>nano-brain</h1>
4
+ <p>Persistent hybrid search memory for AI coding agents.</p>
5
+ <div class="hero-actions">
6
+ <a class="button primary" href="https://github.com/kokorolx/nano-brain">GitHub</a>
7
+ <span class="code-pill">npm i nano-brain</span>
8
+ </div>
9
+ </section>
@@ -0,0 +1,26 @@
1
+ <section id="how" class="fade-in">
2
+ <h2 class="section-title">How It Works</h2>
3
+ <p class="section-subtitle">
4
+ Query expansion and dual retrieval streams converge through RRF fusion (k=60), then a reranker refines the final ordering.
5
+ </p>
6
+ <div class="pipeline">
7
+ <div class="pipeline-row">
8
+ <div class="node">Query</div>
9
+ <div class="connector"></div>
10
+ <div class="node">Query Expansion</div>
11
+ </div>
12
+ <div class="merge"></div>
13
+ <div class="pipeline-row split">
14
+ <div class="node">BM25 Search</div>
15
+ <div class="node">Vector Search</div>
16
+ </div>
17
+ <div class="merge"></div>
18
+ <div class="pipeline-row">
19
+ <div class="node">RRF Fusion (k=60)</div>
20
+ <div class="connector"></div>
21
+ <div class="node">LLM Reranking</div>
22
+ <div class="connector"></div>
23
+ <div class="node">Results</div>
24
+ </div>
25
+ </div>
26
+ </section>
@@ -0,0 +1,18 @@
1
+ <section id="models" class="fade-in">
2
+ <h2 class="section-title">Models</h2>
3
+ <p class="section-subtitle">Local GGUF models sized for efficient offline retrieval.</p>
4
+ <div class="grid models">
5
+ <div class="model-card">
6
+ <h4>nomic-embed-text-v1.5 (~270MB)</h4>
7
+ <p>Embeddings</p>
8
+ </div>
9
+ <div class="model-card">
10
+ <h4>bge-reranker-v2-m3 (~1.1GB)</h4>
11
+ <p>Reranking</p>
12
+ </div>
13
+ <div class="model-card">
14
+ <h4>qmd-query-expansion-1.7B (~1GB)</h4>
15
+ <p>Query Expansion</p>
16
+ </div>
17
+ </div>
18
+ </section>
@@ -0,0 +1,15 @@
1
+ <section id="quick-start" class="fade-in">
2
+ <h2 class="section-title">Quick Start</h2>
3
+ <p class="section-subtitle">CLI workflows for MCP, search, and indexing.</p>
4
+ <pre class="codeblock"><code><span class="token-comment"># MCP server</span>
5
+ nano-brain mcp <span class="token-comment"># Start MCP server (stdio)</span>
6
+ nano-brain mcp --http <span class="token-comment"># Start MCP server (HTTP)</span>
7
+
8
+ <span class="token-comment"># Search</span>
9
+ nano-brain search "query" <span class="token-comment"># BM25 search</span>
10
+ nano-brain query "query" <span class="token-comment"># Hybrid search</span>
11
+
12
+ <span class="token-comment"># Index management</span>
13
+ nano-brain status <span class="token-comment"># Show index health</span>
14
+ nano-brain update <span class="token-comment"># Reindex all collections</span></code></pre>
15
+ </section>
@@ -0,0 +1 @@
1
+ <div class="stats fade-in">2700+ documents indexed | 15 workspaces | 3 AI models | 10 MCP tools | 428 tests passing</div>
@@ -0,0 +1,13 @@
1
+ <section id="tech" class="fade-in">
2
+ <h2 class="section-title">Tech Stack</h2>
3
+ <div class="tech-stack">
4
+ <span class="tech-pill">TypeScript</span>
5
+ <span class="tech-pill">Bun</span>
6
+ <span class="tech-pill">SQLite</span>
7
+ <span class="tech-pill">sqlite-vec</span>
8
+ <span class="tech-pill">FTS5</span>
9
+ <span class="tech-pill">node-llama-cpp</span>
10
+ <span class="tech-pill">MCP SDK</span>
11
+ <span class="tech-pill">chokidar</span>
12
+ </div>
13
+ </section>
package/site/script.js ADDED
@@ -0,0 +1,12 @@
1
+ const observer = new IntersectionObserver(
2
+ (entries) => {
3
+ entries.forEach((entry) => {
4
+ if (entry.isIntersecting) {
5
+ entry.target.classList.add('visible')
6
+ }
7
+ })
8
+ },
9
+ { threshold: 0.15 }
10
+ )
11
+
12
+ document.querySelectorAll('.fade-in').forEach((el) => observer.observe(el))
@@ -0,0 +1,44 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>nano-brain · MCP Server</title>
7
+ <style>
8
+ {{styles}}
9
+ </style>
10
+ </head>
11
+ <body>
12
+ <header class="nav">
13
+ <div class="nav-inner">
14
+ <div class="brand"><span class="brand-dot"></span>nano-brain</div>
15
+ <nav class="nav-links">
16
+ <a href="#features">Features</a>
17
+ <a href="#compare">Compare</a>
18
+ <a href="#how">How It Works</a>
19
+ <a href="#api">API</a>
20
+ <a href="#config">Config</a>
21
+ <a href="#models">Models</a>
22
+ </nav>
23
+ </div>
24
+ </header>
25
+
26
+ <div class="page">
27
+ {{partial:hero}}
28
+ {{partial:features}}
29
+ {{partial:compare}}
30
+ {{partial:how-it-works}}
31
+ {{partial:api}}
32
+ {{partial:config}}
33
+ {{partial:quick-start}}
34
+ {{partial:models}}
35
+ {{partial:tech-stack}}
36
+ {{partial:stats}}
37
+ {{partial:footer}}
38
+ </div>
39
+
40
+ <script>
41
+ {{script}}
42
+ </script>
43
+ </body>
44
+ </html>