@andespindola/brainlink 0.1.0-beta.4 → 0.1.0-beta.40

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 (58) hide show
  1. package/AGENTS.md +5 -5
  2. package/CHANGELOG.md +43 -2
  3. package/CONTRIBUTING.md +2 -2
  4. package/COPYRIGHT.md +5 -0
  5. package/README.md +213 -20
  6. package/SECURITY.md +1 -1
  7. package/dist/application/add-note.js +62 -13
  8. package/dist/application/analyze-vault.js +95 -8
  9. package/dist/application/build-context.js +56 -1
  10. package/dist/application/dedupe-notes.js +226 -0
  11. package/dist/application/frontend/client-css.js +214 -100
  12. package/dist/application/frontend/client-html.js +60 -45
  13. package/dist/application/frontend/client-js.js +656 -94
  14. package/dist/application/get-graph-layout.js +22 -7
  15. package/dist/application/get-graph-node.js +12 -0
  16. package/dist/application/get-graph-summary.js +12 -0
  17. package/dist/application/get-graph.js +3 -3
  18. package/dist/application/import-legacy-sqlite.js +296 -0
  19. package/dist/application/index-vault.js +11 -4
  20. package/dist/application/list-agents.js +3 -3
  21. package/dist/application/list-links.js +5 -5
  22. package/dist/application/migrate-vault.js +91 -0
  23. package/dist/application/search-graph-node-ids.js +12 -0
  24. package/dist/application/search-knowledge.js +75 -5
  25. package/dist/application/server/routes.js +27 -1
  26. package/dist/benchmarks/large-vault.js +1 -1
  27. package/dist/cli/commands/agent-commands.js +412 -0
  28. package/dist/cli/commands/config-commands.js +167 -0
  29. package/dist/cli/commands/read-commands.js +25 -8
  30. package/dist/cli/commands/write-commands.js +669 -9
  31. package/dist/cli/main.js +4 -0
  32. package/dist/cli/runtime.js +5 -2
  33. package/dist/domain/context.js +53 -11
  34. package/dist/domain/embeddings.js +2 -1
  35. package/dist/domain/graph-layout.js +20 -14
  36. package/dist/domain/markdown.js +36 -4
  37. package/dist/domain/middle-out.js +18 -0
  38. package/dist/infrastructure/config.js +94 -8
  39. package/dist/infrastructure/file-index.js +328 -0
  40. package/dist/infrastructure/file-system-vault.js +15 -0
  41. package/dist/infrastructure/paths.js +9 -1
  42. package/dist/infrastructure/private-pack-codec.js +73 -0
  43. package/dist/infrastructure/search-packs.js +348 -0
  44. package/dist/infrastructure/session-state.js +172 -0
  45. package/dist/mcp/main.js +11 -3
  46. package/dist/mcp/server.js +27 -2
  47. package/dist/mcp/startup.js +35 -0
  48. package/dist/mcp/tools.js +633 -19
  49. package/docs/AGENT_USAGE.md +144 -16
  50. package/docs/ARCHITECTURE.md +37 -26
  51. package/docs/QUICKSTART.md +111 -0
  52. package/package.json +6 -4
  53. package/dist/infrastructure/sqlite/document-writer.js +0 -51
  54. package/dist/infrastructure/sqlite/graph-reader.js +0 -120
  55. package/dist/infrastructure/sqlite/schema.js +0 -111
  56. package/dist/infrastructure/sqlite/search-reader.js +0 -156
  57. package/dist/infrastructure/sqlite/types.js +0 -1
  58. package/dist/infrastructure/sqlite-index.js +0 -25
@@ -18,7 +18,7 @@ The correct dependency direction is:
18
18
  agent -> Brainlink CLI -> Markdown vault + derived index
19
19
  ```
20
20
 
21
- Agents should never depend on the internal SQLite schema as a public API.
21
+ Agents should never depend on internal index persistence files as a public API.
22
22
 
23
23
  The installed CLI exposes two equivalent binaries:
24
24
 
@@ -39,9 +39,19 @@ $HOME/.brainlink/vault
39
39
 
40
40
  `blink server` follows the same rule, so it serves the default Brainlink vault instead of the current working directory.
41
41
 
42
- Use `--vault <path>` for a one-off custom vault, or set `vault` in `brainlink.config.json` / `.brainlink.json` for a workspace-level custom default. Set `BRAINLINK_HOME` when the whole Brainlink home directory should live somewhere else.
42
+ Use `--vault <path>` for a one-off custom vault, or set `vault` in config for a persistent default.
43
+ Configuration precedence is:
44
+
45
+ 1. global: `$BRAINLINK_HOME/brainlink.config.json` (or `$HOME/.brainlink/brainlink.config.json`)
46
+ 2. local: `./brainlink.config.json`
47
+ 3. local legacy: `./.brainlink.json`
48
+
49
+ Set `BRAINLINK_HOME` when the whole Brainlink home directory should live somewhere else.
50
+
51
+ Use `blink config where` and `blink config doctor` to inspect active paths and effective source.
43
52
 
44
53
  You can also set `defaultAgent` in `brainlink.config.json` / `.brainlink.json` (for example `"defaultAgent": "coding-agent"`). When set, CLI commands and MCP calls reuse it when `--agent`/`agent` is not passed.
54
+ You can set `agentProfiles` to define per-agent defaults for `defaultSearchMode`, `defaultSearchLimit` and `defaultContextTokens`.
45
55
 
46
56
  `autoIndexOnWrite` (default: `true`) controls whether `add` and MCP write tools index right after writing.
47
57
 
@@ -170,16 +180,16 @@ Required write behavior:
170
180
  Good linked note:
171
181
 
172
182
  ```bash
173
- blink add "SQLite Index Rebuild" \
183
+ blink add "Index Rebuild" \
174
184
  --agent coding-agent \
175
- --content "Legacy derived indexes without agent columns are rebuilt because SQLite is disposable. Related: [[Architecture]], [[Agent Namespaces]]. #sqlite #architecture #decision"
185
+ --content "Derived index artifacts are rebuildable and disposable. Related: [[Architecture]], [[Agent Namespaces]]. #index #architecture #decision"
176
186
  blink validate --agent coding-agent
177
187
  ```
178
188
 
179
189
  Poor disconnected note:
180
190
 
181
191
  ```bash
182
- blink add "SQLite Index Rebuild" \
192
+ blink add "Index Rebuild" \
183
193
  --agent coding-agent \
184
194
  --content "We rebuild old indexes now."
185
195
  ```
@@ -246,7 +256,7 @@ cp docs/templates/agent-note-template.md /tmp/agent-note.md
246
256
  When using MCP, use this compact sequence for the same memory discipline:
247
257
 
248
258
  1. Bootstrap context:
249
- - `brainlink_context` with `agent`, `query`, `mode: hybrid`, `limit`.
259
+ - `brainlink_bootstrap` with `agent`, optional `query`, `mode: hybrid`, `limit`.
250
260
  2. Capture durable decisions:
251
261
  - `brainlink_add_note` or `brainlink_add_file` with explicit `[[wiki links]]` and `#tags`.
252
262
  3. Run maintenance before handoff or before the next step:
@@ -341,7 +351,69 @@ $HOME/.brainlink/vault/
341
351
  .brainlink/
342
352
  ```
343
353
 
344
- `blink init ./vault` creates a custom vault instead.
354
+ `blink init ./vault` creates a custom vault instead. If the custom vault is empty and the default `$HOME/.brainlink/vault` already has Markdown memory, Brainlink copies that content into the custom vault and reindexes it. Use `blink init ./vault --no-migrate-existing` to intentionally start empty, or `blink init ./vault --migrate-from <old-vault>` to migrate from a specific previous vault. Existing target files are not overwritten; conflicting source files are preserved with a `.conflict-<timestamp>` suffix.
355
+
356
+ ### Configure Defaults
357
+
358
+ ```bash
359
+ blink config where
360
+ blink config get vault
361
+ blink config doctor
362
+ blink config doctor --fix
363
+ blink config set-vault /absolute/path/to/vault
364
+ blink config set-vault /absolute/path/to/vault --global
365
+ ```
366
+
367
+ `config set-vault` updates Brainlink config through CLI. By default it writes local `brainlink.config.json`, appends the vault to `allowedVaults`, and migrates markdown when the target is empty.
368
+
369
+ ### Migrate Vaults Explicitly
370
+
371
+ ```bash
372
+ blink migrate-vault --from ~/.brainlink/vault --to ./team-vault --dry-run
373
+ blink migrate-vault --from ~/.brainlink/vault --to ./team-vault
374
+ blink migrate-vault --from ~/.brainlink/vault --to "s3://my-memory-bucket/brainlink"
375
+ blink migrate-vault --from ~/.brainlink/vault --to ./team-vault --report ./migration-report.json
376
+ ```
377
+
378
+ Use `--dry-run` to preview `copied`, `conflicted`, `unchanged` before writing files.
379
+
380
+ ### Import Legacy SQLite DB
381
+
382
+ ```bash
383
+ blink db-import --vault ./team-vault
384
+ blink db-import --vault ./team-vault --db ./legacy/brainlink.db
385
+ blink db-import --vault ./team-vault --db ./legacy/brainlink.db --table legacy_notes --dry-run
386
+ ```
387
+
388
+ `db-import` migrates rows from legacy SQLite memory into Markdown notes in the current vault and indexes the result by default.
389
+ Without `--db`, Brainlink auto-detects common legacy database paths.
390
+ Use `--agent` to force namespace, `--limit` for staged migration, `--dry-run` to preview writes, and `--no-index` to postpone indexing.
391
+
392
+ ### Install Agent Integration
393
+
394
+ ```bash
395
+ blink agent install
396
+ blink agent install --self-test
397
+ blink agent upgrade
398
+ blink agent policy --preset fully-auto
399
+ blink agent policy --preset strict
400
+ blink agent install --plugin-path ./plugins/brainlink
401
+ blink agent status
402
+ ```
403
+
404
+ `agent install` configures Brainlink MCP in `~/.codex/config.toml` so compatible agents can use Brainlink by default.
405
+ Use `agent upgrade` on legacy installations to reapply the latest defaults and run self-test diagnostics.
406
+ Use `agent policy --preset fully-auto` to keep startup/read auto-bootstrap enabled, or `agent policy --preset strict` to force explicit bootstrap calls.
407
+
408
+ ### Quickstart Plug-And-Play
409
+
410
+ ```bash
411
+ blink quickstart --json
412
+ blink quickstart --vault ./team-vault --agent coding-agent --query "architecture decisions" --json
413
+ blink quickstart --vault ./team-vault --mcp-only --json
414
+ ```
415
+
416
+ `quickstart` runs index, doctor, stats and validation, marks bootstrap readiness for MCP sessions, optionally returns context, and updates agent integration by default.
345
417
 
346
418
  ### Add A Note
347
419
 
@@ -356,6 +428,26 @@ blink add "Note Title" --vault ./vault --content-file ./notes.md --no-auto-index
356
428
  This creates a slugged Markdown file with frontmatter and a heading.
357
429
 
358
430
  The CLI blocks common secret patterns by default. Do not use `--allow-sensitive` unless the vault is intentionally protected.
431
+ Brainlink also auto-connects notes that have no `[[wiki links]]` by adding a fallback edge to an agent hub note, so new memory does not stay disconnected.
432
+ `add` also returns `possibleDuplicates` (exact hash + semantic candidates) so agents can decide duplicate resolution immediately.
433
+
434
+ ### Detect Duplicate Notes
435
+
436
+ ```bash
437
+ blink dedupe --vault ./vault --json
438
+ blink dedupe --vault ./vault --agent coding-agent --limit 20 --min-score 0.92 --json
439
+ blink dedupe --vault ./vault --no-semantic --json
440
+ ```
441
+
442
+ ### Resolve Duplicate Notes
443
+
444
+ ```bash
445
+ blink dedupe-resolve --vault ./vault --left agents/shared/a.md --right agents/shared/b.md --action merge --json
446
+ blink dedupe-resolve --vault ./vault --left agents/shared/a.md --right agents/shared/b.md --action link --json
447
+ blink dedupe-resolve --vault ./vault --left agents/shared/a.md --right agents/shared/b.md --action ignore --json
448
+ ```
449
+
450
+ `dedupe-resolve` keeps connectivity: non-merge actions still create a low-priority related edge (`#related-to`).
359
451
 
360
452
  For agent-private memory:
361
453
 
@@ -395,12 +487,16 @@ blink search "authentication token policy" --vault ./vault --mode semantic --jso
395
487
  ```
396
488
 
397
489
  This returns matching chunks with title, source path, score, `textScore`, `semanticScore`, `searchMode`, and content.
490
+ If `--mode`/`--limit` are omitted, Brainlink resolves those values from the active agent profile before global defaults.
398
491
 
399
492
  Search modes:
400
493
 
401
- - `hybrid`: default; combines SQLite FTS and local embedding similarity.
402
- - `fts`: lexical SQLite full-text search only.
403
- - `semantic`: local deterministic embedding similarity with SQLite bucket candidate narrowing.
494
+ - `hybrid`: default; combines lexical matching and local embedding similarity.
495
+ - `fts`: lexical full-text matching only.
496
+ - `semantic`: local deterministic embedding similarity.
497
+
498
+ Hybrid results are cached in-memory for a short TTL and invalidated when `.brainlink/index.json` changes.
499
+ Context assembly uses middle-out ordering inside each note: the highest-scoring chunk is selected first, then nearby chunks are expanded while token budget allows.
404
500
 
405
501
  ### Build Agent Context
406
502
 
@@ -459,13 +555,26 @@ shared: 30 documents
459
555
  ```bash
460
556
  blink server --host 127.0.0.1 --port 4321
461
557
  blink server --vault ./vault --host 127.0.0.1 --port 4321
558
+ blink server --vault ./vault --host 127.0.0.1 --port 4321 --no-open
462
559
  ```
463
560
 
464
561
  This starts a local frontend for inspecting the knowledge graph.
562
+ By default it tries to open the graph in a native desktop GUI window:
563
+ - macOS: Swift + WebKit
564
+ - Windows: PowerShell WinForms WebBrowser
565
+ - Linux: optional Python GTK + WebKit2 (requires `python3` + `gi` + `WebKit2`)
566
+
567
+ On Linux, native GUI is disabled by default for better startup performance. Enable it with `BRAINLINK_LINUX_NATIVE_GUI=1`.
568
+ If native GUI launch is unavailable, it falls back to dedicated app-window mode and then to the default browser.
569
+ Use `--no-open` to keep the server headless.
570
+ When native GUI is active, the GUI window closes automatically when the `blink server` process stops.
465
571
 
466
572
  Without `--vault`, the graph UI serves `$HOME/.brainlink/vault`.
467
573
 
468
- The frontend includes an agent selector. Selecting an agent calls the same read APIs with `agent=<agent-id>` and renders that namespace instead of merging every agent into one graph.
574
+ The frontend includes an agent selector that shows only the agent id. Selecting an agent calls the same read APIs with `agent=<agent-id>` and renders that namespace instead of merging every agent into one graph.
575
+
576
+ Graph navigation controls include zoom in, zoom out, fit visible nodes and reset-to-fit-all nodes. Mouse wheel zoom (including `cmd+scroll` and `ctrl+scroll`) is anchored to the cursor. Keyboard shortcuts are `+` (zoom in), `-` (zoom out) and `0` (reset fit). Double-click on canvas zooms in at cursor position. Totals for notes, links and tags stay visible as floating metrics under the Brainlink title, and node details open on click in a modal (tags, outgoing links, backlinks and Markdown content).
577
+ During graph filtering, Brainlink keeps hub context nodes visible (`Memory Hub`/`MOC`/high-degree fallback) so filtered views still show relationship anchors.
469
578
 
470
579
  The command reindexes by default, then serves:
471
580
 
@@ -518,8 +627,13 @@ Example MCP client configuration:
518
627
 
519
628
  Available MCP tools:
520
629
 
630
+ - `brainlink_bootstrap`
631
+ - `brainlink_policy`
632
+ - `brainlink_recommendations`
521
633
  - `brainlink_context`
522
634
  - `brainlink_search`
635
+ - `brainlink_dedupe`
636
+ - `brainlink_resolve_duplicate`
523
637
  - `brainlink_add_note`
524
638
  - `brainlink_add_file`
525
639
  - `brainlink_index`
@@ -530,9 +644,17 @@ Available MCP tools:
530
644
  - `brainlink_broken_links`
531
645
  - `brainlink_orphans`
532
646
 
647
+ Recommended start of every memory-dependent task: call `brainlink_bootstrap` first, then `brainlink_context`. By default, Brainlink enforces context-first for non-context MCP reads (`enforceContextFirst=true`), and also enforces bootstrap with auto-bootstrap on reads when state is missing or stale (`autoBootstrapOnRead=true`).
648
+ MCP startup also bootstraps the configured default vault/agent automatically (`autoBootstrapOnStartup=true`), so sessions start warm without manual calls.
649
+ If `autoBootstrapOnRead` or `enforceContextFirst` are disabled through `brainlink_policy`, behavior is relaxed accordingly; otherwise read tools return preflight-required responses when requirements are not satisfied.
650
+ `brainlink_bootstrap`, `brainlink_policy` and preflight responses include structured `nextActions` so clients can continue tool flows automatically.
651
+ `brainlink_policy` also accepts policy presets (`fully-auto`, `strict`) so MCP clients can switch behavior in one call.
652
+ `brainlink_recommendations` returns the suggested execution order so an agent can follow Brainlink best practices automatically.
653
+
533
654
  MCP clients can pass `vault` and `agent` arguments per tool call. Set `BRAINLINK_ALLOWED_VAULTS` when exposing Brainlink to an external agent process so a tool cannot pass arbitrary vault paths:
534
655
 
535
656
  `brainlink_graph` returns weighted edges. Agents should prefer higher `weight` and stronger `priority` when deciding which related notes matter most.
657
+ `brainlink_add_note` and `brainlink_add_file` return `writeConnectivity` metadata and guarantee at least one edge for new notes.
536
658
 
537
659
  ```bash
538
660
  export BRAINLINK_ALLOWED_VAULTS="/absolute/path/to/project-vault"
@@ -543,6 +665,8 @@ export BRAINLINK_ALLOWED_VAULTS="/absolute/path/to/project-vault"
543
665
  ```txt
544
666
  GET /api/graph
545
667
  GET /api/graph-layout
668
+ GET /api/graph-node?id=<node-id>
669
+ GET /api/graph-filter?q=<query>&limit=<n>
546
670
  GET /api/search?q=<query>&limit=10&mode=hybrid
547
671
  GET /api/context?q=<query>&limit=12&tokens=2000&mode=hybrid
548
672
  GET /api/links
@@ -555,6 +679,10 @@ GET /api/validate
555
679
 
556
680
  The HTTP API is read-only. Use the CLI for writes and indexing.
557
681
 
682
+ Indexing writes private encrypted search packs at `.brainlink/search-packs/*.blpk` for resilient retrieval and portability.
683
+ Pack search now uses compressed-space prefiltering (token bloom index per pack) before decrypting/reading pack payloads.
684
+ Pack decryption keys are resolved from `$BRAINLINK_HOME/keys` (or `BRAINLINK_SEARCH_PACK_KEY` when explicitly set).
685
+
558
686
  ## Agent Integration Contract
559
687
 
560
688
  Input:
@@ -586,9 +714,9 @@ Non-goals:
586
714
  ## Operational Rules
587
715
 
588
716
  - Re-run `index` after modifying notes.
589
- - Treat `.brainlink/brainlink.db` as disposable.
590
- - Commit Markdown notes, not local database files.
591
- - Do not manually edit the database.
717
+ - Treat `.brainlink/index.json` and `.brainlink/search-packs/` as disposable.
718
+ - Commit Markdown notes, not local index files.
719
+ - Do not manually edit generated index artifacts.
592
720
  - Keep generated context short enough for the target model.
593
721
  - Prefer specific queries over broad queries.
594
722
  - Write explicit `[[wiki links]]` when durable memory should be connected.
@@ -618,9 +746,9 @@ Weak retrieval usually means:
618
746
 
619
747
  ## Current Limits
620
748
 
621
- - Search supports FTS, local semantic embeddings, SQLite semantic buckets and hybrid ranking.
749
+ - Search supports FTS, local semantic embeddings and hybrid ranking.
622
750
  - Local embeddings are deterministic and provider-free; remote embedding providers are not implemented yet.
623
751
  - MCP integration is available through the `brainlink-mcp` stdio server.
624
752
  - HTTP API is local and unauthenticated.
625
- - Bucket vaults support S3-compatible `s3://bucket/prefix` URIs and use a local cache for SQLite indexes.
753
+ - Bucket vaults support S3-compatible `s3://bucket/prefix` URIs and use local cache/index artifacts.
626
754
  - Watch mode depends on platform filesystem watcher behavior and is only supported for local filesystem vaults.
@@ -8,7 +8,7 @@ CLI -> application use cases -> domain functions -> infrastructure adapters
8
8
 
9
9
  The core rule is simple:
10
10
 
11
- Domain code must not know about the CLI, filesystem, or SQLite.
11
+ Domain code must not know about the CLI, filesystem, or index persistence format.
12
12
 
13
13
  ## Modules
14
14
 
@@ -34,6 +34,8 @@ src/
34
34
 
35
35
  cli/
36
36
  commands/
37
+ agent-commands.ts
38
+ config-commands.ts
37
39
  read-commands.ts
38
40
  write-commands.ts
39
41
  main.ts
@@ -51,13 +53,16 @@ src/
51
53
  types.ts
52
54
 
53
55
  infrastructure/
54
- sqlite/
55
- document-writer.ts
56
- graph-reader.ts
57
- schema.ts
58
- search-reader.ts
56
+ file-index.ts
59
57
  file-system-vault.ts
60
- sqlite-index.ts
58
+ private-pack-codec.ts
59
+ search-packs.ts
60
+ session-state.ts
61
+
62
+ mcp/
63
+ main.ts
64
+ server.ts
65
+ tools.ts
61
66
  ```
62
67
 
63
68
  ## Domain
@@ -72,7 +77,6 @@ The domain layer contains pure knowledge rules:
72
77
  - extract `#tags`
73
78
  - split documents into chunks
74
79
  - create deterministic local embeddings
75
- - create deterministic embedding buckets for semantic candidate retrieval
76
80
  - calculate cosine similarity
77
81
  - estimate token counts
78
82
  - select context sections
@@ -108,12 +112,11 @@ The infrastructure layer handles side effects:
108
112
  - mirroring S3-compatible bucket Markdown into a local cache
109
113
  - writing Markdown notes
110
114
  - creating `.brainlink`
111
- - writing and querying SQLite
112
- - running FTS, semantic and hybrid retrieval
113
- - narrowing semantic candidates through SQLite embedding buckets before cosine scoring
115
+ - writing and querying file-based indexes
116
+ - running lexical, semantic and hybrid retrieval
117
+
114
118
 
115
- SQLite is an index, not the canonical storage model. For bucket vaults, Markdown
116
- objects in the bucket remain canonical and SQLite is still local derived data.
119
+ Index artifacts are rebuildable and are not canonical storage. For bucket vaults, Markdown objects in the bucket remain canonical and local index files are derived data.
117
120
 
118
121
  ## Indexing Flow
119
122
 
@@ -124,11 +127,9 @@ read markdown files
124
127
  -> resolve links
125
128
  -> split chunks
126
129
  -> create chunk embeddings
127
- -> reset SQLite index
130
+ -> reset file index
128
131
  -> persist documents, chunks and links
129
- -> populate FTS records
130
- -> persist embedding vectors
131
- -> persist embedding buckets
132
+ -> persist chunks, links and embeddings in file index
132
133
  ```
133
134
 
134
135
  ## Retrieval Flow
@@ -137,8 +138,10 @@ read markdown files
137
138
  question
138
139
  -> selected mode: fts | semantic | hybrid
139
140
  -> optional query embedding
140
- -> FTS query and/or embedding bucket candidate lookup
141
+ -> optional compressed pack prefilter (token bloom)
142
+ -> lexical scoring and/or semantic cosine scoring
141
143
  -> cosine similarity over candidate chunks
144
+ -> middle-out context expansion around strongest chunk
142
145
  -> ranked chunks with textScore and semanticScore
143
146
  -> token-budget selection
144
147
  -> Markdown context package
@@ -155,7 +158,7 @@ server command
155
158
  -> browser renders graph canvas
156
159
  ```
157
160
 
158
- The graph UI is intentionally read-only. Markdown remains the write interface and SQLite remains a derived index.
161
+ The graph UI is intentionally read-only. Markdown remains the write interface and index artifacts remain derived data.
159
162
 
160
163
  ## HTTP API Flow
161
164
 
@@ -163,7 +166,7 @@ The graph UI is intentionally read-only. Markdown remains the write interface an
163
166
  HTTP request
164
167
  -> route handler
165
168
  -> application use case
166
- -> filesystem and SQLite adapters
169
+ -> filesystem and index adapters
167
170
  -> JSON response
168
171
  ```
169
172
 
@@ -181,6 +184,10 @@ MCP client
181
184
  ```
182
185
 
183
186
  The MCP adapter stays thin. It validates tool inputs, resolves the configured vault and calls the same application use cases used by the CLI.
187
+ At server startup, Brainlink runs a bootstrap pass on the configured default vault/agent, then keeps enforcing bootstrap policy on read tools.
188
+ For MCP agents, non-context read tools also enforce context-first by default, requiring a recent `brainlink_context` call before additional reads.
189
+ When `mode`/`limit`/`tokens` are omitted, MCP read tools resolve per-agent defaults from `agentProfiles` and then fallback to global config defaults.
190
+ Session state is persisted in `$BRAINLINK_HOME/session-state.json` with independent bootstrap/context freshness per vault/agent so read tools can enforce bootstrap and context-first policies with optional automation.
184
191
 
185
192
  ## Link Resolution
186
193
 
@@ -270,11 +277,10 @@ vault/agents/<agent-id>/**/*.md
270
277
 
271
278
  Rebuildable:
272
279
 
273
- - `.brainlink/brainlink.db`
280
+ - `.brainlink/index.json`
281
+ - `.brainlink/search-packs/*.blpk`
274
282
  - `$BRAINLINK_HOME/bucket-cache`
275
- - FTS records
276
283
  - local embedding vectors
277
- - local embedding bucket index
278
284
  - chunks
279
285
  - resolved links
280
286
 
@@ -284,13 +290,18 @@ Rebuildable:
284
290
 
285
291
  Markdown keeps the system portable, inspectable, Git-friendly, and compatible with Obsidian-like workflows.
286
292
 
287
- ### SQLite As Local Index
293
+ ### File Index As Local Index
288
294
 
289
- SQLite gives fast local search, local vector storage and rebuildable retrieval without forcing users to run external infrastructure.
295
+ Brainlink uses a local JSON index plus encrypted pack exports for fast rebuildable retrieval without external infrastructure.
296
+ Hybrid retrieval also uses a short-lived in-memory cache keyed by vault/query/agent and invalidated by index file mtime to reduce repeated query latency.
297
+ Indexing exports private encrypted pack files (`.brainlink/search-packs/*.blpk`) from indexed chunks for fast retrieval and recovery continuity.
298
+ Pack manifests include compressed-space token bloom metadata so retrieval can skip unrelated packs before decryption.
299
+ Pack encryption keys are resolved from `$BRAINLINK_HOME/keys` or from `BRAINLINK_SEARCH_PACK_KEY` when configured.
300
+ Legacy `.jsonl.gz` search packs are auto-upgraded to `.blpk` on first retrieval flow.
290
301
 
291
302
  ### CLI First
292
303
 
293
- The CLI is the smallest useful integration surface for agents. HTTP is a local inspection adapter, and MCP can be implemented outside this package by wrapping the CLI.
304
+ The CLI is the smallest useful integration surface for agents. HTTP is a local inspection adapter, and Brainlink also ships a built-in MCP server (`brainlink-mcp`) that uses the same application use cases.
294
305
 
295
306
  ### Functional Core
296
307
 
@@ -0,0 +1,111 @@
1
+ # Quickstart
2
+
3
+ Use this path when you want Brainlink running as agent memory with the smallest setup.
4
+
5
+ ## 1) Install Brainlink
6
+
7
+ ```bash
8
+ npm install -g @andespindola/brainlink@latest
9
+ ```
10
+
11
+ ## 2) Install Agent Integration
12
+
13
+ ```bash
14
+ blink agent install --self-test
15
+ blink agent upgrade
16
+ blink agent policy --preset fully-auto
17
+ blink agent status
18
+ ```
19
+
20
+ For local plugin gallery in this repository:
21
+
22
+ ```bash
23
+ blink agent install --plugin-path ./plugins/brainlink --self-test
24
+ ```
25
+
26
+ One-command setup and readiness check:
27
+
28
+ ```bash
29
+ blink quickstart --query "what should I know before this task?" --json
30
+ ```
31
+
32
+ ## 3) Initialize Or Select Vault
33
+
34
+ ```bash
35
+ blink init
36
+ blink config where
37
+ ```
38
+
39
+ To set a different default vault:
40
+
41
+ ```bash
42
+ blink config set-vault /absolute/path/to/vault
43
+ ```
44
+
45
+ Optional per-agent retrieval defaults in `brainlink.config.json`:
46
+
47
+ ```json
48
+ {
49
+ "agentProfiles": {
50
+ "coding-agent": {
51
+ "defaultSearchMode": "semantic",
52
+ "defaultSearchLimit": 8,
53
+ "defaultContextTokens": 2400
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ ## 4) Run Bootstrap Before Work
60
+
61
+ MCP clients should call `brainlink_bootstrap` first for each vault/agent session, then `brainlink_context`.
62
+ By default, Brainlink enforces context-first for non-context read tools, so a fresh `brainlink_context` call is required before other MCP reads.
63
+ Read tools auto-bootstrap by default when state is missing/stale, and bootstrap/preflight responses include structured `nextActions` for automatic client flows.
64
+ MCP startup also runs bootstrap automatically for the configured default vault/agent.
65
+
66
+ For CLI workflows:
67
+
68
+ ```bash
69
+ blink context "what should I know before this task?" --mode hybrid --json
70
+ ```
71
+
72
+ ## 5) Write Durable Memory
73
+
74
+ ```bash
75
+ blink add "Architecture Decision" --content "Use explicit [[Bounded Context]] links and #tags. #architecture #decision"
76
+ ```
77
+
78
+ ## 6) Validate Health
79
+
80
+ ```bash
81
+ blink validate
82
+ blink doctor
83
+ blink stats --extended --json
84
+ ```
85
+
86
+ ## 7) Migrate Existing Memory (Optional)
87
+
88
+ Preview first:
89
+
90
+ ```bash
91
+ blink migrate-vault --from ~/.brainlink/vault --to ./team-vault --dry-run --report ./migration-report.json
92
+ ```
93
+
94
+ Apply:
95
+
96
+ ```bash
97
+ blink migrate-vault --from ~/.brainlink/vault --to ./team-vault --report ./migration-report.json
98
+ ```
99
+
100
+ S3 target:
101
+
102
+ ```bash
103
+ blink migrate-vault --from ~/.brainlink/vault --to "s3://my-memory-bucket/brainlink" --dry-run
104
+ ```
105
+
106
+ Legacy SQLite import:
107
+
108
+ ```bash
109
+ blink db-import --vault ./team-vault
110
+ blink db-import --vault ./team-vault --db ./legacy/brainlink.db --dry-run
111
+ ```
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@andespindola/brainlink",
3
- "version": "0.1.0-beta.4",
3
+ "version": "0.1.0-beta.40",
4
4
  "description": "Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
- "author": "Anderson Espindola",
7
+ "author": "Substructa",
8
8
  "homepage": "https://github.com/andersonflima/brainlink#readme",
9
9
  "repository": {
10
10
  "type": "git",
@@ -32,6 +32,7 @@
32
32
  "dist",
33
33
  "assets",
34
34
  "README.md",
35
+ "COPYRIGHT.md",
35
36
  "LICENSE",
36
37
  "CHANGELOG.md",
37
38
  "CONTRIBUTING.md",
@@ -58,12 +59,13 @@
58
59
  "dependencies": {
59
60
  "@aws-sdk/client-s3": "^3.1038.0",
60
61
  "@modelcontextprotocol/sdk": "^1.29.0",
61
- "better-sqlite3": "^12.9.0",
62
62
  "commander": "^14.0.2",
63
63
  "zod": "^4.3.6"
64
64
  },
65
+ "overrides": {
66
+ "qs": "6.15.2"
67
+ },
65
68
  "devDependencies": {
66
- "@types/better-sqlite3": "^7.6.13",
67
69
  "@types/node": "^24.9.2",
68
70
  "tsx": "^4.21.0",
69
71
  "typescript": "^5.9.3",
@@ -1,51 +0,0 @@
1
- import { createEmbeddingBuckets } from '../../domain/embeddings.js';
2
- const toTitleKey = (title) => title.toLowerCase();
3
- export const createIndexWriter = (database) => ({
4
- reset: () => {
5
- database.exec(`
6
- DELETE FROM embedding_buckets;
7
- DELETE FROM chunks_fts;
8
- DELETE FROM links;
9
- DELETE FROM chunks;
10
- DELETE FROM documents;
11
- `);
12
- },
13
- saveDocuments: (documents) => {
14
- const insertDocument = database.prepare(`
15
- INSERT INTO documents (id, agent_id, title, path, content, tags_json, frontmatter_json, created_at, updated_at)
16
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
17
- `);
18
- const insertChunk = database.prepare(`
19
- INSERT INTO chunks (id, document_id, ordinal, content, token_count, embedding_provider, embedding_json)
20
- VALUES (?, ?, ?, ?, ?, ?, ?)
21
- `);
22
- const insertChunkFts = database.prepare(`
23
- INSERT INTO chunks_fts (chunk_id, document_id, agent_id, title, content)
24
- VALUES (?, ?, ?, ?, ?)
25
- `);
26
- const insertEmbeddingBucket = database.prepare(`
27
- INSERT OR IGNORE INTO embedding_buckets (bucket, chunk_id)
28
- VALUES (?, ?)
29
- `);
30
- const insertLink = database.prepare(`
31
- INSERT INTO links (from_document_id, to_title, to_title_key, to_document_id, weight, priority)
32
- VALUES (?, ?, ?, ?, ?, ?)
33
- `);
34
- const transaction = database.transaction(() => {
35
- documents.forEach(({ document, chunks, links }) => {
36
- insertDocument.run(document.id, document.agentId, document.title, document.path, document.content, JSON.stringify(document.tags), JSON.stringify(document.frontmatter), document.createdAt, document.updatedAt);
37
- chunks.forEach((chunk) => {
38
- insertChunk.run(chunk.id, chunk.documentId, chunk.ordinal, chunk.content, chunk.tokenCount, chunk.embeddingProvider, JSON.stringify(chunk.embedding));
39
- insertChunkFts.run(chunk.id, chunk.documentId, document.agentId, document.title, chunk.content);
40
- createEmbeddingBuckets(chunk.embedding).forEach((bucket) => insertEmbeddingBucket.run(bucket, chunk.id));
41
- });
42
- });
43
- documents.forEach(({ links }) => {
44
- links.forEach((link) => {
45
- insertLink.run(link.fromDocumentId, link.toTitle, toTitleKey(link.toTitle), link.toDocumentId, link.weight, link.priority);
46
- });
47
- });
48
- });
49
- transaction();
50
- }
51
- });