Engram
Gives coding agents a persistent, searchable project memory stored locally in SQLite
Local memory store an assistant writes corrections and conventions to and recalls across tools
By plur-ai TypeScript Local · stdio Knowledge and memory
56 popularity score ★ 313 ↓ 1.4k/wk
Opens the app, which asks before it adds the server.
claude mcp add plur -- npx -y @plur-ai/mcp{
"mcpServers": {
"plur": {
"command": "npx",
"args": [
"-y",
"@plur-ai/mcp"
]
}
}
}{
"mcpServers": {
"plur": {
"command": "npx",
"args": [
"-y",
"@plur-ai/mcp"
]
}
}
}{
"servers": {
"plur": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@plur-ai/mcp"
]
}
}
}[mcp_servers.plur]
command = "npx"
args = ["-y", "@plur-ai/mcp"]gemini mcp add --scope user plur npx -- -y @plur-ai/mcpPLUR_PATH |
Optional: Folder for the engram store. |
|---|---|
PLUR_TOOL_PROFILE |
Optional: full exposes every tool directly; lean or cursor exposes 14 core tools plus plur_admin. |
PLUR_TELEMETRY |
Optional: on enables the content-free usage counters, off disables them; a saved preference applies when unset. |
| Set together: search | |
PLUR_DISABLE_EMBEDDINGS |
Optional: Set to 1, true or yes to skip the embedding model and search by keyword only. |
PLUR_EMBEDDER |
Optional: Embedding model: minilm, bge-small, bge-base, embedding-gemma or openai-3-large (the last needs OPENAI_API_KEY). |
PLUR_MODEL_DOWNLOAD |
Optional: Set to off to stop the embedding model being fetched; a model not already on disk is then not loaded. |
PLUR_RERANKER |
Optional: Set to bge-reranker-v2-m3 to opt in to a local cross-encoder reranker for recall. |
| Set together: llm | |
OPENROUTER_API_KEY secret |
Optional: Enables the LLM-based tools through OpenRouter with gpt-4o-mini; used before OPENAI_API_KEY when both are set. |
OPENAI_API_KEY secret |
Optional: Enables the LLM-based tools through OpenAI with gpt-4o-mini, and the openai-3-large embedder. |
PLUR keeps what an assistant learns while working (corrections, preferences, project conventions, decisions) as small typed records it calls engrams. They are stored as plain YAML in ~/.plur/, or in the folder named by PLUR_PATH. The MCP server, published as @plur-ai/mcp, gives the assistant tools to save, search, rate, retire and re-scope those records and to log timestamped events. It can also push the store to a git remote so the same memory follows you to another machine or a team.
Search runs on your machine, mixing keyword ranking with a small local embedding model, and engrams can carry a scope such as project:my-app so one project's notes stay out of another's.
In v0.22.1 there are 45 tools. By default the server runs a lean profile with 14 of them exposed plus plur_admin, a dispatcher through which the other 30 are called by name. PLUR_TOOL_PROFILE=full exposes the 44 directly. The README's own tool table is shorter. A comment in tools.ts explains why the core set holds tools that delete or rewrite memory, such as plur_tensions and plur_report_failure: the dispatcher is never allowed to delete or overwrite.
New in this line is the folder map at ~/.plur/folders.yaml, edited with plur folders set from a terminal. A folder can be on, off, ask or remote-only, and can carry a default scope. In an off folder the 33 tools that touch engrams return a plain answer without reading or writing any store. In a folder with no decision yet they return a question with ready-made plur folders set commands for the user to choose from. The server never writes the map itself (packages/mcp README).
| Runtime | Node.js 22+ |
|---|---|
| Runs on | macOS, Windows, Linux |
| Also |
|
Node.js 22 or newer, per the package's engines field and its README. The repository's main README still says 20. The makers' setup also installs @plur-ai/cli globally and runs plur init, which writes client configuration and session hooks. The server starts without it, but the folder map is changed with the plur folders commands from that CLI. The embedding model is downloaded once (plur doctor does this). Without it search is keyword-only. An OpenRouter or OpenAI API key is needed only for the LLM-based tools.
It stores and recalls engrams only; its README says it does not index or search source code or files. Unless PLUR_TOOL_PROFILE=full is set, most tools are reachable only through plur_admin (tools.ts). In a folder the folder map turns off, or when the client's workspace roots cannot be fetched, memory tools do nothing. Clients without a PLUR adapter (Windsurf, Gemini CLI and other generic MCP clients) get the tools but no automatic injection, so memory is used only when the model chooses to call them. A personal sync pushes every engram, private ones included, so the README warns to use a private repository. plur_recall_hybrid is deprecated. The Python SDK is not yet on PyPI.
Suits a developer who switches between Claude Code, Cursor, Codex or OpenCode and wants one memory of corrections and conventions that stays on their own disk in files they can read, diff and edit, with optional git sharing for a team. Its adapters for those clients load memory automatically; in other clients it relies on the model to call the tools. It is not a code-search or documentation tool, and not a hosted memory API: its README points readers who need a hosted service or a temporal knowledge graph to other products, and to code-intelligence tools for searching source.
19 only read, 20 change things, 6 can delete or overwrite. A ? marks an optional parameter.
plur_admin changesaction: stringargs?: objectplur_session_start changestask: stringtags?: arraydefault_scope?: stringplur_session_end changessummary: stringsession_id?: stringengram_suggestions: arrayplur_learn changesstatement: stringtype?: enumscope?: stringdomain?: stringtags?: arrayrationale?: stringsource?: stringpinned?: booleancommitment?: enumlocked_reason?: stringvalid_from?: stringvalid_until?: stringsupersedes?: arraysession_id?: stringmeasured_under?: objectattribution?: objectclaim_class?: enumlicense?: stringvisibility?: enumplur_learn_batch changesengrams: arraymax_llm_calls?: numbersession_id?: stringplur_recallquery: stringmode?: enumscope?: stringdomain?: stringlimit?: numberbudget?: objectcaller_session_id?: stringinclude_episodes?: booleansession_id?: stringplur_recall_hybridquery: stringscope?: stringdomain?: stringlimit?: numberbudget?: objectcaller_session_id?: stringinclude_episodes?: booleansession_id?: stringplur_injecttask: stringbudget?: numberscope?: stringsession_id?: stringplur_inject_hybridtask: stringbudget?: numberscope?: stringsession_id?: stringplur_feedback changesid?: stringsignal?: enumscope?: stringsignals?: arrayplur_pin changesid?: stringpinned?: booleanlist?: booleanscope?: stringplur_forget deletesid?: stringsearch?: stringreason?: stringscope?: stringplur_capture changessummary: stringagent?: stringchannel?: stringsession_id?: stringtags?: arrayplur_timelinesince?: stringuntil?: stringagent?: stringchannel?: stringsearch?: stringplur_ingest changescontent: stringsource?: stringextract_only?: booleanscope?: stringdomain?: stringplur_episode_to_engram changesepisode_id: stringscope?: stringdomain?: stringtags?: arrayplur_packs_previewsource: stringplur_packs_install changessource: stringplur_packs_uninstall deletesname: stringplur_packs_listplur_packs_discoverquery?: stringtags?: arraycategory?: stringplur_packs_export changesname: stringdescription?: stringfilter_domain?: stringfilter_scope?: stringfilter_tags?: arrayfilter_type?: enumoutput_dir?: stringcreator?: stringlicense?: stringplur_sync changesremote?: stringfull?: booleanremote_type?: enumplur_sync_statusplur_outbox changesflush?: booleanplur_extract_meta changesllm_base_url: stringllm_api_key: stringllm_model?: stringdomain?: stringscope?: stringrun_validation?: booleandry_run?: booleanplur_meta_engramsdomain?: stringmin_confidence?: numberhierarchy_level?: enumlimit?: numberplur_validate_meta deletesmeta_engram_id: stringtest_domain: stringllm_base_url: stringllm_api_key: stringllm_model?: stringplur_statusdomain?: stringcreated_after?: stringcheck_updates?: booleanplur_provenanceid?: stringsearch?: stringformat?: enumplur_receiptdays?: numberplur_doctorretry?: booleanrerank_eval?: booleanplur_session_scope changesop: enumscope?: stringreason?: stringsession_id?: stringplur_stores_add changespath?: stringurl?: stringtoken?: stringscope: stringshared?: booleanreadonly?: booleanplur_stores_listplur_suggest_scopestatement: stringdomain?: stringtags?: arraymin_confidence?: numberplur_scopes_discover changesurl?: stringregister?: booleanplur_promote changesid?: stringids?: arrayplur_rescope changesid?: stringids?: arraytarget_scope: stringkeep_local?: booleandry_run?: booleanplur_tensions deletesscope?: stringdomain?: stringscan?: booleanpersist?: booleanaction?: enumid?: stringwinner?: stringstatus?: enumllm_base_url?: stringllm_api_key?: stringllm_model?: stringmin_confidence?: numbermax_pairs?: numberbatch_size?: numbertemporal_discount?: booleanplur_tensions_purge deletesplur_historyengram_id?: stringlimit?: numberplur_report_failure deletesengram_id: stringfailure_context: stringllm_base_url?: stringllm_api_key?: stringllm_model?: stringplur_similarity_searchquery: stringlimit?: numberscope?: stringplur_profilescope?: stringllm_base_url?: stringllm_api_key?: stringllm_model?: stringforce_regenerate?: boolean