@@ -172,6 +172,44 @@ def observation_to_block(
172172
173173_MM_MARKER = "# mind-mem"
174174
175+ # Canonical Memory Protocol snippet — written into every detected CLI's
176+ # system-prompt file by ``mm install-all``. The companion document is
177+ # ``docs/agent-memory-protocol.md``; both must be kept in sync.
178+ #
179+ # Wiring at the protocol level (MCP entries) is necessary but not
180+ # sufficient — without an explicit instruction the LLM in each CLI does
181+ # not reliably call the MCP tools. This snippet is the instruction half.
182+ MEMORY_PROTOCOL_SNIPPET = (
183+ f"{ _MM_MARKER } : agent instructions (auto-written by `mm install-all`)\n "
184+ "\n "
185+ "## Memory Protocol (mind-mem MCP — USE CONSTANTLY)\n "
186+ "\n "
187+ "The mind-mem MCP server is wired into this CLI. Before answering ANY\n "
188+ "question that touches prior work, decisions, project state, people,\n "
189+ "companies, technical choices, or \" remember when…\" — call mind-mem\n "
190+ "first. The governed blocks in mind-mem's Postgres backend are the\n "
191+ "source of truth.\n "
192+ "\n "
193+ "### Always recall before answering\n "
194+ "Run `mcp__mind-mem__recall` (or `mm recall \" $query\" ` via bash) with\n "
195+ "relevant keywords FIRST. If recall returns results, cite them. If\n "
196+ "not, say \" no record found\" — do not guess.\n "
197+ "\n "
198+ "### Always propose_update after learning new facts\n "
199+ "When the user shares a new decision, project status, relationship,\n "
200+ "contact, or technical finding worth preserving — run\n "
201+ "`mcp__mind-mem__propose_update` to store it. Don't wait to be asked.\n "
202+ "\n "
203+ "### Use hybrid_search for complex queries\n "
204+ "For multi-faceted questions, use `mcp__mind-mem__hybrid_search`\n "
205+ "(BM25 + vector + RRF fusion) for best recall.\n "
206+ "\n "
207+ "### Hallucination guardrail\n "
208+ "If you find yourself writing about prior projects, repos, or\n "
209+ "decisions without having called recall in this session, you are\n "
210+ "about to hallucinate. Stop and call recall first.\n "
211+ )
212+
175213
176214# ---------------------------------------------------------------------------
177215# MCP server command — every client that supports MCP points at this.
@@ -605,9 +643,7 @@ def _merge_mcp_vibe_toml(existing_text: str, ws: str, srv: dict) -> tuple[str, b
605643 description = "OpenAI Codex CLI" ,
606644 config_fmt = "text-block" ,
607645 path_tmpl = "{ws}/AGENTS.md" ,
608- content_tmpl = (
609- f'{ _MM_MARKER } : agent instructions (auto-written)\n \n Before every response, run `mm context "$QUERY"` and prepend the output.\n '
610- ),
646+ content_tmpl = MEMORY_PROTOCOL_SNIPPET ,
611647 detect_binaries = ("codex" ,),
612648 mcp_fmt = "mcp-toml-codex" ,
613649 mcp_path_tmpl = "{home}/.codex/config.toml" ,
@@ -617,9 +653,7 @@ def _merge_mcp_vibe_toml(existing_text: str, ws: str, srv: dict) -> tuple[str, b
617653 description = "Mistral Vibe CLI" ,
618654 config_fmt = "text-block" ,
619655 path_tmpl = "{ws}/AGENTS.md" ,
620- content_tmpl = (
621- f'{ _MM_MARKER } : agent instructions (auto-written)\n \n Before every response, run `mm context "$QUERY"` and prepend the output.\n '
622- ),
656+ content_tmpl = MEMORY_PROTOCOL_SNIPPET ,
623657 detect_paths = ("{home}/.vibe" ,),
624658 detect_binaries = ("vibe" ,),
625659 mcp_fmt = "mcp-toml-vibe" ,
@@ -640,7 +674,7 @@ def _merge_mcp_vibe_toml(existing_text: str, ws: str, srv: dict) -> tuple[str, b
640674 description = "Cursor editor" ,
641675 config_fmt = "text-block" ,
642676 path_tmpl = "{ws}/.cursorrules" ,
643- content_tmpl = ( f" { _MM_MARKER } \n mind-mem workspace: {{ws}} \n Use `mm inject --agent cursor` before answering. \n " ) ,
677+ content_tmpl = MEMORY_PROTOCOL_SNIPPET ,
644678 detect_paths = (
645679 "{home}/.cursor" ,
646680 "{home}/Library/Application Support/Cursor" ,
@@ -655,7 +689,7 @@ def _merge_mcp_vibe_toml(existing_text: str, ws: str, srv: dict) -> tuple[str, b
655689 description = "Windsurf editor (Codeium)" ,
656690 config_fmt = "text-block" ,
657691 path_tmpl = "{ws}/.windsurfrules" ,
658- content_tmpl = ( f" { _MM_MARKER } \n workspace: {{ws}} \n prefer `mm inject --agent windsurf`. \n " ) ,
692+ content_tmpl = MEMORY_PROTOCOL_SNIPPET ,
659693 detect_paths = (
660694 "{home}/.codeium/windsurf" ,
661695 "{home}/.windsurf" ,
@@ -711,7 +745,7 @@ def _merge_mcp_vibe_toml(existing_text: str, ws: str, srv: dict) -> tuple[str, b
711745 description = "Cline (VS Code extension)" ,
712746 config_fmt = "text-block" ,
713747 path_tmpl = "{ws}/.clinerules" ,
714- content_tmpl = ( f" { _MM_MARKER } \n mind-mem workspace: {{ws}} \n Run `mm inject --agent cline` before tool use. \n " ) ,
748+ content_tmpl = MEMORY_PROTOCOL_SNIPPET ,
715749 detect_paths = (
716750 "{home}/.vscode/extensions" ,
717751 "{home}/.vscode-server/extensions" ,
@@ -724,7 +758,7 @@ def _merge_mcp_vibe_toml(existing_text: str, ws: str, srv: dict) -> tuple[str, b
724758 description = "Roo Code (VS Code fork / extension)" ,
725759 config_fmt = "text-block" ,
726760 path_tmpl = "{ws}/.roo/system-prompt.md" ,
727- content_tmpl = ( f" { _MM_MARKER } \n mind-mem workspace: {{ws}} \n Use `mm inject --agent roo` before answering. \n " ) ,
761+ content_tmpl = MEMORY_PROTOCOL_SNIPPET ,
728762 detect_paths = (
729763 "{home}/.roo" ,
730764 "{home}/.vscode/extensions" ,
0 commit comments