RMS Memory MCP
<div align="center">
# π§ RMS Memory MCP
**Latest release:** see [GitHub Releases](https://github.com/max-ramas/rms-memory-mcp/releases) Β· `rms-memory update` installs it Β· the optional companion GUI is released separately
**Persistent, local-first memory for your AI coding agents.**
Stop re-explaining your architecture to Cursor, Zed, and Claude Code and other IDEs every single session.
[](https://opensource.org/licenses/MIT)
[](https://www.rust-lang.org/)
[](https://crates.io/crates/rms-memory-mcp)
[](https://github.com/max-ramas/rms-memory-mcp/releases)


[]()
[](https://modelcontextprotocol.io)
[Features](#-key-features) β’ [Download](#-download) β’ [Install](#-installation) β’ [Quick Start](#-quick-start) β’ [CLI](#-cli-commands) β’ [MCP Tools](#-mcp-tools-exposed) β’ [Architecture](#-architecture-highlights)
</div>
---
> ### π Privacy promise
> RMS does **not** collect your data or usage statistics. RMS Memory MCP has no accounts, license
> checks or analytics, and your notes, code, queries and settings stay on your machine (local-first).
> The only requests that reach RMS carry no content and no personal identifier:
> - **Update check:** `rms-memory doctor` (and the `rms_doctor` tool) asks `update.rms-ds.com` for the
> newest version, at most once a day: your OS, CPU architecture and the version, no ID. If that
> server is unreachable it falls back to GitHub\*. Turn it off with `RMS_MEMORY_NO_UPDATE_CHECK=1`.
> - **Downloads you ask for:** `rms-memory update`, `rms-memory gui` and the install scripts fetch
> signed files from `update.rms-ds.com`, which counts downloads per release and source; its
> analytics store no IP addresses or user agents.
> - **Embedding model:** on first use it is downloaded once from Hugging Face\*.
>
> Embeddings are computed on your machine (the bundled model, or a local Ollama), so your notes never
> leave your computer for any AI service.
>
> If an online service is ever introduced, we will tell you clearly beforehand.
---
<div align="center">
<a href="https://ko-fi.com/M7I020HKXX" target="_blank" rel="noopener noreferrer">
<img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="ko-fi">
</a>
</div>
---
## The Problem
You're developing a single project but switching between different agents β Cursor, Zed, Claude Code, OpenCode, etc. Every one of them loses context of architectural decisions, system requirements, and user preferences the moment you close the tab. You end up re-explaining the same things over and over, or copy-pasting a stale `CLAUDE.md` between tools.
**RMS Memory MCP** bridges this gap: a single, isolated, centralized Markdown vault β perfectly structured for LLM consumption β that any MCP-compatible IDE can read from and write to.
### π₯οΈ Prefer a GUI over raw Markdown?
**[RMS Memory GUI](./GUI-README.md)** turns your vault into a visual workspace β full graph editor, per-project Git & GitHub sync, one-click Doctor repair, and an AI-assisted Wiki generator (bring your own key). One-time desktop app, works on top of everything below. The MCP server stays 100% free and standalone either way.
## β¨ Key Features
| | |
|---|---|
| ποΈ **Global Centralized Vaults** | Project context lives outside your repo β zero `.mcp` file pollution. |
| π **Hybrid Retrieval (LanceDB)** | Embedded Vector Search + Tantivy Full-Text Search for zero-fail context hits. |
| π **Multilingual Semantic Parsing** | `fastembed-rs` + `multilingual-e5-small` by default β native Russian & English understanding. Since 1.3.0 `rms-memory embedding use` switches to another bundled model or a local Ollama model (each keeps its own index), and `rms-memory embedding eval` measures hit@k / MRR on your own vault. |
| π³ **AST Markdown Chunker** | `pulldown-cmark`-based chunking keeps code blocks and lists bound to their parent heading. |
| π§© **Semantic Code Memory** | Optional Tree-sitter indexing for Rust, Go, JS/JSX, TS/TSX, Python, C/C++, Java, Ruby, Swift, C#, PHP, Kotlin, SQL, HTML, CSS, and Vue `<script>` blocks; stable segment identities and repeated preambles preserve context when large implementations split. Opt-in `watch` mode reindexes **only dirty paths** (with full-walk fallback). |
| πΈοΈ **Knowledge Graph (v1.2.0)** | Durable Markdown/code relationships via MCP `rms_graph` (neighbors, path, snapshot, mutations) and optional search `include_graph_neighbors`. Companion GUI still owns the visual GraphView. |
| π§Ή **Safe Project Lifecycle** | Unregistering preserves vault/index data; permanent GUI deletion requires the exact project key, is confined to the master vault, and never touches source code. |
| π **Federated Corpus Search** | Search `vault`, `code`, or `all`; mixed results use Reciprocal Rank Fusion rather than incompatible raw vector distances. |
| π― **Bounded Recall (v1.0.7)** | `rms_search` returns an inject/abstain envelope with `max_chars`, optional `min_score`, fail-closed errors, and `retrieval_mode` (`hybrid` or short-query `fts_prefer`). |
| β»οΈ **Knowledge Lifecycle** | Frontmatter `status` / `supersedes` / temporal `valid_*` gate Lance recall; soft supersede via `rms_write`; Doctor freshness lint (check 7 of 8); `rms-memory prune` archives aged superseded notes (dry-run default). |
| π **Obsidian vaults (v1.3.0)** | `rms-memory projects attach-obsidian <PATH>` indexes an existing Obsidian vault in place, strictly read-only (RMS Memory never creates, edits or deletes files in it); `rms-memory import --obsidian <DIR>` copies one into a project vault instead. `[[wikilinks]]`, aliases, headings and embeds resolve the way Obsidian does in the graph, index and doctor. |
| π **Local HTTP transport (v1.3.0)** | `rms-memory serve --http` serves MCP Streamable HTTP on `127.0.0.1:7337/mcp` with a bearer token from `~/.rms-memory/http-token`, loopback Host/Origin checks and per-session state β for clients that cannot spawn a stdio process. See [SECURITY.md](SECURITY.md#local-http-transport). |
| π **Credential refusal (v1.3.0)** | `rms_write` and checkpoint tools refuse text containing well-known token formats (AWS `AKIAβ¦`, GitHub `ghp_β¦`/`github_pat_β¦`, OpenAI/Anthropic `sk-β¦`, Slack, Stripe live, Google, npm, GitLab) or a PEM private key, naming the kind and line but never the value. Doctor check 8 reports such notes already in the vault (report only). Not a guarantee β see [SECURITY.md](SECURITY.md#credential-refusal-limits). |
| β¬οΈ **Updates (v1.4)** | `rms-memory update` installs the newest release from the RMS update server: the signed manifest, size and sha256 are verified, the new binary is smoke-tested, swapped in atomically and the previous one is kept for `rms-memory update --rollback`. Binaries installed by brew, cargo or a package are left to that tool (`--force` overrides). `doctor` also checks for a newer version at most once a day (update server first, GitHub as fallback; `RMS_MEMORY_NO_UPDATE_CHECK=1` disables it) and warns when the running server binary was replaced on disk; MCP `initialize` repeats the cached notice without network access. |
| π **Session Continuity (v1.0.7)** | Vault-backed checkpoints (`rms_checkpoint_save/done/load/query`), `rms_overview` project orientation (since 1.3.0 with index lag and git branch / changed files), MCP resources `rms://<project>/β¦` and prompts (`session_start`, `save_progress`, `record_decision`), `rms_hygiene` consolidation report, `rms_system_instructions` self-bootstrap, editor-agnostic `rms-memory hook` CLI, installer L3 thin adapters, and `pinned` notes that bypass temporal/`min_confidence` recall gates. |
| π§ **Multi-project MCP routing (v1.0.8+)** | Explicit `project` always rebinds the active vault; empty Cursor `roots/list` falls back to process cwd; injected rules require `project: "<key>"` on every memory tool call; `rms-memory inject-rules [--all]` refreshes keys. |
| π **Cross-project federated search (v1.0.9)** | Pass `projects: [key, β¦]` to `rms_search` / `rms_code_search` for read-only RRF federation. Vault/all across multiple projects requires `cross_project_vault=true` on every listed key (hard fail otherwise). |
| π§ **Concurrent bind cache (v1.0.9)** | Up to 4 warm Store+watcher pairs (LRU); multi-root IDE sessions stop thrashing open/close. |
| π§± **Cargo workspace (v1.0.9+)** | `rms-memory-{core,index,vault,cli}` path crates under `crates/`; public umbrella `rms-memory-mcp` keeps stable module paths for the GUI. `cli` hosts cycle-free `gc`/`prune` (1.1.1). See [docs/crate-split.md](./docs/crate-split.md). |
| π¦ **Unified Releases** | Public assets use `rms_memory_mcp_<version>_<target>.*` / `rms_memory_gui_<version>_*` on the **same** `vX.Y.Z` tag (MCP + GUI share numbering). Unversioned names are no longer published. |
| πͺΆ **Small idle footprint (v1.3.0)** | Each `serve` process loads the embedding model only when it needs to embed and releases it after 5 idle minutes (`RMS_MEMORY_MODEL_IDLE_SECS`), so many IDEs with an idle server cost about 50 MB each instead of a model copy each. Since 1.4.2 on Linux the freed memory is also handed back to the system (an idle process drops to about 100 MB instead of staying near 700 MB). |
| βοΈ **Dynamic Auto-Installer** | `rms-memory install` scans your system and wires itself into every supported IDE. |
| π **Rules-as-Code Patching** | Non-destructive AST patching of `.cursorrules`, `.zed/assistant.md`, etc. Opt-in by default. |
| π§ͺ **Durable Vault Writes** | `rms_write` creates rolling `.bak` backups and atomically replaces `create`/`replace` targets after fsync, so interrupted writes never expose a truncated Markdown file. Optional `dry_run` previews create/update/noop without touching disk or the index (fingerprint ignores volatile audit stamps). |
| π **File git history (v1.1.2)** | Derived `code_path` fileβcommit cache (`rms_file_history` / `rms-memory file-history`); agents should not shell `git log`. Optional search `include_file_history` attaches the last 3 commits per **code** hit (not with federated `projects`). |
| π **Canonical Wiki Isolation** | Generated `<vault>/wiki/**` stay Git-synchronized but are excluded from indexes/search/watchers/graph/packs; MCP write and canonical DocumentService also reject wiki paths (wiki-safe writers only). |
| π‘οΈ **Ten-Point Resiliency** | GC, background sync, write-guard snapshots, macOS sandbox bypass, `llms.txt` export, path traversal + injection protection, zombie prevention, graceful shutdown. |
| π **Security Hardened** | Panic-free database layer, symlink traversal blocked, JSON-RPC error responses, request size limits. See [SECURITY.md](./SECURITY.md) and [NOTICE](./NOTICE). |
| π§ **Audit Metadata** | Every record auto-receives `last_modified_by`, `timestamp`, `confidence`, `source` β agents can filter by reliability. |
| π **Multi-Scope** | `--scope` flag supports arbitrary identifiers beyond filesystem paths (thread IDs, lead IDs, etc.). |
| π₯οΈ **Optional Companion GUI** | Paid Tauri desktop app: visual Markdown/graph editor, Git & Vault sync, Doctor dashboard, AI-assisted organizer/Wiki (BYOK), and cross-tool spend tracking β layered on top of the same vault, never required. See [GUI-README.md](./GUI-README.md). Install and open it from the terminal with `rms-memory gui`. |
## π₯ Download
<div align="center">
**RMS Memory MCP** (command-line server, free)
[](https://update.rms-ds.com/get/rms-memory-mcp/pkg?platform=darwin&arch=arm64&src=readme)
[](https://update.rms-ds.com/get/rms-memory-mcp/msi?platform=windows&arch=amd64&src=readme)
[](https://update.rms-ds.com/get/rms-memory-mcp/deb?platform=linux&arch=amd64&src=readme)
[](https://update.rms-ds.com/get/rms-memory-mcp/deb?platform=linux&arch=arm64&src=readme)
Also as: [macOS .tar.gz](https://update.rms-ds.com/get/rms-memory-mcp/tar.gz?platform=darwin&arch=arm64&src=readme) Β· [Windows .zip](https://update.rms-ds.com/get/rms-memory-mcp/zip?platform=windows&arch=amd64&src=readme) Β· Linux x64 [.tar.gz](https://update.rms-ds.com/get/rms-memory-mcp/tar.gz?platform=linux&arch=amd64&src=readme) / [.rpm](https://update.rms-ds.com/get/rms-memory-mcp/rpm?platform=linux&arch=amd64&src=readme) Β· Linux ARM64 [.tar.gz](https://update.rms-ds.com/get/rms-memory-mcp/tar.gz?platform=linux&arch=arm64&src=readme) / [.rpm](https://update.rms-ds.com/get/rms-memory-mcp/rpm?platform=linux&arch=arm64&src=readme)
The installers put `rms-memory` on your `PATH` (`/usr/local/bin` on macOS, `Program Files\RMS Memory MCP` on Windows). Always the newest stable release. The macOS installer and binary are signed with an Apple Developer ID and notarized, so macOS opens them without a warning. The Windows installer is not code-signed yet, so SmartScreen may warn before the `.msi` runs.
</div>
**Prefer a one-line installer?** It picks the right build, verifies the signature and puts the binary on your `PATH`:
```bash
curl -fsSL https://raw.githubusercontent.com/max-ramas/rms-memory-mcp/master/scripts/install.sh | bash
```
```powershell
irm https://raw.githubusercontent.com/max-ramas/rms-memory-mcp/master/scripts/install.ps1 | iex
```
With an archive: unpack, put `rms-memory` (`rms-memory.exe` on Windows) on your `PATH` and run `rms-memory install` to register it in your IDEs. Already installed? `rms-memory update` fetches the release from the same server, verifies its signature and checksum, and keeps the previous binary for `rms-memory update --rollback`. The signed manifest of the latest release is at [`/v1/rms-memory-mcp/latest`](https://update.rms-ds.com/v1/rms-memory-mcp/latest). Downloads through this server are counted per release; no IP addresses or user agents are stored.
<div align="center">
**RMS Memory GUI** (optional desktop app, trial included)
[](https://update.rms-ds.com/get/rms-memory-gui/dmg?platform=darwin&arch=arm64&src=readme)
[](https://update.rms-ds.com/get/rms-memory-gui/exe?platform=windows&arch=amd64&src=readme)
[](https://update.rms-ds.com/get/rms-memory-gui/msi?platform=windows&arch=amd64&src=readme)
[](https://update.rms-ds.com/get/rms-memory-gui/appimage?platform=linux&arch=amd64&src=readme)
[](https://update.rms-ds.com/get/rms-memory-gui/deb?platform=linux&arch=amd64&src=readme)
[](https://update.rms-ds.com/get/rms-memory-gui/rpm?platform=linux&arch=amd64&src=readme)
The MCP server never needs the GUI. From a terminal, `rms-memory gui` installs it for your OS (signature and checksum verified) and opens it.
</div>
Homebrew, `.deb`/`.rpm` packages of the MCP and older versions: [GitHub Releases](https://github.com/max-ramas/rms-memory-mcp/releases).
## π¦ Installation
### Option 1: Homebrew (macOS Apple Silicon & Linux)
```bash
brew tap max-ramas/tap
brew install rms-memory-mcp
```
Installs a prebuilt binary β no Rust toolchain required. The formula updates
automatically with every release.
> **Not covered by Homebrew:** macOS Intel (dropped as of v1.0.1) and
> Windows (Homebrew doesn't run there β use Option 2 or the `.zip` below).
### Option 2: GitHub release binary
Prebuilt binaries for `aarch64-apple-darwin` (Apple Silicon), `x86_64-unknown-linux-gnu`,
`aarch64-unknown-linux-gnu`, and `x86_64-pc-windows-msvc` are published on every
[release](https://github.com/max-ramas/rms-memory-mcp/releases), along with
`.deb`/`.rpm` packages for Linux. One-line installers auto-detect your architecture:
```bash
curl -fsSL https://raw.githubusercontent.com/max-ramas/rms-memory-mcp/master/scripts/install.sh | bash
```
```powershell
irm https://raw.githubusercontent.com/max-ramas/rms-memory-mcp/master/scripts/install.ps1 | iex
```
### Option 3: Build from Source
```bash
# 1. Clone the repository
git clone https://github.com/max-ramas/rms-memory-mcp.git
cd rms-memory-mcp
# 2. Build the optimized release binary
cargo build --release
# 3. Add the binary to your global PATH
cp target/release/rms-memory ~/.cargo/bin/
```
### crates.io (`cargo install`)
As of **1.1.0+**, tag push publishes **only** the umbrella crate `rms-memory-mcp`
to crates.io. Internal workspace members (`rms-memory-core` / `index` / `vault` /
`cli`) stay `publish = false` (path deps for local builds and the companion GUI).
Release packaging flattens those crates into a staging tree via
`scripts/flatten-for-crates-io.py` before `cargo publish` (as of **1.1.1** the
staging tree also inlines `rms-memory-cli`) β see
[docs/crate-split.md](./docs/crate-split.md).
```bash
cargo install rms-memory-mcp
# Prefer Homebrew or a GitHub release binary if you want a pinned installer.
```
### Optional RMS Memory GUI installers
The companion **RMS Memory GUI** is a paid, optional Tauri desktop control plane:
a visual Markdown/graph editor, per-project and Vault-wide Git/GitHub sync, a
Doctor dashboard with one-click repair, an AI-assisted organizer and Wiki
generator (bring your own key, proposal-only), and cross-tool spend tracking.
The MCP server remains fully standalone: it does not require the GUI, an AI provider,
or a GUI license to index, search, sync or serve MCP clients.
See [GUI-README.md](./GUI-README.md) for the full feature breakdown, supported
platforms, installer verification and release-distribution policy.
GUI source is private, but desktop installers are published as binary assets
on this repository's [GitHub Releases](https://github.com/max-ramas/rms-memory-mcp/releases)
under the matching `v<version>` tag. macOS builds are signed with Developer ID and
notarized; Windows builds are not signed yet β see [GUI-README.md](./GUI-README.md). The private GUI workflow transfers only the completed
`.dmg`, `.msi`/`.exe`, `.AppImage`, `.deb`, and `.rpm` installer files (plus
`SHA256SUMS.txt` when present). With updater signing enabled, the GUI pipeline
mirrors signed `latest.json`, companion `.sig` files, and macOS `*.app.tar.gz`
onto this public release (URLs rewritten to `rms-memory-mcp`; in-app Install
reads `β¦/releases/latest/download/latest.json`). It never mirrors GUI source,
build logs, credentials, or private GUI release archives.
The same publication flow runs for a `v*` GUI tag and for a manually dispatched,
version-validated GUI release.
## π Quick Start
The fastest way to get every IDE on your machine connected:
```bash
rms-memory install
```
This scans `~/.config/` and `~/Library/Application Support/` and hooks `rms-memory` directly into **Cursor**, **Zed**, **Claude Code**, **OpenCode**, and others β no manual JSON editing.
### Generated Wiki namespace
The optional desktop GUI writes human-readable Wiki pages to `<vault>/wiki/`. RMS Memory MCP remains AI-free and treats this directory as generated output rather than canonical memory. A shared case-insensitive path policy (`src/path_policy.rs`, also reused by the GUI) excludes the entire namespace from Markdown/code indexing, vector and full-text retrieval, watchers, the durable graph and Wiki context packs. **Write isolation** matches that policy: `rms_write` requires `.md` and rejects `wiki/**`; canonical `DocumentService` list/read/write APIs exclude or reject wiki; Wiki page mutations use wiki-safe methods that skip memory audit-frontmatter injection. Linked-document `link:` resolution always re-checks that the canonical target stays inside the vault. Full or incremental sync removes legacy Wiki-derived records by path without deleting the files, and `doctor` reports the isolation state explicitly.
For virtual projects without a filesystem path (threads, leads, etc.), use `--scope`:
```bash
rms-memory --scope "thread:abc-123" serve
```
### Use multiple isolated scopes
A scope is an isolation boundary for a vault and its index. Without `--scope`, RMS Memory uses the canonical current working directory; an explicit filesystem path addresses that same kind of project vault. Any other non-empty identifier creates an isolated virtual vault:
```bash
rms-memory serve # current project scope
rms-memory --scope "/home/user/my-project" serve # explicit project scope
rms-memory --scope "thread:abc-123" serve # virtual thread scope
rms-memory --scope "product:acme" serve # virtual product scope
```
For project knowledge plus per-thread history, query each scope explicitly and merge the results in the caller. RMS Memory intentionally does not mix scopes implicitly. Scope IDs may not be empty or exceed 512 characters; absolute and `./`/`../` values are resolved as paths, while all other values are opaque identifiers.
When using `min_confidence`, start with an unfiltered search. Use `0.3β0.5` for broad refinement and reserve `0.7+` for verified canonical facts; records without a confidence value remain visible.
### Configure your vault
The simplest way to configure the server is to run the interactive setup wizard. You don't need to memorize any CLI flags β just run:
```bash
rms-memory config
```
*(Alternatively, set the vault root directly with `rms-memory config --vault-path ~/MyVaults/`, then run `rms-memory init` in each repository you want to register.)*
Register a repository explicitly from its root before connecting IDE agents:
```bash
cd /path/to/project
rms-memory init
```
This creates the project mapping in `~/.rms-memory/registry.toml` and provisions its isolated, structured vault. Routine MCP discovery is read-only and fail-closed: it never creates a project from `/`, never falls back to a shared global vault, and never guesses between multiple registered projects.
```text
~/MyVaults/
βββ <ProjectKey>/
βββ rules/
βββ decisions/
βββ architecture/
βββ artifacts/
βββ docs/
βββ api/
```
### Optional semantic code memory
Markdown memory remains the default corpus. Semantic source indexing is separate, supports all bundled language adapters, and never changes source files:
```bash
rms-memory reindex --code # build/update only derived code memory
rms-memory reindex --all # refresh Markdown vault + code memory
```
Registered projects support `code_index_mode = "off" | "manual" | "watch"`; the default is `off`. Set it from the project root with `rms-memory config --code-index-mode watch` (or add `--scope <project-path>`). `watch` is explicitly opt-in, coalesces supported source saves for three seconds, and **reindexes only the dirty paths** (`try_index_code_paths`) with a full-walk fallback when the index is cold, the dirty set is empty/oversized (>200), or the watcher channel overflows. Concurrent IDE processes share a completion marker so an unchanged workspace stays idle. Code search results include their source language.
Perf smoke for large fixtures: `./scripts/bench_large_vault.sh [notes] [code_files]`.
Language selection is project-scoped and defaults to every bundled adapter:
```bash
rms-memory config --code-languages auto
rms-memory config --code-languages go,typescript,tsx,vue
```
Supported names are `rust`, `go`, `javascript`, `jsx`, `typescript`, `tsx`, `python`, `c`, `cpp`, `java`, `ruby`, `swift`, `vue`, `csharp`, `php`, `kotlin`, `sql`, `html`, and `css`. Generated paths (`node_modules`, `.next`, `.nuxt`, `target`, `vendor`, and `coverage`) are always excluded. Ambiguous `.h` files are indexed as C exactly once; use `.hpp`, `.hh`, or `.hxx` for C++ headers. Vue indexes only inline JavaScript/TypeScript `<script>` contents and maps results back to the `.vue` host file; templates, styles, `script setup` macros, and external `src` scripts remain outside v1.0.5 semantic extraction.
HTML files contribute inline JavaScript `<script>` blocks (mapped back to the `.html` file) and elements with an `id`; CSS files contribute rule sets by selector and `@keyframes`. SQL files contribute `CREATE TABLE / VIEW / TYPE / FUNCTION / PROCEDURE / TRIGGER` statements.
### Use an existing Obsidian vault
```bash
rms-memory projects attach-obsidian ~/Obsidian/Notes --key notes # in place, read-only
rms-memory import --obsidian ~/Obsidian/Notes --dry-run # or copy into this project's vault
```
An attached vault is indexed and searchable (pass `project: "notes"`), but RMS Memory never creates, edits, moves or deletes files in it: `rms_write`, checkpoints, prune and hooks refuse, and `projects remove` only drops the registration. The index lives under `~/.rms-memory/dbs/` like any other. Obsidian links (`[[Note]]`, `[[Note|label]]`, `[[Note#Heading]]`, `![[image.png]]`, frontmatter `aliases`) resolve in the graph, the index and doctor.
### Embedding model and retrieval eval
The default model is `multilingual-e5-small` (384 dimensions, downloaded once). To compare it with others on your own notes and switch:
```bash
rms-memory embedding list
rms-memory embedding eval --models multilingual-e5-small,bge-m3 --show-misses
rms-memory embedding use bge-m3 # or: ollama:nomic-embed-text (local Ollama)
```
`eval` turns each note's first heading into a query (or reads `--queries file.jsonl` with `{"query": "...", "expect": ["path.md"]}` lines) and reports hit@1, hit@k and MRR for embeddings alone and for hybrid search. Each model keeps its own index under the project's `dbs/` folder, so switching back reuses the old one. After `use`, restart running MCP servers (IDE, GUI); the next sync builds the new index. Ollama URLs must be loopback (`http://127.0.0.1:11434` by default).
## π CLI Commands
| Command | Description |
|---|---|
| `rms-memory serve [--http] [--port 7337]` | Starts the JSON-RPC stdio server (auto-triggered by your IDE). `--http` serves MCP Streamable HTTP on `127.0.0.1` instead, with a bearer token. |
| `rms-memory init` | Registers a project into the global registry. `--dry-run` supported. `--full` forces creation of all IDE rule templates. |
| `rms-memory inject-rules [--all]` | Re-injects managed IDE rule blocks with the concrete registry `project` key (existing files only, unless `--full`). Use after template updates. Fail-closed: a single unregistered path is refused rather than injected with a guessed key β run `init` there first, or use `--all` to refresh every registered project. |
| `rms-memory import` | Scans for existing docs (`README.md`, `docs/`, `ADR/`) and imports them β interactively or via `--auto-import`. `--obsidian <DIR> [--into obsidian] [--dry-run]` copies an Obsidian vault (notes, attachments, folders) into the project vault without touching the source or overwriting files. |
| `rms-memory install` | Hooks the server into supported IDEs. `--dry-run` supported. |
| `rms-memory uninstall` | Removes the server from all discovered IDE configurations. |
| `rms-memory doctor` | Runs 8-point vault health diagnostics (the 8th reports credentials stored in notes, never changing them; a 9th checks `patterns/` notes against the code when the vault has them), shows the code-index state and prints update / restart notices. `--repair-frontmatter` safely repairs duplicate, missing, and known attached frontmatter IDs with backups; arbitrary invalid YAML is reported but never rewritten automatically. |
| `rms-memory config` | Without flags: prints global + current-project settings, then offers interactive global editing. Any flag runs non-interactively. Global: `--vault-path`, `--auto-add`, `--inject-rules`, `--auto-import skip\|link\|import_organize\|import`, `--max-backups N`. Project (cwd or `--scope <path>`): `--code-index-mode off\|manual\|watch`, `--code-languages auto\|<comma-list>`, `--include <globs>`, `--exclude <globs>`, `--cross-project-vault true\|false`. |
| `rms-memory reindex [--vault\|--code\|--all]` | Refreshes Markdown memory (default), derived semantic code memory, or both. |
| `rms-memory sync` | Incremental LanceDB delete-then-insert sync (also runs automatically during `serve`). |
| `rms-memory gc` | Prunes orphaned LanceDB indices belonging to deleted vaults. |
| `rms-memory prune [--older-than-days N] [--apply]` | Archives superseded notes older than N days (default 30) under `artifacts/pruned/YYYY-MM-DD/`. Dry-run by default; never deletes. Distinct from `gc` (orphan DBs) and from supersession (lifecycle marking). |
| `rms-memory file-history catch-up\|reindex\|query` | Derived `code_path` git fileβcommit cache (Lance). `reindex` requires `--project`. Prefer MCP `rms_file_history` for agents. |
| `rms-memory update [--check\|--yes\|--rollback\|--force\|--json]` | Checks the RMS update server and installs a newer binary (signature, size and sha256 verified, atomic swap, `--rollback` restores the previous one). |
| `rms-memory gui [--download-only\|--no-open\|--yes\|--json]` | Installs the optional desktop GUI (14-day trial) from the update server and opens it; opens it when it is already installed. Downloads are labelled `src=cli` on the update server. |
| `rms-memory stats [--days N] [--json] [--reset]` | Local, content-free statistics: how many characters each tool returned to agents (see `docs/token-usage.md`). Never sent anywhere; `RMS_MEMORY_NO_STATS=1` turns the recording off. |
| `rms-memory wiki ...` | Generates wiki context packs from the vault and the code index (same data as `rms_wiki_pack`). |
| `rms-memory features` | Live GUI/AI status banner + capability catalog (`GUI`/`AI` tags; soft yellow when GUI absent, gray when installed). Informational only β MCP core is never paywalled. |
| `rms-memory graph status\|ensure\|neighbors\|path\|snapshot\|export-dot\|β¦` | Durable knowledge graph (same actions as MCP `rms_graph`). Mutations require `--project`. |
| `rms-memory log` | Tails the telemetry log (`~/.rms-memory/rms.log`; moved to `rms.log.1` when a process starts and it exceeds 20 MB). |
| `rms-memory export-llms` | Compiles the current vault into a single `llms.txt` payload. |
| `rms-memory projects list` | Lists registered project keys and their code/vault paths. |
| `rms-memory projects locate --project <key>` | Resolves one registered project key. |
| `rms-memory projects resolve-key --path <dir>` | Looks up the registry key for a code path (including post-migrate redirects). |
| `rms-memory projects migrate --project <key> --to <new-path>` | Moves/renames a registered project after the repo folder changed. Plans key rename, vault/db moves, and `link:` repairs; supports `--dry-run`, `--no-repair-links`, `--strict-git`. Prefer this over recreating `.git` or re-running `init`. |
| `rms-memory projects remove <key>` | Removes an erroneous project registration while preserving its vault files. |
| `rms-memory projects attach-obsidian <PATH> [--key KEY]` | Registers an existing Obsidian vault in place, read-only: indexed and searchable, never modified. The read-only flag is kept in `~/.rms-memory` (`registry.toml` and `read-only-vaults`); if that directory is deleted or recreated, attach the vault again. |
| `rms-memory embedding list\|use <id>\|eval` | Lists the bundled embedding models, switches the model (`ollama:<model>` for a local Ollama), or scores retrieval quality (hit@1, hit@k, MRR) on the project's vault, for embeddings alone and hybrid search. Restart MCP servers after `use`; the next sync builds the model's index. |
| `rms-memory dialogs init\|mode\|collect\|index\|search\|session\|status\|read\|restore\|verify` | Optional local archive of your AI-assistant dialogs (Claude Code, Codex, Antigravity, OpenCode, Cursor, Zed), read from the files those tools already keep on disk; nothing is intercepted and nothing is sent anywhere. `init --encrypt` encrypts every file with [age](https://age-encryption.org) (passphrase only needed to read). Modes: `off`, `collect`, `collect-and-serve`. `collect --index` also builds a full-text index of user and assistant turns (encrypted when the archive is); `search` and `session` read it. See `docs/dialogs.md`. |
| `rms-memory hook --event <e>` | Editor-agnostic continuity hook (`session_start`, `pre_compact`, `session_stop`); JSON on stdout. `--project <key>` or unique cwd resolution (fail-closed); `--apply` creates/updates or closes a checkpoint. |
| **All commands** | Accept `--scope <id>` to target arbitrary isolated vaults (threads, leads, etc.). |
## π MCP Tools Exposed
Tool descriptions are written to be **action-oriented**, so agents use the vault proactively without being asked.
<table>
<tr><th>Tool</th><th>Purpose</th><th>Input</th></tr>
<tr>
<td><code>rms-memory_rms_search</code></td>
<td>Searches Markdown memory by default. Set <code>corpus</code> to <code>code</code> or <code>all</code>; <code>all</code> uses Reciprocal Rank Fusion. Pass <code>projects: [key, β¦]</code> for read-only cross-project federation (when both <code>project</code> and <code>projects</code> are set, <code>projects</code> wins); vault/all with <code>len>1</code> requires <code>cross_project_vault=true</code> on every listed key (hard fail β no silent degrade). Returns an inject/abstain decision envelope (<code>decision</code>, <code>reason</code>, <code>injected_ids</code>, optional <code>retrieval_mode</code>). Optional <code>include_file_history</code> / <code>include_graph_neighbors</code> enrich hits (not with federated <code>projects</code>). Agents are instructed to call this <em>first</em>.</td>
<td><code>{ query, project?, projects?, corpus: vault|code|all, limit, include_content, snippet_chars?, pattern_status?, min_confidence, max_chars?, min_score?, include_file_history?, include_graph_neighbors?, include_notes? }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_code_search</code></td>
<td>Convenience endpoint for the derived semantic code index. Results include file, symbol, kind, line range, and segment index, plus <code>code_index</code> (fresh / stale / not indexed) and <code>related_notes</code> (decisions and patterns that mention the file or symbol). Same optional <code>projects: [β¦]</code> federation as <code>rms_search</code> (code-only; does not change the active bind). Optional <code>include_graph_neighbors</code>.</td>
<td><code>{ query, project?, projects?, limit, include_content, include_file_history?, include_graph_neighbors?, include_notes? }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_read</code></td>
<td>Reads a document found via <code>rms_search</code>: the whole note by default, or just an <code>outline</code>, one <code>heading</code>, a character window (<code>max_chars</code>/<code>offset</code>), or a short "unchanged" stub when <code>if_hash</code> still matches. Returns a <code>content_hash</code>.</td>
<td><code>{ path, project?, outline?, heading?, max_chars?, offset?, if_hash? }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_write</code></td>
<td>Persists new decisions, constraints, or rules. Agents are prompted to call this <em>proactively</em> after solving a tricky bug or learning a preference. Auto-injects audit metadata. Optional soft supersede of a prior note. Optional <code>dry_run</code> previews create/update/noop without disk or index side effects. Content or <code>source</code> containing a known token format or private key is refused (kind + line, never the value).</td>
<td><code>{ path, project?, content, mode: replace|append|create, confidence, source, status?, supersedes?, dry_run? }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_file_history</code></td>
<td>Derived <code>code_path</code> git fileβcommit history (no shell). Lazy catch-up; <code>action=reindex</code> requires explicit <code>project</code> (after force-push). Prefer over <code>git log</code>. Search may set <code>include_file_history</code> for the last 3 commits on code hits (not with <code>projects</code> federation).</td>
<td><code>{ path?, project?, limit?, include_message?, action?: query|catch_up|reindex }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_graph</code></td>
<td>Durable knowledge graph for agents: status/ensure/neighbors/path/snapshot/semantic/export_dot; create_edge and suppress/restore overrides (mutations require explicit <code>project</code>). Refreshed on sync and immediately after <code>rms_write</code> (write response includes <code>graph_refresh</code>). Visual GraphView remains GUI-only. Also available as CLI <code>rms-memory graph</code>.</td>
<td><code>{ action?, project?, node?, path?, from?, to?, source?, target?, relation?, edge_key?, override_action?, force?, limit?, max_depth?, β¦ }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_doctor</code></td>
<td>Eight-point vault health report (structure, IDs, links, LanceDB, wiki isolation, registry, freshness, stored credentials) plus <code>notices</code> for a newer release or a replaced server binary. <code>repair_frontmatter</code> requires explicit <code>project</code>.</td>
<td><code>{ project?, repair_frontmatter? }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_reindex</code></td>
<td>Full vault/code/all index rebuild. Requires explicit <code>project</code>.</td>
<td><code>{ project, corpus?: vault\|code\|all }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_sync</code></td>
<td>Incremental vault index sync (prefer over reindex for routine catch-up).</td>
<td><code>{ project? }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_projects</code></td>
<td>Lists registered project keys even when the MCP client did not supply workspace roots.</td>
<td><code>{}</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_remind</code></td>
<td>Reminders for the user: add (<code>due_at</code> with a UTC offset, or <code>in_minutes</code>), list, snooze, done, cancel. Due reminders are appended to tool responses as a <code>[RMS reminder]</code> block (windows 30/20/10/5 minutes). Free in the MCP; the management page is part of the GUI.</td>
<td><code>{ action, text?, due_at?, in_minutes?, id? }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_overview</code></td>
<td>Structured orientation for exactly one project: counts by folder/status, recent notes, active checkpoints, coverage metadata, index lag (modified/new/removed files) and the code repository's git state (branch, HEAD, ahead/behind, changed file names β never diff contents). Fail-closed scoping; never aggregates across projects. Returns <code>structuredContent</code> + JSON text.</td>
<td><code>{ project?, recent_limit? }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_checkpoint_save</code> / <code>done</code> / <code>load</code> / <code>query</code></td>
<td>Session continuity on plain Markdown (<code>artifacts/checkpoints/</code>): save goal/pending/links before context compaction, list or load active checkpoints on resume, close with a summary β closing writes a durable session note under <code>artifacts/sessions/</code> and drops the checkpoint out of default recall. <code>goal</code>/<code>pending</code>/<code>summary</code> get the same credential refusal as <code>rms_write</code>.</td>
<td><code>{ name, project?, goal?, pending?, links?, summary?, status? }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_system_instructions</code></td>
<td>Returns the canonical memory-usage protocol (search-first, persist, continuity) so agents can self-bootstrap without injected rule files.</td>
<td><code>{ project? }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_wiki_pack</code></td>
<td>Builds a deterministic Wiki context pack from vault/code sources (manifest-driven). Writes under <code>wiki/.generation/</code>; does not call cloud LLMs.</td>
<td><code>{ project?, manifest? }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_prune</code></td>
<td>Archives aged <code>status: superseded</code> notes under <code>artifacts/pruned/YYYY-MM-DD/</code> with a JSONL manifest. Safe by default: <code>apply</code> is false (dry-run). Never deletes. Skips pinned, wiki, trash, and prior prune batches. Distinct from <code>gc</code> and from supersession marking.</td>
<td><code>{ project?, older_than_days?, apply? }</code></td>
</tr>
<tr>
<td><code>rms-memory_rms_hygiene</code></td>
<td>Read-only consolidation report: near-duplicate notes (embedding similarity confirmed by shared word 3-grams), identical notes, checkpoints untouched for 14+ days, session notes older than 90 days. The agent merges with <code>rms_write</code> + <code>supersedes</code> and closes checkpoints with <code>rms_checkpoint_done</code>.</td>
<td><code>{ project?, min_similarity? }</code></td>
</tr>
</table>
MCP **resources** (1.3.0): `rms://<project>/overview`, `rms://<project>/instructions`, `rms://<project>/checkpoint/<name>` and `rms://<project>/note/<path>` are read-only views for clients that attach context by URI. MCP **prompts**: `session_start`, `save_progress` (`name`) and `record_decision` (`topic`).
The server resolves an explicit scope or legacy `rootUri`, then negotiates MCP `roots/list`. If a client exposes neither (or opens several registered roots), pass the short registry key in `project`; injected agent rules contain the correct key for that repository. `rms_projects` lists valid keys without requiring a bound workspace. An explicit `project` on any tool call always wins and rebinds the active vault β one long-lived MCP process can serve every registered project. Without `project`, ambiguity stays fail-closed (no silent pick-first).
To remove an accidental registration without deleting its Markdown vault:
```bash
rms-memory projects remove <key>
```
If the repository folder was **moved or renamed**, do **not** recreate `.git` or
re-run `init` from scratch. Plan and apply a migrate instead:
```bash
rms-memory projects migrate --project <key> --to /new/path/to/repo --dry-run
rms-memory projects migrate --project <key> --to /new/path/to/repo
rms-memory projects resolve-key --path /new/path/to/repo
```
The CLI command `projects remove` is intentionally non-destructive. The companion GUI exposes a
separate **Delete project and data** action for permanent cleanup of the
registration, Markdown vault, and derived index. It requires typing the exact
project key and accepts only a dedicated child of the configured master vault;
the repository source path is explicitly excluded from deletion.
## π Architecture Highlights
<details>
<summary><b>Cargo workspace (v1.0.9+ / 1.1.1)</b></summary>
Implementation lives in path-only crates under `crates/` (`rms-memory-core`, `rms-memory-index`, `rms-memory-vault`, `rms-memory-cli` for cycle-free `gc`/`prune`). The published product remains the root umbrella `rms-memory-mcp` (binary + MCP server + tools + rules injector + `serve`), which re-exports every former `rms_memory_mcp::<module>` path so the companion GUI keeps stable imports. Heavy deps (`lancedb`, `ort`, `fastembed`, tree-sitter) concentrate in `rms-memory-index`. Details: [docs/crate-split.md](./docs/crate-split.md).
</details>
<details>
<summary><b>Unified Configuration & Knowledge Isolation</b></summary>
A central `~/.rms-memory/registry.toml` routes every project to an isolated vault, computed from a hash of the project path. No `.mcp` files, no per-repo config β global MCP entries (e.g. Zed's `settings.json`) can target any workspace automatically.
</details>
<details>
<summary><b>Safe Project Lifecycle</b></summary>
The transport-neutral `ProjectService` is the single implementation used by
the CLI and companion GUI. Registry mutation remains revisioned through
`ConfigManager`; deletion validates canonical paths before unregistering and
returns structured warnings if filesystem cleanup cannot be completed.
</details>
<details>
<summary><b>Linked Documents (zero-copy import)</b></summary>
Instead of duplicating existing docs into the vault, `rms-memory import` can create lightweight **Link Files** β Markdown stubs with a `link: <path>` frontmatter property. Reads/writes are transparently redirected to the source file, while the vector index still respects the vault's directory structure.
</details>
<details>
<summary><b>Hybrid Search (LanceDB + Tantivy)</b></summary>
Embedded LanceDB (`~/.rms-memory/dbs/`) combines vector similarity with full-text search, so a query never comes back empty just because the exact keywords didn't match.
</details>
<details>
<summary><b>Separate Markdown and Code Corpora</b></summary>
Human-authored Markdown and derived Rust code live in separate tables. Code chunks carry stable symbol identities, line ranges, and preambles; unchanged chunks reuse their vectors. `corpus=all` fuses independently ranked result sets with Reciprocal Rank Fusion, avoiding any assumption that distances from the two corpora are comparable.
</details>
<details>
<summary><b>Graph-ready Knowledge Core</b></summary>
Graph nodes and edges are deliberately independent of retrieval chunk boundaries. Markdown links, Rust imports, trait implementations, and lexical call hints can be reconciled as derived relationships; user-created edges and suppress/restore overrides persist across reindexing. Current Rust call edges are syntax-level hints, not a compiler-accurate call graph.
</details>
<details>
<summary><b>AST-Aware Chunking</b></summary>
`pulldown-cmark` parses the Markdown AST directly. Chunks are built by walking up to the parent heading, with a strict 1500-character boundary and ~200-character overlapping window for oversized code blocks β no mid-sentence truncation.
</details>
<details>
<summary><b>Ten-Point Production Resiliency</b></summary>
1. Path traversal + filter injection prevention
2. Zombie process prevention (watcher shutdown on EOF + `std::process::exit(0)`)
3. Graceful shutdown (`SIGINT`/`Ctrl+C` handler)
4. macOS sandbox bypass for `fastembed` model downloads
5. `rms-memory gc` β orphaned vector store pruning
6. PID-aware per-project writer lock and read-only background synchronization across IDE processes
7. Markdown watcher plus an explicitly opt-in, 3s-debounced code watcher with **path-scoped** reindex and shared-generation suppression
8. Write-guard snapshotting with rolling `.bak` backups (default: 5)
9. Isolated telemetry logging (`~/.rms-memory/rms.log`)
10. `llms.txt` export for flat, decoupled LLM ingestion
</details>
<details>
<summary><b>Validated v1.0.5 Multi-IDE Behavior</b></summary>
Live MCP requests have been verified for `rms_search(corpus=vault|code|all)` and `rms_code_search`. On this repository, `reindex --code` indexed 43 Rust files into 298 semantic items and 438 segments with all vectors reused on an unchanged run. An isolated five-server watcher run coalesced rapid saves into one shared completion-marker update; a later real-project stress gate completed concurrent GeoMail, License Server, RMS Monitoring, and GeoTax Site indexing, then seven MCP servers (after four IDE restarts) stayed at 0.0% CPU with no background reindex.
</details>
## π§© Supported IDEs
| IDE | Auto-Install | Rules Injection |
|---|:---:|:---:|
| Cursor | β
| `.cursorrules` |
| Zed | β
| `.zed/assistant.md` |
| Claude Code | β
| `.claude/CLAUDE.md` |
| OpenCode | β
| β |
| Codex | β
| β |
| VS Code | β
| β |
| Antigravity | β
| β |
## π License
MIT License β see [LICENSE](LICENSE) for details.
---
<div align="center">
<sub>Built by <a href="https://ramzaeff.com">Maksim Ramzaev</a> Β· <a href="https://rms-ds.com">RMS Digital Services</a></sub>
</div>
---
\* Contacted directly by the tool for your convenience (a fallback update lookup on GitHub, the one-time embedding model download from Hugging Face). RMS does not take part in that exchange.
TDQS
Scored across 20 tools
Most tools target clearly distinct operations: search, read/write, checkpoint lifecycle, sync/reindex, diagnostics, graph, history, and reminders. A few pairs need careful reading to distinguish, notably rms_doctor vs rms_hygiene (diagnostics vs duplicate/cleanup reporting), rms_prune vs rms_hygiene, and rms_sync vs rms_reindex, but their descriptions explicitly clarify the boundaries.
All tools share a predictable rms_ snake_case prefix, which is consistent throughout. Within that, some names are verb-first (rms_search, rms_read, rms_write) and others are noun-first (rms_checkpoint_query, rms_file_history, rms_wiki_pack), but the style remains readable and mostly grouped by domain.
Twenty tools is on the heavy side for a memory server, though the product genuinely spans search, persistence, checkpoints, indexing, graph, diagnostics, and reminders. Tools like rms_system_instructions and rms_remind feel somewhat peripheral, making the surface borderline heavy rather than tightly scoped.
The surface covers search (vault/code/all), read/write, checkpoint create/query/load/close, project discovery, overview, incremental sync and full reindex, graph traversal/mutation, file history, diagnostics, hygiene, pruning, wiki packing, and reminders. Lifecycle coverage is broad and coherent, with only intentionally absent operations like hard deletion, which is explicitly replaced by pruning/archiving.