Knowledge in Markdown, versioned in git. Hybrid BM25 + semantic search. 100% local and offline. Agent-native via MCP.
Zero lock-in. You keep the .md files · the index rebuilds itself · $0 per query.
Every session, your agent trips over the same gotcha, re-decides what was already decided, re-reads what was already read. Pinky gives it durable, auditable memory — without sending your code anywhere.
The .md files with frontmatter that the agent (or you) writes. Readable, versioned in git, reviewable with git diff. It’s yours and it stays with you.
↓ pinky reindex
A SQLite index (FTS5 + sqlite-vec) derived from the Markdown. If it corrupts or the model changes, it rebuilds itself. Nothing critical lives only here.
↑ 100% regenerable
Local and offline, hybrid, markdown-as-truth, and agent-native. The others have one or two.
Local ONNX embeddings, or a deterministic embedder with no network. In-process SQLite, zero daemon. Ideal for sensitive or regulated code that can’t leave the machine.
--hash-embed → no network, everBM25 finds the exact match (pg_pool_timeout); the vector finds the similar ("the pool hangs"). Fused with Reciprocal Rank Fusion.
measurable quality: hit@k + MRRThe index is cache; the .md files are the truth. Zero lock-in: you keep readable files. Audit what your agent learned with a git diff.
reindex rebuilds everythingStandard MCP server with 8 tools — exposed as a token-conscious default of 3 (brain_search, brain_save, brain_stats) and an opt-in full set (PINKY_MCP_TOOLS=*). Plus Claude Code hooks. Not an app — infrastructure.
Semantic dedup, staleness decay, code↔knowledge backlinks, pruning telemetry, and an evergreen validator. Fights entropy; not a dumping ground.
pinky dedup · stale · telemetryNo mandatory Docker, no services, no database to manage. One disposable brain.db file and three small Rust binaries.
curl | sh → running in <2 minThe agent searches before acting, saves what it discovers, and leaves a diary when done. Knowledge grows on its own as you work.
The agent (guided by a rule), the stop hook, or you. YAML frontmatter + Markdown body.
Parse → chunk → embed → SQLite. Incremental: only re-embeds what changed.
Hybrid BM25 + vector, RRF fusion, optional lexical rerank, filters by project/type/tag.
Dedup, staleness, diary rollups, pruning telemetry, quality eval.
Default (3 tools) — token-aware; the agent pays only for tools it could call.
PINKY_MCP_TOOLS=* also exposes brain_update, brain_delete, brain_feedback, brain_similar for curation, and brain_context for what the brain knows about a code file.
They inject context before read/write and write a diary when done. Time-budgeted: they never block.
The [[wikilinks]] between entries, the // Brain: breadcrumbs left in your code, and the supersedes chains stop being decoration: they are indexed, traversed when you search, and measured. No embeddings, no similarity threshold, no graph database.
An entry one explained hop from a strong hit — linked by a wikilink, named from the same code file, or the replacement of a superseded hit — can now enter the results. The old --links only re-ordered what had already matched; this changes recall.
one hop · never twoNeighbours compete for the existing result slots (at most 2), so a response never grows by a single token. And every expanded hit carries its provenance: a caller that can’t tell "matched your query" from "one hop away" would cite the second as the first.
↳ via [[slug]] (wikilink)Before a read or a write, Pinky resolves the breadcrumbs inside that file instead of turning auth/login_controller.rs into the words "auth login controller" and hoping BM25 finds something. Keyword guessing is now the fallback, not the plan.
pinky graph of --file src/auth.rsLouvain clusters your entries by edge density alone; exact Brandes betweenness finds the documents most paths run through. On a real 130-entry brain: 39 clusters labelled from the members’ own tags — plus the 31 entries connected to nothing. Deterministic: an unchanged graph rebuilds byte-identical.
pinky graph communitiesClusters and their hubs, the load-bearing entries, what is orphaned, and the links that point nowhere. The session-start hook now names the few entries the rest of the brain hangs off — different from "most used": that is what the agent reached for lately, this is what the knowledge is built around.
pinky graph report --out GRAPH_REPORT.mdPast 2 hits from the same cluster the rest of the window is demoted, never dropped — a cluster that genuinely owns the answer still wins. On the golden set the graph-aware ranking scores exactly like plain hybrid: it costs nothing where it can’t help.
PINKY_GRAPH_EXPAND=0 turns it offNone of it touches the embeddings model: the graph answers with the shared daemon asleep and in airgapped installs. The migration only adds tables — your index and its usage telemetry survive the upgrade.
It doesn’t just save and search: it understands time, learns what’s useful, and protects its own quality.
Mark what supersedes what (supersedes) and ask "what did we know on that date?" with search --as-of. The old stops confusing you, but stays auditable.
The stop hook correlates which entries the agent actually re-read and marks them useful. pinky stats --value shows you what the brain is giving you.
It understands your notes’ [[wikilinks]] and the breadcrumbs in your code — and walks them when you search. A graph’s value without dragging in a graph DB.
pinky sync versions the knowledge in git and auto-resolves diary and frontmatter conflicts. Your team shares the same memory.
The MCP server exposes 3 tools by default (brain_search, brain_save, brain_stats) and curates with brain_update, brain_delete, brain_feedback, brain_similar only when you set PINKY_MCP_TOOLS=*. The agent doesn't pay for tools it won't call.
The agent saves as soon as it learns something — and sometimes what it learned was "the deploy failed with this token". API keys, GitHub and AWS tokens, JWTs and private keys are redacted on every write path and before indexing, keeping the prefix so the note still says which credential it was. pinky redact backfills what you wrote before.
The eval harness reports hit@k, MRR, and nDCG over a golden set; CI fails the build if relevance drops. It never degrades silently.
Push injections (stats per session, hits per Read) made sense in interactive sessions. In orchestration — one claude -p per stage — they multiplied silently. Pinky ships with knobs to silence the noise without losing the brain.
PINKY_HEADLESS=1 silences push hooksReturns Ok() before opening the index in session-start, pre-read, pre-write, and post-bash. The agent still calls brain_search (pull model) — exactly what it was designed for. Saves ~7k tok/agent in a typical 15-file exploration.
PINKY_HOOK_HITS tunes hits per hookDefault 3 → 0 (clean no-op) or up to 10. Snippets shrink with PINKY_HOOK_SNIPPET (240 → as low as 40 chars). A high-Read pipeline drops from ~21k tok to ~1k tok of injected context.
The session_id already recorded in the usage table is now read back to skip re-injecting an entry_id already served. Two Reads that match the same gotcha no longer double its tokens.
brain_search excludes diary by defaultSession logs are not knowledge — they pollute BM25 spacing. Set include_diary=true or --type diary when you want them; otherwise the agent doesn't pay ~90 tok/hit for stale entries it shouldn't see.
PINKY_MCP_TOOLS tailors the toolsetDefault 3 tools (brain_search, brain_save, brain_stats) saves ~1.6k tok/turn of system-prompt schema vs the full 7. Curation tools opt-in via PINKY_MCP_TOOLS=*.
The MCP's brain_search default omits the 4-decimal score (a human metric) and the .md path (only useful in interactive TUI). The agent keeps the id (for feedback/similar) and the snippet. verbose=true restores the full line.
All of these are opt-in to keep it off: the interactive single session behaves as before. Only orchestration (headless) and agent-pull paths benefit by default.
| Pinky | Platform memory | Vector-DB SaaS | grep + notes | |
|---|---|---|---|---|
| Local / offline | Yes | No | No | Yes |
| Hybrid BM25 + vector | Yes | No | partial | No |
| Portable Markdown (no lock-in) | Yes | No | No | Yes |
| Agent-native (MCP) | Yes | partial | No | No |
| Zero-ops (one binary) | Yes | Yes | No | Yes |
| Cost per query | $0 | included | 💲 | $0 |
Pinky is the only one combining local + offline, hybrid, markdown-as-truth, and agent-native at the same time.
Context tokens pulled in per knowledge query, same scenario, measured on a real 16-doc corpus (~59 KB).
Measured with the pinky binary: brain_search --json payload vs. grep + read the files vs. re-reading the code (tokens ≈ chars/4). It’s the retrieval payload; on larger corpora the gap widens.
One Rust binary, no runtime, no daemon. Everything below is measured and reproducible with pinky bench and pinky eval on your machine.
| Entries | Indexing | DB size | Search p50 | Search p95 |
|---|---|---|---|---|
| 1.000 | 0,4 s | 10 MB | 8,1 ms | 8,7 ms |
| 10.000 | 4,8 s | 104 MB | 49,4 ms | 52,7 ms |
| 100.000 | 56,6 s | 1,03 GB | 470,9 ms | 494,6 ms |
The real case of a personal or team brain (1k–10k entries) has plenty of headroom: p95 < 55 ms end to end. At 100k the brute-force KNN is around ½ s — usable, with binary quantization on the roadmap (justified ≥ 50k). Latency and quality measured with the deterministic embedder (pure engine); the ONNX semantic model is optional —downloaded once— or run with --hash-embed and no model. And it is loaded once per machine, not once per chat: since v0.3.0 the model lives in a shared daemon that exits when idle, so three open chats went from 3,7 GB to 1,23 GB of RSS — and cost nothing while nobody searches. MacBook Apple Silicon, release build.
Gotchas are injected before it writes code. Fewer re-committed mistakes — not just fewer tokens.
Knowledge persists and accumulates; a new dev or agent starts out knowing what the team already learned.
100% local and offline: it unlocks sensitive or regulated projects a SaaS couldn’t touch. $0 per query.
Markdown versioned in git: review it with a git diff in a PR. Zero lock-in — you keep the files.
Dedup, staleness decay, and pruning telemetry; the CI eval fails the build if relevance drops.
One binary, no daemon; pinky init in one command; the hooks are time-budgeted and never block your agent.
Signed, reproducible, auditable, and tested offline. What a regulated team reviews before adopting a tool.
Opt-in feature with SQLCipher (AES-256, page-level): the brain.db is encrypted. The key travels via the environment; opening with the wrong one fails cleanly, never corrupts.
An agent with write access can destroy months of knowledge. snapshot makes a tar.gz + SHA-256 manifest; restore verifies every checksum before writing a byte.
Binaries signed with minisign + mandatory SHA-256 checksum. Bit-for-bit reproducible builds (pinned toolchain) and a CycloneDX SBOM per release.
minisign · SBOM · reproduciblepinky doctor --airgap fails if anything would need the network. And a CI job runs index + search inside an isolated network namespace: the claim is proven on every push.
The .md files are the stable interface; the index is disposable. An old binary over a newer index fails clearly instead of operating silently.
cargo-deny in CI (RUSTSEC advisories + licenses + sources), GitHub Actions pinned by commit hash, and publish = false so nothing leaks to crates.io.
Airgapped or on-prem: embeddings run locally and nothing leaves the machine. The agent’s memory complies without exfiltrating code.
The agent inherits accumulated gotchas, decisions, and patterns. Instant onboarding: a new dev (or agent) starts out knowing what the team already learned.
The stop hook leaves a diary entry per session; rollups build the weekly/monthly summary with no LLM.
The multilingual-e5-small model covers ES and IT: search in one language, find what was written in another.
Linux x86_64 and macOS Apple Silicon have prebuilt binaries. Other platforms: build from source.
# 1 · set up the project: creates documentation/ and registers the MCP pinky init # 2 · index the knowledge (hybrid search, multilingual model) pinky reindex documentation # 3 · search — or let the agent use the brain_search tool pinky search "timeout closing the postgres pool" # 4 · reopen the project in Claude Code → the 'pinky' MCP is available
Already have it? Update with pinky update (verified download from the CDN).
All installation options (manual download, Docker, source) →
For retrieval, the hybrid BM25 + vector closes the gap: BM25 nails exact terms and the vector handles semantics. And quality is measurable — the eval harness reports hit@k and MRR, and CI fails the build on a relevance regression.
The index is disposable: pinky reindex rebuilds it entirely from the .md files. Plus there are schema- and embedding-model version guards: if something doesn’t line up, it warns and regenerates — it never corrupts silently.
The core is agnostic and MCP is an open standard: it works with any MCP client, and the CLI works on its own. The hooks, though, are Claude Code-specific today.
The ONNX model (~450 MB, optional) downloads once, then everything runs offline. If you want zero-network and zero-model from minute one, use --hash-embed: a deterministic embedder that never touches the network and runs in ~13 MB of RAM (a bit less precise, ideal for airgapped/CI).
Measured and reproducible (pinky bench): at 10,000 entries the full hybrid search is ~50 ms (p95); at 1,000, ~9 ms. The bottleneck isn’t volume: it’s organization and retrieval, which is exactly what Pinky solves.
curl | sh installs the binaries; pinky init leaves the project ready with the MCP registered using relative (relocatable) paths. No baked-in absolute paths, no touching code.