
Research
/Security News
Mini Shai-Hulud Campaign Hits Red Hat Cloud Services npm Packages
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.
nano-brain
Advanced tools
Persistent memory and code intelligence for AI coding agents.
nano-brain is a persistent memory server for AI coding agents that solves session amnesia. It automatically ingests AI sessions, notes, and codebase files, indexes everything with hybrid search (BM25 + pgvector), and serves memories via MCP tools and REST API. Built in Go with PostgreSQL — single static binary, zero CGO dependencies.
POST /api/reload-config# Start PostgreSQL + pgvector
docker run -d --name nanobrain-pg -p 5432:5432 \
-e POSTGRES_USER=nanobrain -e POSTGRES_PASSWORD=nanobrain -e POSTGRES_DB=nanobrain_dev \
pgvector/pgvector:pg17
# Start Ollama + pull embedding model
ollama pull nomic-embed-text
# Check prerequisites
npx @nano-step/nano-brain@beta doctor
# Start server
npx @nano-step/nano-brain@beta
Also available as:
npx nano-brain@beta(unscoped alias)Note: Do NOT run
npx nano-brainfrom the nano-brain source directory — npm will resolve the local package instead of the registry. Run from any other directory.
# Build
CGO_ENABLED=0 go build -o nano-brain ./cmd/nano-brain
# Start PostgreSQL + pgvector (example with Docker)
docker run -d --name nanobrain-pg -p 5432:5432 \
-e POSTGRES_USER=nanobrain -e POSTGRES_PASSWORD=nanobrain -e POSTGRES_DB=nanobrain_dev \
pgvector/pgvector:pg17
# Start server
DATABASE_URL="postgres://nanobrain:nanobrain@localhost:5432/nanobrain_dev" ./nano-brain
# Register workspace
curl -X POST http://localhost:3100/api/v1/init \
-H "Content-Type: application/json" \
-d '{"root_path":"/path/to/project","name":"my-project"}'
# Write a document
curl -X POST http://localhost:3100/api/v1/write \
-H "Content-Type: application/json" \
-d '{"workspace":"<hash>","source_path":"notes/decision.md","content":"# Decision\nUse PostgreSQL.","tags":["decision"]}'
# Search
curl -X POST http://localhost:3100/api/v1/query \
-H "Content-Type: application/json" \
-d '{"workspace":"<hash>","query":"database decision"}'
Every release ships a SHA256SUMS asset alongside the four platform binaries.
You can verify a downloaded binary against the published checksums using
standard tooling:
TAG=v2026.6.2.1 # any release tag
curl -fLO https://github.com/nano-step/nano-brain/releases/download/$TAG/SHA256SUMS
curl -fLO https://github.com/nano-step/nano-brain/releases/download/$TAG/nano-brain-linux-amd64
sha256sum -c SHA256SUMS --ignore-missing
# nano-brain-linux-amd64: OK
npm install @nano-step/nano-brain (and the unscoped nano-brain alias)
performs this verification automatically during postinstall — a SHA-256
mismatch aborts the install with exit code 1 and removes the partial binary.
For air-gapped installs or environments where a corporate proxy modifies the
download stream, set NANO_BRAIN_SKIP_SHA_VERIFY=1 before running npm install
to bypass the check (a warning is printed so the bypass is visible in CI logs).
Releases tagged before this feature shipped do not have a SHA256SUMS asset;
installs of those versions succeed with a single WARN line and no verification.
See issue #320 for the
threat model and rationale.
Config file: ~/.nano-brain/config.yml
server:
host: localhost
port: 3100
database:
url: postgres://nanobrain:nanobrain@localhost:5432/nanobrain_dev
embedding:
provider: ollama # ollama or voyage
url: http://localhost:11434
model: nomic-embed-text
dimension: 0 # auto-detect from provider
concurrency: 3
search:
rrf_k: 60
recency_weight: 0.3
recency_half_life_days: 180
limit: 20
harvester:
opencode:
db_root: "" # e.g., ~/.ai-sandbox/opencode-dbs (multi-DB, highest priority)
db_path: "" # e.g., ~/.local/share/opencode/opencode.db (single DB)
session_dir: "" # e.g., ~/.local/share/opencode/storage (legacy JSON)
claudecode:
enabled: false
session_dir: ""
watcher:
debounce_ms: 2000
reindex_interval: 300
# Per-collection exclude_patterns and allowed_extensions are also supported
# via the workspaces map. See "Ignore patterns" section below for the
# global and workspace-local .nano-brainignore files.
storage:
max_file_size: 314572800 # 300MB
max_size: 10737418240 # 10GB
telemetry:
retention_days: 90
logging:
level: info
file: "" # empty = stdout only
summarization:
enabled: false # set to true to generate LLM summaries of harvested sessions
provider_url: "" # OpenAI-compatible endpoint, e.g. https://ai-proxy.example.com/v1
api_key: "" # or set NANO_BRAIN_SUMMARIZE_API_KEY env var
model: "nano-brain" # model name passed to the provider
max_tokens: 8000 # max tokens per LLM completion
concurrency: 3 # parallel map-phase LLM calls
When binding to a non-loopback address, enable auth to protect your memory:
server:
host: 0.0.0.0
port: 3100
auth:
enabled: true
realm: nano-brain
users:
- username: admin
password_hash: "$2a$10$..." # from: nano-brain auth hash <password>
tokens:
- "nbt_..." # from: nano-brain auth token
bypass_paths:
- /health
Generate credentials:
# Generate bcrypt hash for Basic Auth
nano-brain auth hash mypassword
# Generate bearer token
nano-brain auth token
Usage examples:
# Basic Auth
curl -u admin:mypassword http://host:3100/api/v1/query -d '{"query":"test"}'
# Bearer token
curl -H "Authorization: Bearer nbt_..." http://host:3100/api/v1/query -d '{"query":"test"}'
# MCP client with URL-embedded credentials
# url: http://admin:mypassword@host:3100/mcp
Two layers of .nano-brainignore files control what the watcher indexes,
both using standard .gitignore syntax (one pattern per line, supports **,
!negation, blank lines, # comments).
~/.nano-brain/.nano-brainignoreLoaded once at server startup. Patterns apply to every registered
collection across every workspace. Use this for rules that are personal
to your machine and span all your projects (e.g. always skip *.png).
# Skip generated files everywhere
*.png
*.jpg
*.pdf
build/
dist/
node_modules/
# But keep this one icon
!icons/important.png
<workspace_root>/.nano-brainignoreLoaded once per collection when the watcher starts watching it (server
startup, POST /api/v1/init, or POST /api/v1/collections). Patterns
apply only to that one workspace. Use this for project-specific rules
you want to share with your team via version control — e.g. skip
generated code that you commit to git but don't want indexed.
# nano-brain-specific rules for this repo (commit me)
*.generated.go
fixtures/large/
*.snap
Workspace-local rules layer additively on top of global rules and
per-collection .gitignore. There is no cross-file negation: a !pattern
in workspace-local cannot un-exclude a path matched by global.
The file at the workspace root is loaded for the code collection. The
sibling memory and sessions collections are rooted under ~/.nano-brain/
and do not normally need their own ignore files.
node_modules, .git, dist, build, target, etc.)~/.nano-brain/.nano-brainignore<workspace_root>/.nano-brainignore.gitignore (in collection root)exclude_patterns (config-level)allowed_extensions (whitelist)Both global and workspace-local files are loaded at collection registration time. To pick up edits:
POST /api/v1/init (this rebuilds the collection's filter and
re-reads the file).POST /api/reload-config does not re-read ignore files — only search
config and log level are reloaded by that endpoint.
Issues: #263 (global), #317 (workspace-local).
When summarization.enabled: true, nano-brain automatically generates structured markdown summaries of each harvested session using an OpenAI-compatible LLM provider. Summaries are:
session-summary for semantic search via the standard query/vsearch API (PG is the source of truth)By default, summaries are written to disk as Markdown files at the path configured in
summarization.output_dir (default: ~/.nano-brain/summaries). The file layout is:
<output_dir>/<workspace_name>/<source>_<slugified-title>_<YYYY-MM-DD>.md
Files are byte-identical to the documents.content field in PostgreSQL — disk is a
derivative view, DB is source of truth. Disk write failures (permission denied, disk
full) log a WARN but do not roll back the DB transaction.
To opt out (DB-only persistence):
summarization:
write_to_disk: false
To backfill historical summaries already in the DB:
nano-brain backfill-summaries
Quick setup with ai-proxy:
summarization:
enabled: true
provider_url: "https://ai-proxy.example.com/v1"
api_key: "" # set NANO_BRAIN_SUMMARIZE_API_KEY instead
model: "claude-sonnet-4-5"
max_tokens: 8000
concurrency: 3
Or via environment variable:
export NANO_BRAIN_SUMMARIZE_API_KEY="sk-..."
Large sessions (100K+ tokens) are handled via map-reduce chunking — no session is too large.
| Variable | Description |
|---|---|
NANO_BRAIN_CONFIG | Path to YAML config file (12-factor; useful in Docker/k8s). Precedence: --config flag > NANO_BRAIN_CONFIG > ~/.nano-brain/config.yml. Leading/trailing whitespace is stripped. If the env-pointed file does not exist, a WARNING: is printed to stderr and defaults are used (operator can spot typos). |
DATABASE_URL | PostgreSQL connection string |
VOYAGE_API_KEY | Voyage AI API key |
OPENCODE_DB_ROOT | OpenCode per-project DB root directory (multi-DB mode) |
OPENCODE_DB_PATH | OpenCode single SQLite database path |
OPENCODE_STORAGE_DIR | OpenCode session directory (legacy) |
NANO_BRAIN_SUMMARIZE_API_KEY | API key for the summarization LLM provider |
NANO_BRAIN_AUTH_ENABLED | Enable Basic Auth + Bearer Token (true/false) |
NANO_BRAIN_AUTH_TOKENS | Comma-separated bearer tokens |
NANO_BRAIN_* | Override any config field (e.g., NANO_BRAIN_SERVER_PORT=3100) |
Docker example — run the server in a container against a host PostgreSQL:
# /path/to/container-config.yml uses host.docker.internal for DB/Ollama
docker run -d \
-e NANO_BRAIN_CONFIG=/etc/nano-brain/config.yml \
-v /path/to/container-config.yml:/etc/nano-brain/config.yml:ro \
-p 3100:3100 \
nano-brain:latest
| Method | Path | Description |
|---|---|---|
| GET | /health | Health check |
| GET | /api/status | Server status with version, uptime, workspace stats |
| POST | /api/v1/init | Register workspace |
| GET | /api/v1/workspaces | List all workspaces (with doc counts) |
| POST | /api/v1/workspaces/resolve | Resolve path → workspace hash + registered status (read-only) |
| DELETE | /api/v1/workspaces/:hash | Permanently delete a workspace + cascade docs/chunks/embeddings |
| GET | /api/v1/wake-up | Workspace briefing |
| POST | /api/harvest | Trigger session harvesting |
| POST | /api/reload-config | Hot-reload configuration |
Workspace is passed in the JSON body for POST, query param for GET.
| Method | Path | Description |
|---|---|---|
| POST | /api/v1/write | Write/update document |
| POST | /api/v1/embed | Trigger embedding |
| POST | /api/v1/search | BM25 keyword search |
| POST | /api/v1/vsearch | Vector similarity search |
| POST | /api/v1/query | Hybrid search (BM25 + vector + RRF + recency) |
| POST | /api/v1/collections | Add collection |
| GET | /api/v1/collections | List collections |
| PUT | /api/v1/collections/:name | Rename collection |
| DELETE | /api/v1/collections/:name | Remove collection |
| GET | /api/v1/tags | List tags with counts |
| POST | /api/v1/get | Get single document by source_path or id |
| POST | /api/v1/multi-get | Batch fetch documents by paths or ids |
| POST | /api/v1/reindex | Queue reindex (202) |
| POST | /api/v1/update | Queue update (202) |
| POST | /api/v1/summarize | Trigger LLM summarization of harvested sessions |
| POST | /api/v1/wake-up | Workspace briefing with session_dir |
| Method | Path | Description |
|---|---|---|
| GET/POST | /mcp | Streamable HTTP (MCP 2025-03-26) |
| GET/POST | /sse | SSE transport (legacy) |
| Command | Description |
|---|---|
nano-brain (no args) | Start HTTP server (default: port 3100) |
nano-brain init --root=<path> | Register workspace |
nano-brain workspaces list | List registered workspaces with doc counts |
nano-brain workspaces current [--path=<p>] [--export|--json|--check] | Resolve current/path workspace hash. --export prints export NANO_BRAIN_WORKSPACE=<hash> for eval; --check exits 2 if not registered |
nano-brain workspaces remove --workspace=<hash> [--dry-run|--force] | Permanently delete a workspace + all its documents/chunks/embeddings |
nano-brain write | Write document via CLI |
nano-brain query [--scope=all] [--tags=t1,t2] | Hybrid search (BM25 + vector + RRF + recency) |
nano-brain search [--scope=all] [--tags=t1,t2] | BM25 keyword search |
nano-brain vsearch [--scope=all] [--tags=t1,t2] | Vector similarity search |
nano-brain wake-up --workspace=<hash> | Workspace briefing (collections, stats, recent memories) |
nano-brain get <source_path|uuid> --workspace=<hash> | Fetch a single document by source_path or UUID |
nano-brain tags --workspace=<hash> | List all tags with document counts |
nano-brain multi-get --workspace=<hash> --paths=p1,p2 | Fetch multiple documents in one round-trip |
nano-brain collection add|remove|list | Manage collections |
nano-brain harvest | Trigger session harvesting |
nano-brain backfill-summaries [--dry-run] [--workspace=] [--since=] | Export existing DB summaries to disk (.md files for Obsidian etc.) |
nano-brain cleanup-stale-raw [--dry-run] | Delete pre-#192 raw OpenCode session docs superseded by summaries |
nano-brain cleanup-orphan-workspaces [--dry-run] | Delete documents/chunks under workspace_hash values not registered in workspaces. Run BEFORE migration 00011 (issue #238). |
nano-brain bench generate|run|compare|stress | Benchmarking suite |
nano-brain db:migrate | Run pending goose migrations |
nano-brain db:migrate --from-v1 <path> | Import V1 SQLite data |
nano-brain logs [-n 50] [-f] | Tail log file |
nano-brain docker start|stop|status | Docker compose management |
nano-brain status [--json] | Server status |
nano-brain auth hash <password> | Generate bcrypt password hash for config |
nano-brain auth token | Generate random bearer token (nbt_-prefixed) |
nano-brain doctor [--json] | Check prerequisites (config, PostgreSQL, pgvector, Ollama, model) |
nano-brain exposes 14 tools via MCP (Model Context Protocol):
| Tool | Description |
|---|---|
memory_query | Hybrid search (BM25 + vector + RRF + recency) |
memory_search | BM25 keyword search |
memory_vsearch | Vector similarity search |
memory_get | Get document by path |
memory_write | Write/update document |
memory_tags | List tags with counts |
memory_status | Server and embedding status |
memory_update | Trigger re-embedding |
memory_wake_up | Workspace briefing |
memory_graph | Knowledge graph view (module → function → dep) |
memory_trace | Call chain trace from entry point |
memory_impact | Cross-file change impact analysis |
memory_symbols | Symbol search (functions, types, constants) |
memory_workspaces_resolve | Resolve filesystem path → workspace hash + registered status (read-only) |
{
"mcp": {
"nano-brain": {
"type": "remote",
"url": "http://localhost:3100/mcp"
}
}
}
Query --> BM25 (ts_rank_cd) ---+
+--> RRF Fusion (k=60) --> Recency Decay --> Results
Query --> Vector (HNSW cos) ---+
websearch_to_tsquery + ts_rank_cd on PostgreSQL tsvector# Import V1 SQLite data to PostgreSQL
nano-brain db:migrate --from-v1 /path/to/old/index.db
# Idempotent — safe to run multiple times
# Uses content-addressed SHA-256 hashing
# Pure Go SQLite reader (modernc.org/sqlite, no CGO)
CGO_ENABLED=0)MIT
FAQs
Persistent memory and code intelligence for AI coding agents
The npm package nano-brain receives a total of 6,127 weekly downloads. As such, nano-brain popularity was classified as popular.
We found that nano-brain demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.

Research
/Security News
The North Korean malware loader hides in a Packagist-listed package and its GitHub branch to fetch and execute remote code in a likely Contagious Interview-style lure.

Security News
The Rust project is moving toward formal rules on LLM use in contributions after months of internal debate over maintainer burden, code quality, and contributor experience.