@andespindola/brainlink
v1.0.5
Published
Local-first knowledge memory for agents with Markdown, backlinks, indexing and context retrieval.
Maintainers
Readme
Brainlink
Local-first memory and knowledge graph for AI agents.
Brainlink turns a folder of Markdown files into a searchable, link-aware memory layer that agents can use before answering, planning, coding, documenting or handing work to another agent.
It is inspired by Obsidian-style knowledge bases: plain Markdown, [[wiki links]], backlinks, tags and graph navigation. The difference is that Brainlink is built for automation first: CLI, JSON output, local HTTP API and a graph frontend.
Purpose
This repository exists to give agents a durable project memory that lives outside the model context window.
Without Brainlink, an agent usually depends on:
- the current prompt
- the current chat history
- files it happens to inspect in this run
- short-lived assumptions made during a task
With Brainlink, an agent can persist and retrieve:
- architecture decisions
- coding conventions
- user preferences
- operational runbooks
- previous investigation summaries
- domain concepts
- unresolved questions
- handoff notes for other agents
The goal is not to replace the model's context window. The goal is to make the model's context window smarter by filling it with the most relevant memory before the agent acts.
How Brainlink Improves Agents
Brainlink improves agent behavior by giving them a repeatable memory workflow:
- Less repeated discovery: agents can retrieve previous decisions instead of rediscovering the same context.
- Better continuity: long-running projects keep memory across sessions and across different agents.
- Grounded answers: context packages include source paths, titles, tags and relevant excerpts.
- Safer collaboration: agent namespaces prevent private context from different agents being mixed accidentally.
- Inspectable memory: humans can open the vault as plain Markdown or in Obsidian-like tools.
- Automation-ready output: CLI commands support
--json, so agents and external tool servers can consume stable machine-readable responses.
Why
LLMs do not have infinite context. Brainlink gives agents an external memory layer:
- Durable knowledge is written as Markdown.
- Notes are connected with
[[wiki links]]. - Concepts are classified with
#tags. - Brainlink builds a local JSON index (
.brainlink/index.json) and private encrypted search packs. - Agents query the index before responding.
- Brainlink returns compact, source-backed context.
Markdown is the source of truth. .brainlink/index.json is a rebuildable index artifact.
After each index run, Brainlink also writes private encrypted search packs at .brainlink/search-packs/*.blpk to preserve fast retrieval and portable recovery.
Online retrieval always uses a single compression stage per pack; optional second-stage compression is reserved for offline backup artifacts only.
Pack decryption uses a Brainlink key from $BRAINLINK_HOME/keys or from BRAINLINK_SEARCH_PACK_KEY when explicitly configured.
Legacy .jsonl.gz packs are upgraded to .blpk automatically on first search/context access.
Features
- Local-first Markdown vault.
- Obsidian-compatible
[[wiki links]]and#tags. - Weighted graph edges so agents can rank relationship importance and priority.
- Backlinks, broken-link reports, orphan detection and validation.
- Full-text, semantic and hybrid retrieval on a local file index.
- Middle-out context assembly around the strongest chunk per document.
- In-process index and context caching with automatic invalidation on index updates.
- Optional CAG context packs at
.brainlink/context-packs/*.json, derived from the current index signature and reusable across repeated context calls. - HTTP graph server caches generated frontend assets and graph-layout JSON payloads by signature, and skips layout serialization when ETag returns
304. - Compressed-space prefiltering for
.blpkpacks before decryption and scan. - Incremental indexing that reprocesses only changed markdown files and reuses existing chunks/embeddings for unchanged notes.
- Adaptive compressed-pack rebuild policy to keep indexing fast during small edit batches.
- Agent namespaces under
agents/<agent-id>/. - S3-compatible bucket vaults through
s3://bucket/prefixURIs. - CLI with machine-readable
--jsonoutput. - Short CLI alias:
blink. - Built-in MCP stdio server for agent tool integration.
- Local HTTP API.
- Realtime graph UI with agent selector and colored knowledge groups.
- Graph renderer uses a cauliflower-style hub layout: the primary hub stays centered, segment hubs anchor surrounding lobes, and visual edges are simplified to root hub -> segment hubs -> local context nodes.
- Real weighted
[[wiki link]]edges stay preserved in the indexed graph APIs for backlinks, ranking and context traversal; the browser layout uses a separate visual edge layer for readability. - Graph exploration uses stable chunk streaming (
/api/graph-stream) with explicit node/edge budgets, returning the full mode-level scene while it fits the budget. - Render pipeline uses WebGL in a dedicated worker through
OffscreenCanvas, keeping the main thread focused on UI controls and details panels. - Large graph layout API automatically uses compact payload encoding with link-coverage-aware edge selection to reduce initial client load without hiding major relationships.
- Large-segment layout spacing now grows logarithmically to keep initial visual density consistent between medium and very large vaults (for example, ~1k vs ~50k notes).
- Graph coordinates are visually compacted across graph sizes so reset starts from a stable fitted scene and zoom-in progressively reveals local detail.
- Zoomed-out graph summarizes the scene as segment hub clusters, then progressively reveals individual nodes as the user zooms in.
- Graph reset fits the full graph scene instead of starting in a separate macro overview mode.
- Graph filtering runs in a dedicated browser worker to keep the UI thread responsive during heavy datasets.
- Node titles are shown as the user zooms closer, while labels remain bounded to visible on-screen nodes in very large graphs.
Install
Requirements:
- Node.js
>=22.5.0 - npm
npm install -g @andespindola/brainlink@latestThe package installs two equivalent commands:
brainlink --help
blink --helpUse brainlink when clarity matters. Use blink for faster daily terminal usage.
The npm package page may show npm i @andespindola/brainlink. That installs
Brainlink as a project dependency. Use -g when you want the terminal commands
available globally, or run it without a global install:
npx @andespindola/brainlink@latest --helpAgent Autonomous Setup
This section is written for agents. If you are an AI agent operating in a user workspace, use this workflow to install and use Brainlink without requiring the user to run commands manually.
For a condensed setup path, see docs/QUICKSTART.md.
1. Check Whether Brainlink Is Installed
command -v blink || command -v brainlinkIf neither command exists, install it:
npm install -g @andespindola/brainlink@latestThen verify:
blink --help2. Use The Default Vault Or Choose A Custom Vault
By default, Brainlink stores memory in:
$HOME/.brainlink/vaultUse the default vault when memory should span many projects:
blink initChoose a project-local vault only when memory belongs to one repository:
BLINK_VAULT=".brainlink-vault"
blink init "$BLINK_VAULT"You can also set BRAINLINK_HOME to move Brainlink's default home directory:
export BRAINLINK_HOME="/path/to/brainlink-home"3. Choose An Agent Namespace
Use a stable namespace for yourself:
BLINK_AGENT="coding-agent"Use shared only for knowledge that should be visible to every workflow.
4. Read Memory Before Acting
Before answering or changing code, retrieve context:
blink context "What should I know before working on this task?" \
--agent "$BLINK_AGENT" \
--jsonIf the context is weak, inspect raw search results:
blink search "architecture conventions tests release" \
--agent "$BLINK_AGENT" \
--mode hybrid \
--limit 10 \
--json5. Write Durable Memory After Learning Something Useful
Only store knowledge that is likely to matter later:
blink add "Testing Policy" \
--agent "$BLINK_AGENT" \
--content $'Run npm run check before final delivery. #testing #process\n\n## Context Links\n\n- [[Release Checklist]]'Brainlink does not infer durable graph relationships from generated context. A context result is only a read package for the model. To create a real graph link, write a concise ## Context Links section and put the canonical [[Note Title]] links there.
Writes with blink add reindex the vault automatically by default. This can be disabled with --no-auto-index and controlled globally with autoIndexOnWrite in brainlink.config.json.
When adding memory, follow this contract:
- Link the new note to existing notes through
## Context Linkswhen there is a related concept. - Use the exact target note title inside
[[...]]. - Add retrieval tags such as
#architecture,#decision,#runbookor#preference. - General wiki-link mentions outside
## Context Linksremain searchable Markdown content, but they do not become graph edges.
If you disable auto-index, run blink index after batched writes.
6. Validate Memory Health
blink validate --agent "$BLINK_AGENT" --json
blink broken-links --agent "$BLINK_AGENT" --json
blink orphans --agent "$BLINK_AGENT" --jsonAgent Operating Loop
Use this loop during real work:
- Identify the task and choose
BLINK_AGENT. - Run
blink context "<task>" --agent "$BLINK_AGENT" --json. - Use returned sources as project memory.
- Perform the task.
- Save only durable learnings with
blink add, including[[wiki links]]to related notes. - Run
blink indexonly when auto-index was disabled during a batch. - Validate with
blink validate,blink broken-linksandblink orphanswhen graph links matter.
Do not store secrets, credentials, private keys, access tokens or transient chat noise.
Quick Start
blink init ./vault
blink add "Architecture" \
--vault ./vault \
--content "Brainlink keeps Markdown as source of truth. #architecture"
blink add "Auth Decision" \
--vault ./vault \
--content "We chose JWT for API clients. [[Architecture]] #auth #jwt"
blink search "jwt auth" --vault ./vault
blink context "how does auth work?" --vault ./vault
blink server --vault ./vaultOpen the graph UI:
http://127.0.0.1:4321When --vault is omitted, commands use the default vault at $HOME/.brainlink/vault. Pass --vault or configure vault in brainlink.config.json when you want a custom project-local vault.
Bucket Vaults
Brainlink can use an S3-compatible bucket as the Markdown source of truth:
export AWS_REGION="us-east-1"
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
blink add "Architecture" \
--vault "s3://my-memory-bucket/brainlink" \
--content "Bucket Markdown is the source of truth. #architecture"
blink index --vault "s3://my-memory-bucket/brainlink"
blink context "architecture" --vault "s3://my-memory-bucket/brainlink"For Cloudflare R2, MinIO or another S3-compatible endpoint:
export BRAINLINK_S3_ENDPOINT="https://<account-id>.r2.cloudflarestorage.com"
export BRAINLINK_S3_FORCE_PATH_STYLE=1Bucket vaults mirror Markdown into a local cache under
$BRAINLINK_HOME/bucket-cache. The bucket remains canonical; the local
.brainlink/index.json stays a disposable index artifact. Run index after remote
bucket changes before relying on search, context, graph or validation
commands. Watch mode is only supported for local filesystem vaults.
Core Model
vault/
agents/
shared/
architecture.md
coding-agent/
implementation-policy.md
research-agent/
source-review-policy.md
.brainlink/
index.jsonPermanent data:
- Markdown notes
- optional Git history around the vault
Rebuildable data:
.brainlink/index.json- full-text records
- local embedding vectors
- local embedding buckets
- chunks
- resolved links
- backlinks
Agent Namespaces
Brainlink separates memory by agent so multiple agents can use the same CLI without mixing private context.
Use shared for project-wide memory:
blink add "Project Rules" \
--vault ./vault \
--agent shared \
--content "All agents should run tests before final answers. #process"Use a dedicated namespace for private agent memory:
blink add "TypeScript Policy" \
--vault ./vault \
--agent coding-agent \
--content "Prefer explicit types and functional core boundaries. [[Project Rules]] #typescript"List indexed namespaces:
blink agents --vault ./vault
blink agents --vault ./vault --jsonQuery a single namespace:
blink search "typescript" --vault ./vault --agent coding-agent --json
blink search "authentication token policy" --vault ./vault --agent coding-agent --mode semantic --json
blink context "how should I change this module?" --vault ./vault --agent coding-agent
blink graph --vault ./vault --agent coding-agent --jsonLink resolution is scoped:
- same agent namespace
shared- unresolved link
This allows coding-agent and research-agent to both have a note named Architecture without contaminating each other's private memory.
MCP Server Integration
Brainlink ships a stdio MCP server with the npm package:
brainlink-mcpExample MCP client configuration:
{
"mcpServers": {
"brainlink": {
"command": "brainlink-mcp"
}
}
}One-Command Agent Setup
If your agent runtime is Codex-compatible, run:
blink agent install --self-test
blink agent upgradeThis configures ~/.codex/config.toml with Brainlink MCP (brainlink-mcp) so Brainlink is available by default in agent sessions.
agent install and agent upgrade also apply the MCP fully-auto bootstrap policy by default (enforceBootstrap, enforceContextFirst, autoBootstrapOnRead, autoBootstrapOnStartup all enabled).
If you are inside this repository and want plugin gallery setup too:
blink agent install --plugin-path ./plugins/brainlinkTo verify:
blink agent statusFor fully automated first run (vault index + health + bootstrap readiness + agent integration):
blink quickstart --query "what should I know before this task?" --jsonFor a locked-down setup, allowlist the vaults that MCP clients may access:
{
"mcpServers": {
"brainlink": {
"command": "brainlink-mcp",
"env": {
"BRAINLINK_ALLOWED_VAULTS": "/absolute/path/to/project-vault,/absolute/path/to/team-vault"
}
}
}
}Install In MCP Client Stores
Brainlink can be exposed to MCP-compatible client stores in two ways:
- Register the stdio server directly when the client accepts
mcpServersconfiguration. - Register the local plugin from this repository when the client supports a plugin gallery or local marketplace.
Direct MCP server setup:
npm install -g @andespindola/brainlink@latest
command -v brainlink-mcpUse this server configuration in any MCP-compatible client that reads a JSON MCP manifest:
{
"mcpServers": {
"brainlink": {
"command": "brainlink-mcp"
}
}
}Local plugin gallery setup:
npm install -g @andespindola/brainlink@latest
git clone https://github.com/andersonflima/brainlink.git "$HOME/brainlink"
mkdir -p "$HOME/plugins"
ln -s "$HOME/brainlink/plugins/brainlink" "$HOME/plugins/brainlink"Then register the plugin in the local marketplace file used by compatible clients:
node <<'NODE'
const fs = require('node:fs')
const os = require('node:os')
const path = require('node:path')
const marketplacePath = path.join(os.homedir(), '.agents', 'plugins', 'marketplace.json')
const pluginEntry = {
name: 'brainlink',
source: {
source: 'local',
path: './plugins/brainlink'
},
policy: {
installation: 'AVAILABLE',
authentication: 'ON_INSTALL'
},
category: 'Productivity'
}
fs.mkdirSync(path.dirname(marketplacePath), { recursive: true })
const marketplace = fs.existsSync(marketplacePath)
? JSON.parse(fs.readFileSync(marketplacePath, 'utf8'))
: {
name: 'local',
interface: {
displayName: 'Local'
},
plugins: []
}
const plugins = Array.isArray(marketplace.plugins) ? marketplace.plugins : []
marketplace.plugins = [...plugins.filter((plugin) => plugin?.name !== 'brainlink'), pluginEntry]
fs.writeFileSync(marketplacePath, `${JSON.stringify(marketplace, null, 2)}\n`)
NODERestart the client after changing marketplace or MCP configuration so it reloads the Brainlink entry. The plugin starts brainlink-mcp and exposes the same tool set listed below.
Available tools:
brainlink_bootstrap: plug-and-play entrypoint that runs index + health checks and can return context in one call.brainlink_policy: read or update bootstrap/context-first policy, including presets (preset: "fully-auto" | "strict").brainlink_recommendations: return an automatic action plan so agents can run Brainlink in the recommended order, including RAG/CAG context strategy guidance.brainlink_context: read indexed context for a task or question; passstrategy: "rag"for fresh retrieval assembly,strategy: "cag"for persisted context packs orstrategy: "auto"for CAG hits with RAG fallback.brainlink_context_packs: list or clear persisted CAG context packs.brainlink_search: search indexed notes.brainlink_explain: explain why indexed notes matched a query.brainlink_dedupe: detect duplicate candidates using exact hash + semantic similarity scores.brainlink_resolve_duplicate: resolve duplicate pairs (merge,link,ignore) with connectivity-safe fallback edges.brainlink_add_note: write durable Markdown memory and reindex.brainlink_remember: capture durable memory with inferred title, tags and Context Links; supports dry-run.brainlink_inbox_add: capture a quick untriaged memory item.brainlink_inbox_list: list untriaged inbox memory items.brainlink_inbox_process: suggest titles, tags and links for inbox items.brainlink_delete_note: delete a durable Markdown note by title or path after explicit confirmation and reindex.brainlink_add_file: ingest a local file as a note and reindex.brainlink_canonicalize_context_links: ensure existing notes link to inferred context hubs.brainlink_volatile_add: write temporary agent-decided memory with TTL; volatile sections are included in context and never create durable graph edges.brainlink_volatile_clear: clear temporary memory for the current vault/agent namespace.brainlink_index: rebuild the vault index. Passfull=truefor a complete source reindex.brainlink_stats: read indexed vault statistics.brainlink_doctor_actions: return vault checks plus prioritized executable next actions.brainlink_validate: validate broken links and orphan notes.brainlink_sync: run index, stats, validation, broken-link and orphan checks in one call.brainlink_graph: read indexed graph nodes and weighted links.brainlink_graph_contexts: list the visual graph contexts used by the local server.brainlink_broken_links: list unresolved wiki links.brainlink_suggest_links: suggest Context Links for content or fixes for unresolved wiki links.brainlink_repair_links: repair unresolved wiki links by retargeting safe matches or creating placeholder target notes.brainlink_orphans: list disconnected notes.brainlink_session_close: write or preview a session handoff note.brainlink_project_init: seed project memory from local project docs.
For the most automatic workflow, start MCP sessions with brainlink_bootstrap (optionally with query) and then continue with brainlink_context/brainlink_add_note.
MCP is kept in parity with practical Brainlink CLI workflows when a feature is safe and meaningful for tool clients.
By default, Brainlink enforces context-first for MCP reads (enforceContextFirst=true): non-context read tools return preflight until brainlink_context is called for the vault/agent session.
By default, MCP startup already runs bootstrap on the configured default vault/agent (autoBootstrapOnStartup=true), so sessions begin warm.
By default, Brainlink enforces bootstrap and auto-runs it for read tools when session state is missing or stale (autoBootstrapOnRead=true).
If you disable autoBootstrapOnRead through brainlink_policy, read tools return a preflight instruction with suggested brainlink_bootstrap arguments.
brainlink_bootstrap, brainlink_policy and preflight responses include structured nextActions so MCP clients can continue automatically without custom parsing.
For one-call planning, use brainlink_recommendations to get the recommended tool sequence for the current vault/agent/query.
The MCP context tools are plug-and-play by default: omit strategy to use the configured token-efficient default (auto unless changed), pass strategy: "cag" for repeated/stable task context, or pass strategy: "rag" when fresh retrieval is required. brainlink_recommendations, preflight responses and policy next actions include executable context arguments so clients can continue without custom parsing.
The same linking rule applies through MCP: brainlink_context is read-only, and real graph links require Markdown notes with explicit ## Context Links sections. brainlink_add_note and brainlink_add_file reindex by default and include index + writeConnectivity metadata. Brainlink does not auto-link new notes to fallback hubs.
Agents can raise the importance of a relationship by putting priority markers on the same line as a wiki link:
- [ ] Review [[Architecture]] priority: high
Related: [[Incident Runbook]] #criticalIndexed edges expose weight and priority (low, normal, high, critical) through CLI JSON, HTTP graph APIs and brainlink_graph. Brainlink indexes every non-self [[wiki link]] inside ## Context Links as a graph edge. Old indexes are rebuilt automatically when their graph link model version is missing or stale.
To migrate older vaults without deleting existing Markdown, generate concise context-link sections from current wiki-link mentions:
blink migrate-context-links --vault ./vault --limit 5
blink index --vault ./vault --fullGraph UI
Start the local frontend:
blink server --host 127.0.0.1 --port 4321By default, the server uses $HOME/.brainlink/vault. Pass --vault ./vault only when you want to inspect a custom vault.
By default, the server watches Markdown files in local filesystem vaults and reindexes after note changes. Use --no-watch to disable realtime reindexing.
By default, blink server tries to open the graph in a native desktop GUI window:
- macOS: Swift + WebKit
- Windows: PowerShell WinForms WebBrowser
- Linux: optional Python GTK + WebKit2 (requires
python3+gi+WebKit2)
On Linux, native GUI is disabled by default for better startup performance. Enable it with BRAINLINK_LINUX_NATIVE_GUI=1.
If native GUI launch is unavailable on your system, it falls back to dedicated app-window mode and then to the default browser.
For Chromium-family browsers on Linux (chromium, chromium-browser, google-chrome, microsoft-edge, brave-browser), Brainlink now auto-applies compatibility flags during launch (--ozone-platform=x11, --ozone-platform-hint=x11, --disable-gpu, --disable-vulkan, --use-gl=swiftshader, --disable-features=Vulkan,VaapiVideoDecoder, --disable-background-networking) to avoid common Wayland/Vulkan/VAAPI startup issues.
On Linux, Brainlink opens the graph through the system default browser first (xdg-open), then $BROWSER/detected browsers as fallback. Chromium-family app-window mode is optional via BRAINLINK_LINUX_APP_WINDOW=1.
Use --no-open to keep it headless.
When native GUI is used, the GUI window automatically closes when the blink server process stops.
The graph UI shows:
- notes as nodes
- all non-self
[[wiki links]]inside## Context Linksas weighted indexed edges - default cauliflower-style visual layout centered on the primary hub, with segment hubs anchoring surrounding lobes and visual edges simplified to root hub -> segment hubs -> local context nodes
- details opened in a non-modal side panel (tags, outgoing links, backlinks, full Markdown content), so zoom and pan remain available while inspecting data
- neutral graph nodes with segment/group metadata
- agent selector (id-only labels) for isolated views
- context selector for segment-scoped cauliflower subgraphs derived from the visual graph context
- graph filter matches title, path, tags and note content
- graph filter keeps hub context nodes visible (
Memory Hub/MOC/high-degree fallback) to preserve relationship readability - realtime refresh while watch mode is enabled
- graph controls for zoom in, zoom out, fit visible nodes and reset-to-fit-all
- wheel zoom (including
cmd+scrollandctrl+scroll) anchored to cursor position for faster navigation in large graphs - wheel/button zoom updates immediately at the cursor anchor without delayed focus-transition interpolation
- Bloom-like scene navigation: reset fits the current graph scene, wheel zoom stays anchored to the cursor, and worker-driven WebGL rendering keeps pan/zoom interaction responsive
- zoom-out cluster mode that shows segment hub clusters first, then reveals local nodes as zoom increases
- keyboard shortcuts:
+zoom in,-zoom out,0reset fit - click on a node opens its details panel; double-click on empty canvas zooms in at cursor position
- floating graph totals (notes, links, tags) below the Brainlink title
- graph rendering safeguards (batched GPU draw calls, lower redraw rate, zoom-aware interaction)
- adaptive CPU safeguards for large graphs: idle frame pacing, throttled background physics updates and cached viewport dimensions to reduce redraw/layout overhead while preserving interaction responsiveness
- worker-first WebGL rendering with Canvas fallback when
OffscreenCanvasor worker rendering is unavailable - large graph view keeps one indexed graph model across zoom levels, uses a stable visual hierarchy for rendering, uses segment clusters at high zoom-out, and shows node titles as zoom approaches readable scale
The server indexes before starting by default. Use --no-index to skip that step:
blink server --vault ./vault --no-indexHTTP API
The HTTP API is mostly read-oriented and exists to power the graph UI, local inspection workflows and the local document-import modal.
The server always refuses non-loopback hosts. Brainlink HTTP only runs on localhost.
Routes:
GET /api/agentsGET /api/graph-contextsGET /api/graphGET /api/graph-layoutGET /api/graph-view?x=<x>&y=<y>&w=<width>&h=<height>&scale=<scale>GET /api/graph-stream?x=<x>&y=<y>&w=<width>&h=<height>&scale=<scale>&nodeBudget=<n>&edgeBudget=<n>GET /api/graph-node?id=<node-id>GET /api/search?q=<query>&limit=8&mode=hybridGET /api/context?q=<query>&limit=8&tokens=1500&mode=hybridGET /api/linksGET /api/backlinks?title=<title>GET /api/statsGET /api/broken-linksGET /api/orphansGET /api/validatePOST /api/import-filewith multipart fieldfile
Read routes accept agent=<agent-id>:
/api/graph-layout?agent=coding-agent
/api/graph-layout?agent=coding-agent&context=Architecture
/api/search?q=typescript&agent=coding-agent&mode=hybrid
/api/context?q=module-boundaries&agent=coding-agent&mode=semanticCLI Reference
Every command works with either brainlink or blink.
agent
blink agent install
blink agent install --self-test
blink agent upgrade
blink agent policy --preset fully-auto
blink agent policy --preset strict
blink agent policy --enforce-context-first false
blink agent install --plugin-path ./plugins/brainlink
blink agent install --mcp-only --allowed-vaults "/absolute/vault,/absolute/team-vault"
blink agent statusInstalls/checks agent integration. install writes Brainlink MCP config into ~/.codex/config.toml.
When plugin files are available, it also links Brainlink plugin files into ~/plugins/brainlink and updates ~/.agents/plugins/marketplace.json.
With --self-test, install also validates MCP block presence, command wiring and local plugin registration signals.
Use agent upgrade on legacy installations to reapply current defaults and run the same self-test diagnostics.
Use agent policy --preset fully-auto for plug-and-play defaults, or agent policy --preset strict to require explicit bootstrap calls.
Both presets keep enforceContextFirst=true so Brainlink stays the primary context source for MCP sessions.
quickstart
blink quickstart --json
blink quickstart --vault ./team-vault --agent coding-agent --query "architecture decisions" --json
blink quickstart --vault ./team-vault --mcp-only --jsonRuns index + doctor + stats + validation, refreshes bootstrap session readiness, optionally returns context for a query, and (by default) upgrades local agent integration for plug-and-play MCP usage.
When --mode, --limit or --tokens are omitted, quickstart uses agent profile defaults when available.
Practical Memory Workflows
blink remember --content "Keep Markdown as the source of truth. #architecture"
blink remember --content-file ./handoff.md --dry-run
blink inbox add --content "Quick note to triage later"
blink inbox list
blink inbox process --json
blink session-close --content "Validated release flow"
blink daily --dry-run
blink suggest-links --content "Architecture and release flow"
blink suggest-links --broken
blink repair-links
blink search "architecture" --explain
blink explain "architecture"
blink doctor --actionable
blink project init --path .remember infers a title, tags and Context Links before writing a durable note. inbox captures quick untriaged memory and later suggests titles, tags and links. session-close/daily writes a handoff note with vault health and git status. suggest-links proposes Context Links or likely fixes for unresolved wiki links. repair-links retargets high-confidence broken links and creates #triage placeholder notes for unresolved targets that cannot be safely retargeted. doctor --actionable returns prioritized commands instead of only checks. project init seeds memory from project docs such as AGENTS.md, README.md and architecture docs.
config
blink config where
blink config get vault
blink config doctor
blink config doctor --fix
blink config set-vault /absolute/path/to/existing-vault
blink config set-vault /absolute/path/to/existing-vault --migrate-from ~/.brainlink/vault
blink config set-vault "s3://my-memory-bucket/brainlink" --globalconfig set-vault writes configuration through CLI (no manual file edits required).
By default it writes local config (./brainlink.config.json), appends the vault to allowedVaults, and migrates Markdown memory from the current configured vault when the target is empty.
When the configured default vault is changed manually in config files, Brainlink also performs automatic migration on the next command that uses the configured vault (without explicit --vault).
Use --global to write to $BRAINLINK_HOME/brainlink.config.json, --no-migrate to skip migration, and --no-index to skip post-migration indexing.
config doctor is dry-run by default; use --fix to apply safe config normalization and allowlist fixes.
vaults
blink vaults list
blink vaults list --json
blink vaults use /absolute/path/to/vault
blink vaults use /absolute/path/to/vault --global
blink vaults delete /absolute/path/to/vault --yes
blink vaults delete /absolute/path/to/vault --yes --prune-configLists known vaults from the configured default, allowedVaults, and the built-in default at $HOME/.brainlink/vault.
vaults use chooses the default vault without migrating memory; use migrate-vault or config set-vault --migrate-from when you want to copy Markdown memory between vaults.
vaults delete only deletes local filesystem vaults, requires --yes, refuses bucket vaults, and refuses deleting the current default vault. Choose another default first with vaults use.
delete-note
blink delete-note --title "Architecture" --yes
blink delete-note --path agents/shared/architecture.md --yes
blink delete-note --title "Architecture" --agent coding-agent --yes
blink delete-note --path agents/shared/architecture.md --yes --no-auto-indexDeletes a durable Markdown note from the selected vault. The command requires --yes, accepts exactly one selector (--title or --path), refuses non-Markdown/protected paths, and reindexes by default. Bucket vault note deletion is intentionally refused until provider-native object deletion is implemented safely.
migrate-vault
blink migrate-vault --from ~/.brainlink/vault --to ./team-vault --dry-run
blink migrate-vault --from ~/.brainlink/vault --to ./team-vault
blink migrate-vault --from ~/.brainlink/vault --to "s3://my-memory-bucket/brainlink"
blink migrate-vault --from ~/.brainlink/vault --to ./team-vault --report ./migration-report.jsonRuns explicit markdown migration between vaults while preserving conflicts as .conflict-<timestamp> files.
Use --dry-run to preview copied, conflicted and unchanged counts before writing.
db-import
blink db-import --vault ./team-vault
blink db-import --vault ./team-vault --db ./legacy/brainlink.db
blink db-import --vault ./team-vault --db ./legacy/brainlink.db --table legacy_notes --dry-runImports durable memory from a legacy SQLite database into Markdown notes (agents/<agent-id>/*.md) and reindexes by default.
When --db is omitted, Brainlink auto-detects common legacy paths such as <vault>/.brainlink/brainlink.db.
Use --agent <id> to force all imported rows into one namespace, --limit for incremental imports, --dry-run to preview without writing files, and --no-index to defer reindexing.
import-file
blink import-file ./report.pdf --vault ./team-vault
blink import-file ./report.pdf --vault ./team-vault --agent coding-agent
blink import-file ./report.pdf --vault ./team-vault --title "Quarterly Report"
blink import-file ./report.pdf --vault ./team-vault --no-auto-indexConverts a document with Docling and imports the converted Markdown as a durable note. The docling executable must be installed and available in PATH.
The graph UI exposes the same flow through the upload button in the toolbar.
init
blink init
blink init ./vault
blink init ./team-vault --migrate-from ~/.brainlink/vaultInitializes vault metadata. Without an argument, Brainlink initializes the default vault at $HOME/.brainlink/vault.
When initializing an empty custom vault, existing Markdown content from the default vault is copied into it and reindexed so context is not left behind. Use --no-migrate-existing to start with an empty custom vault, or --migrate-from <vault> to copy from a specific source. Existing target files are never overwritten; conflicting source files are preserved with a .conflict-<timestamp> suffix.
add
blink add "Note Title" --agent coding-agent --content "Markdown content"
blink add "Note Title" --vault ./vault --agent coding-agent --content "Markdown content"
blink add "Note Title" --vault ./vault --content-file ./notes.md
blink add "Note Title" --vault ./vault --content-file ./notes.md --no-auto-index--content and --content-file are mutually exclusive. Add --no-auto-index when you want to defer reindexing.
Creates a Markdown note under agents/<agent-id>/. Common secret patterns are blocked by default; use --allow-sensitive only for an intentionally protected vault.
To avoid disconnected memory, Brainlink auto-adds a fallback wiki edge when a note is written without links, creating agent hub notes when needed.
add also returns possibleDuplicates (exact hash + semantic candidates) so agents can resolve duplicate memory right after writes.
dedupe
blink dedupe --vault ./vault --json
blink dedupe --vault ./vault --agent coding-agent --limit 20 --min-score 0.92 --json
blink dedupe --vault ./vault --no-semantic --jsonDetects possibleDuplicate pairs using exact content hashes and optional semantic similarity.
dedupe-resolve
blink dedupe-resolve --vault ./vault --left agents/shared/a.md --right agents/shared/b.md --action merge --json
blink dedupe-resolve --vault ./vault --left agents/shared/a.md --right agents/shared/b.md --action link --json
blink dedupe-resolve --vault ./vault --left agents/shared/a.md --right agents/shared/b.md --action ignore --jsonResolves a duplicate pair with merge, link or ignore.
When action is not merge, Brainlink still creates a low-priority related edge (#related-to) so notes remain connected.
index
blink index
blink index --vault ./vault
blink index --vault ./vault --fullRebuilds the local index from Markdown files. By default, unchanged notes reuse existing indexed chunks for speed.
Use --full to force a complete source reindex of every Markdown note. Full reindex builds the replacement index before persisting it, so existing context is not cleared first.
Brainlink also performs this complete source reindex automatically when it detects that the stored graph link model is older than the current model.
bench
blink bench --vault ./vault
blink bench --vault ./vault --watch
blink bench --vault ./vault --watch --debounce 500
blink bench --vault ./vault --jsonRuns indexing with realtime phase telemetry (start, scan, parse, embed, persist, packs, complete) and prints a benchmark summary at the end of each run.
Summary includes compression behavior for .blpk packs when rebuild happens:
- pack rebuild reason
- pack count and pack build duration
- uncompressed input bytes vs compressed output bytes
- saved percentage
- objective guardrails (minimum savings and maximum latency regression thresholds)
Use --watch to keep benchmarking incremental reindex runs after Markdown changes (local filesystem vaults only).
When .brainlink/search-packs/manifest.json is missing but .blpk files exist, Brainlink repairs the manifest first and avoids unnecessary full pack rebuild on small edits.
pack-backup
blink pack-backup --vault ./vault
blink pack-backup --vault ./vault --output ./vault/.brainlink/backups/custom.blpkbak.gz
blink pack-backup --vault ./vault --jsonCreates an offline backup artifact of encrypted search packs with a second compression pass.
This is intentionally outside the online retrieval path (index, search, context).
agents
blink agents --vault ./vault
blink agents --vault ./vault --jsonLists indexed agent namespaces.
search
blink search "query" --vault ./vault --limit 10
blink search "query" --vault ./vault --agent coding-agent --json
blink search "query" --vault ./vault --mode semantic --jsonRuns retrieval over indexed chunks.
If --mode or --limit is omitted, Brainlink resolves values from the current agent profile before falling back to global defaults.
Modes:
hybrid: default; combines lexical matching with local embedding similarity.fts: exact lexical retrieval from the file index.semantic: local deterministic embedding similarity only.
Hybrid results are cached in-memory for a short TTL and invalidated automatically when the local index file changes. Context selection uses a middle-out strategy: it starts from the strongest chunk in a note and expands to neighboring chunks while respecting token budget.
context
blink context "question" --vault ./vault --limit 8 --tokens 1500
blink context "question" --vault ./vault --agent coding-agent --json
blink context "question" --vault ./vault --agent coding-agent --mode hybrid --json
blink context "question" --vault ./vault --agent coding-agent --strategy cag --json
blink context "question" --vault ./vault --agent coding-agent --strategy auto --json
blink context-packs --vault ./vault --json
blink context-packs --vault ./vault --stale --clearBuilds a compact context package for an agent.
Repeated calls with the same vault, agent, query, mode and token/limit settings are served from a short in-memory cache while the index is unchanged.
The default strategy is configured by defaultContextStrategy and starts as auto, which uses CAG when a fresh pack exists and RAG otherwise, refreshing a pack for future calls. --strategy cag enables cache-augmented context generation by reading or refreshing a persisted context pack under .brainlink/context-packs; --strategy rag forces fresh retrieval assembly from the current index. Context responses include cache, metrics, requestedStrategy and recommendedStrategy metadata. Packs are derived artifacts and become stale when the index or volatile memory signature changes.
links
blink links --vault ./vault
blink links --vault ./vault --agent coding-agentLists indexed wiki links. JSON output includes weight and priority for each relationship.
backlinks
blink backlinks "Architecture" --vault ./vault
blink backlinks "Architecture" --vault ./vault --agent coding-agentLists notes pointing to a target title, ordered by strongest relationship first. JSON output includes weight and priority.
graph
blink graph --vault ./vault --json
blink graph --vault ./vault --agent coding-agent --jsonPrints indexed graph data. Edges include weight and priority so agents can categorize importance.
stats
blink stats --vault ./vault
blink stats --vault ./vault --agent coding-agent --json
blink stats --vault ./vault --agent coding-agent --extended --jsonPrints vault metrics.
Use --extended to include storage footprint, link quality ratios and observability probes (index, search, context latencies).
broken-links
blink broken-links --vault ./vaultLists unresolved wiki links.
orphans
blink orphans --vault ./vaultLists notes without incoming or outgoing links.
validate
blink validate --vault ./vaultValidates graph health. The command exits non-zero when required checks fail.
doctor
blink doctor --vault ./vaultRuns environment and vault checks. When vault has zero markdown and zero indexed documents, doctor prints recommended next steps (add note, inspect config source, migrate memory).
watch
blink watch --vault ./vaultWatches Markdown files and rebuilds the index when notes change.
canonicalize-context-links
blink canonicalize-context-links --vault ./vault --dry-run
blink canonicalize-context-links --vault ./vaultEnsures existing notes have canonical ## Context Links entries to inferred context hubs such as User Preferences Hub, GitHub Repositories Hub or Brainlink Hub. The command is idempotent, creates missing hub notes by default, and fully reindexes after writes unless --no-index is passed.
server
blink server
blink server --vault ./vault
blink server --vault ./vault --no-open
blink server --vault ./vault --no-watchStarts the local graph UI and HTTP API.
Watch mode is enabled by default for Markdown changes in local filesystem vaults. Use --no-watch to run without the watcher.
By default, it tries to open a native desktop GUI window for the graph URL.
On Linux, native GUI is disabled by default; enable it with BRAINLINK_LINUX_NATIVE_GUI=1.
If native GUI launch is unavailable, it falls back to dedicated app-window mode and then browser open.
When fallback opens Chromium-family browsers on Linux, Brainlink automatically uses compatibility launch flags for stable rendering on Ubuntu/Wayland setups.
Use --no-open to skip that behavior.
The HTTP server only binds to loopback hosts such as 127.0.0.1, localhost or ::1.
Machine-Readable Output
Commands with finite output support --json:
blink context "question" --vault ./vault --agent coding-agent --jsonWhen running through npm scripts, use --silent to keep stdout clean:
npm run --silent dev -- context "question" --vault ./vault --jsonConfiguration
Brainlink merges configuration in this order:
- Global:
$BRAINLINK_HOME/brainlink.config.json(or$HOME/.brainlink/brainlink.config.jsonby default) - Local:
brainlink.config.jsonin the current working directory - Local legacy compatibility:
.brainlink.jsonin the current working directory
If no vault is configured and no --vault flag is passed, Brainlink uses $HOME/.brainlink/vault.
{
"vault": ".brainlink-vault",
"host": "127.0.0.1",
"port": 4321,
"allowedVaults": [".brainlink-vault"],
"defaultAgent": "shared",
"autoIndexOnWrite": true,
"autoCanonicalContextLinks": true,
"defaultSearchLimit": 8,
"defaultContextTokens": 1500,
"defaultContextStrategy": "auto",
"embeddingProvider": "local",
"defaultSearchMode": "hybrid",
"chunkSize": 1200,
"searchPack": {
"rowChunkSize": 5000,
"compressionLevel": 5,
"useDictionary": true,
"guardrailMinSavingsPercent": 8,
"guardrailMaxLatencyRegressionPercent": 5
},
"agentProfiles": {
"coding-agent": {
"defaultSearchMode": "semantic",
"defaultSearchLimit": 8,
"defaultContextTokens": 1500,
"defaultContextStrategy": "auto"
},
"*": {
"defaultSearchMode": "hybrid"
}
}
}defaultAgent is optional. When set, CLI and MCP calls that omit --agent/agent use this value automatically. If not set, behavior remains as before.
agentProfiles is optional. When present, CLI and MCP resolve mode, limit, tokens and context strategy per agent automatically, then fallback to global defaults.
autoIndexOnWrite is optional and defaults to true. Set it to false to defer indexing after writes.
autoCanonicalContextLinks is optional and defaults to true. When enabled, blink add, brainlink_add_note and brainlink_add_file add a canonical ## Context Links entry to the inferred context hub, creating that hub when needed.
Remote MCP Server
Brainlink can run as a centralized MCP service for clustered workloads. This keeps one shared memory service inside the cluster while applications and agents connect to the MCP endpoint over Streamable HTTP.
BRAINLINK_MCP_TOKEN="change-me" brainlink mcp-server \
--vault /data/vault \
--host 0.0.0.0 \
--port 3333 \
--path /mcpThe server exposes:
POST /mcp MCP Streamable HTTP endpoint
GET /healthz liveness probe
GET /readyz readiness probeWhen BRAINLINK_MCP_TOKEN or --token is set, MCP requests must include:
Authorization: Bearer <token>For Kubernetes, run Brainlink as a central Deployment with a Service and a mounted vault volume:
apiVersion: apps/v1
kind: Deployment
metadata:
name: brainlink-mcp
spec:
replicas: 1
selector:
matchLabels:
app: brainlink-mcp
template:
metadata:
labels:
app: brainlink-mcp
spec:
containers:
- name: brainlink
image: brainlink:latest
args: ["brainlink", "mcp-server", "--vault", "/data/vault", "--host", "0.0.0.0", "--port", "3333"]
env:
- name: BRAINLINK_MCP_TOKEN
valueFrom:
secretKeyRef:
name: brainlink-mcp
key: token
ports:
- containerPort: 3333
readinessProbe:
httpGet:
path: /readyz
port: 3333
livenessProbe:
httpGet:
path: /healthz
port: 3333
volumeMounts:
- name: vault
mountPath: /data/vault
volumes:
- name: vault
persistentVolumeClaim:
claimName: brainlink-vault
---
apiVersion: v1
kind: Service
metadata:
name: brainlink-mcp
spec:
selector:
app: brainlink-mcp
ports:
- port: 3333
targetPort: 3333Use "embeddingProvider": "none" when you want FTS-only indexing.
For local security checks, set your Snyk token in the environment:
export SNYK_TOKEN="snyk_..."For GitHub Actions, add a repository secret SNYK_TOKEN and the CI/publish workflows will consume it automatically during build/test.
Set BRAINLINK_ALLOWED_VAULTS for external wrappers, including MCP servers, so a tool cannot pass arbitrary --vault paths:
export BRAINLINK_ALLOWED_VAULTS="/absolute/path/to/project-vault,/absolute/path/to/team-vault"Bucket vaults can be allowlisted with the same variable:
export BRAINLINK_ALLOWED_VAULTS="s3://my-memory-bucket/brainlink"Note Format
Brainlink supports Markdown with optional frontmatter:
---
title: "Auth Decision"
agent: "coding-agent"
type: "decision"
---
# Auth Decision
We chose JWT for API clients.
Related:
- [[Architecture]]
- [[API Gateway]]
#auth #jwt #decisionSupported signals:
titlefrontmatteragentfrontmatter- first
# Heading - file name fallback
[[Wiki Link]][[Wiki Link#Section]][[Wiki Link|Alias]]#tags
Development
npm install
npm run build
npm run test
npm run checkLarge vault benchmark:
npm run benchmark:large -- --notes 5000Use --keep to keep the generated temporary vault for inspection.
Local CLI:
npm run dev -- --help
npm run dev -- server --vault .brainlink-vaultPackage smoke test:
npm run pack:smokeArchitecture
src/
application/ use cases
cli/ command-line adapter
domain/ pure knowledge rules
infrastructure/ filesystem and index adaptersDetailed notes:
Current Limits
- Semantic search uses deterministic local embeddings, not a remote model provider.
embeddingProvidercurrently supportslocalandnone.- Link resolution is title-based inside each agent namespace, with
sharedas fallback. - HTTP API is local and unauthenticated.
- Watch mode depends on the platform filesystem watcher.
Stable Scope
The 1.0.0 line is the first stable functional release of the local-first memory loop:
- Markdown as durable memory.
- Rebuildable file index plus local embeddings and encrypted pack exports.
- CLI as the primary agent interface.
- HTTP graph API and frontend as inspection tools.
- Agent namespaces to avoid context mixing.
- MCP tools for context retrieval, durable memory writes and graph maintenance.
- Remote MCP server mode for centralized cluster access.
- Vault management commands for listing, selecting and safely deleting local vaults.
The stable release includes local semantic retrieval, local-first storage, remote MCP transport and operational vault management. Remote embedding providers and deeper graph editing remain future milestones.
Security
Brainlink is local-first by default.
- Do not expose the HTTP server publicly without authentication.
- Brainlink HTTP is localhost-only and refuses non-loopback hosts.
- Brainlink blocks common secret patterns by default when adding notes. Use
--allow-sensitiveonly for intentional, protected vaults. - Do not store secrets, credentials, API keys or regulated personal data unless the vault is protected by your own storage controls.
- Treat
.brainlink/index.jsonand.brainlink/search-packs/as disposable derived artifacts.
See SECURITY.md.
Contributing
See CONTRIBUTING.md.
License
MIT. See LICENSE. Copyright (c) 2026 Substructa. See COPYRIGHT.md.
Memory Optimization Loop (1-7)
Use this when your agent work needs consistent memory quality:
- Start with
blink context "<task>" --agent "$BLINK_AGENT" --json. - Keep notes focused with explicit
[[wiki links]]and#tags. - Route agent-specific knowledge to dedicated namespaces under
agents/<agent-id>/. - Keep
sharedas a curated global layer only. - Use targeted queries (
--limit, explicit terms,--mode hybrid) before broad scans. - Run the sync command after writing notes:
npm run brainlink:sync -- --vault ./vault --agent "$BLINK_AGENT"- Before final response, keep the returned context sources as the grounding baseline.
