{"id":49603142,"url":"https://github.com/ancientice/mempalace-rs","last_synced_at":"2026-05-04T10:04:26.722Z","repository":{"id":355362763,"uuid":"1204645001","full_name":"AncientiCe/mempalace-rs","owner":"AncientiCe","description":"Local-first AI memory system in Rust with SQLite storage, semantic search, knowledge graph, MCP server, and CLI.","archived":false,"fork":false,"pushed_at":"2026-05-03T07:40:45.000Z","size":249,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-03T09:24:14.469Z","etag":null,"topics":["ai","embeddings","knowledge-graph","llm","local-first","mcp","memory","rust","semantic-search","sqlite"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AncientiCe.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-08T07:39:47.000Z","updated_at":"2026-05-03T07:40:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/AncientiCe/mempalace-rs","commit_stats":null,"previous_names":["ancientice/mempalace-rs"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/AncientiCe/mempalace-rs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AncientiCe%2Fmempalace-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AncientiCe%2Fmempalace-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AncientiCe%2Fmempalace-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AncientiCe%2Fmempalace-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AncientiCe","download_url":"https://codeload.github.com/AncientiCe/mempalace-rs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AncientiCe%2Fmempalace-rs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32602730,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T22:12:39.696Z","status":"online","status_checked_at":"2026-05-04T02:00:06.625Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","embeddings","knowledge-graph","llm","local-first","mcp","memory","rust","semantic-search","sqlite"],"created_at":"2026-05-04T10:04:25.201Z","updated_at":"2026-05-04T10:04:26.705Z","avatar_url":"https://github.com/AncientiCe.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mempalace-rs\n\n[![CI](https://github.com/AncientiCe/mempalace-rs/actions/workflows/ci.yml/badge.svg)](https://github.com/AncientiCe/mempalace-rs/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![Rust 1.82+](https://img.shields.io/badge/rust-1.82%2B-orange.svg)](https://www.rust-lang.org)\n\nA local memory palace for AI assistants, implemented in Rust.\n\nThis project stores verbatim text, embeds it locally, and retrieves relevant\ndrawers with semantic search. It can be used as a CLI, an MCP stdio server, or\nas a Rust library through the `Palace` facade.\n\n## What It Does\n\n- Stores project files and conversation turns in a local SQLite database.\n- Generates local embeddings with ONNX Runtime and `all-MiniLM-L6-v2`.\n- Retrieves memories by semantic similarity with optional wing/room filters.\n- Provides a knowledge graph for temporal entity relationships.\n- Exposes MCP tools for assistants that support Model Context Protocol.\n- Offers a small Rust library API for embedding memory into other services.\n\n## Storage\n\nCollapses Python's dual-store (ChromaDB + SQLite) into **one file** at `~/.mempalace/palace.db`:\n\n| Table | Purpose |\n|---|---|\n| `drawers` | Text content + embedding BLOB + metadata |\n| `entities` | KG entity nodes |\n| `triples` | KG temporal relationship edges |\n\nEmbeddings are stored as `f32` vectors from `all-MiniLM-L6-v2`. Search uses local cosine similarity over the stored vectors.\n\n---\n\n## Benchmarks\n\nRetrieval recall on the LongMemEval `s_cleaned` split — 500 questions over conversational haystacks of ~50 sessions / ~115k tokens each (30 abstention questions are filtered out per the standard convention, leaving 470 evaluated).\n\nThe recipe behind the numbers below:\n\n- **Granularity**: one drawer per session.\n- **Indexed content**: the **full session** — both user and assistant turns are stored and embedded together. No user-turn filtering, no summarization, no LLM extraction.\n- **Embedder**: `all-MiniLM-L6-v2` (384-dim, ONNX), 512-token cap, run locally — no API calls.\n- **Retrieval**: **hybrid** — BM25 (k1=1.5, b=0.75, weight 0.35) fused with cosine similarity (weight 0.65), top-K = 10. Pure score fusion, no hand-tuned keyword/temporal/preference boosters.\n- **No LLM at any stage**: no extraction, no rerank, no answer generation. The recall numbers measure the retriever in isolation.\n- **Metric**: `recall_any@K` at session granularity — does any gold session appear in the top-K results?\n- **Hardware**: Apple M1 Pro, 10 cores (8P + 2E), 32 GB RAM.\n\n| Split | R@1 | R@5 | R@10 |\n|---|---:|---:|---:|\n| `longmemeval_oracle` (sanity check) | 1.000 | 1.000 | 1.000 |\n| `longmemeval_s_cleaned` | **0.889** | **0.981** | **0.991** |\n\nPer-question-type on `s_cleaned`:\n\n| Question type | R@1 | R@5 | R@10 |\n|---|---:|---:|---:|\n| knowledge-update | 0.944 | 1.000 | 1.000 |\n| multi-session | 0.909 | 0.983 | 1.000 |\n| single-session-assistant | 1.000 | 1.000 | 1.000 |\n| single-session-preference | 0.633 | 0.867 | 0.933 |\n| single-session-user | 0.922 | 1.000 | 1.000 |\n| temporal-reasoning | 0.835 | 0.976 | 0.984 |\n\n### Reading the numbers\n\n- **`oracle` is a sanity check, not a real result.** That split hands the retriever only the sessions known to contain the answer, so perfect recall just confirms the pipeline is wired up correctly.\n- **`s_cleaned` is the real test.** ~50 sessions / ~115k tokens of conversational haystack per question, no hints. R@5 = 0.981 means that for 461 of 470 evaluated questions, a gold session appears somewhere in the top 5 retrieved.\n- **R@1 → R@5 → R@10 tells you where the failures cluster.** The jump from 0.889 to 0.981 means most \"misses\" at top-1 are near-misses — the right session is usually rank 2–5, displaced by a lexically similar distractor. The further jump to 0.991 at top-10 means only ~9 questions out of 470 fall outside the top-10 entirely; those are the genuinely hard cases.\n- **Per-question-type breakdown is where the model's blind spots show.**\n  - `single-session-assistant`, `single-session-user`, `knowledge-update`: ≥0.94 at R@1, ≈1.0 at R@5. The retriever handles direct questions where the answer is stated verbatim in one session.\n  - `multi-session` and `temporal-reasoning`: strong at R@5 (~0.98) but lower at R@1 (~0.83–0.91). Multiple sessions are relevant and the \"best\" one is a judgement call — top-1 ranking among near-equivalents is genuinely ambiguous.\n  - `single-session-preference`: the visible weak spot at 0.633 / 0.867 / 0.933. Preference questions (\"what's my favorite X\") are answered by sentences like *\"I like…\"* / *\"I prefer…\"* that don't share keywords with the question. Pure BM25 + frozen MiniLM has no signal for preference-shaped sentences specifically; closing this gap would require either an LLM-extracted preference index or a hand-rolled pattern booster.\n- **What's deliberately *not* in these numbers.** No LLM at any stage — no extraction during ingest, no query rewriting, no rerank, no answer generation. No per-dataset hyperparameter tuning. No keyword/temporal/preference boosters. No GPU. The result is the retrieval engine in isolation, on a single CPU, with fixed defaults.\n\n---\n\n## Installation\n\n### macOS / Linux\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/AncientiCe/mempalace-rs/main/scripts/install.sh | sh\n```\n\n### Windows\n\n```powershell\nirm https://raw.githubusercontent.com/AncientiCe/mempalace-rs/main/scripts/install.ps1 | iex\n```\n\nThe installer downloads the matching GitHub Release binary, verifies its SHA-256\nchecksum, installs it locally, and registers the MCP server with Cursor, Codex,\nand Claude Code.\n\nDevelopment install:\n\n```bash\ncargo install --path .\nmempalace install --all\n```\n\nThe first time you run `mine`, the embedding model is downloaded automatically from HuggingFace and cached.\n\n---\n\n## Quick Start\n\n```bash\n# 1. Detect rooms from your project folder structure\nmempalace init ~/my-project\n\n# 2. Index the project into the palace\nmempalace mine ~/my-project\n\n# 3. Index conversations\nmempalace mine-convos ~/Desktop/transcripts\n\n# 4. Search\nmempalace search \"how did we decide on the database schema\"\n\n# 5. Wake-up (L0 + L1 context for the AI)\nmempalace wake-up\n```\n\n---\n\n## CLI Reference\n\n| Command | Description |\n|---|---|\n| `mempalace init \u003cdir\u003e` | Detect rooms from folder structure, write `mempalace.yaml` |\n| `mempalace mine \u003cdir\u003e` | Chunk, embed, and store project files |\n| `mempalace mine-convos \u003cdir\u003e` | Ingest conversation exports |\n| `mempalace search \u003cquery\u003e` | Semantic search with similarity scores |\n| `mempalace wake-up` | Print L0 (identity) + L1 (essential story) context |\n| `mempalace status` | Palace overview: drawer counts by wing/room |\n| `mempalace split` | Split Claude Code mega-transcripts by session |\n| `mempalace repair` | Re-embed any drawers missing vectors |\n| `mempalace install` | Register the MCP server with Cursor, Codex, and Claude Code |\n| `mempalace uninstall` | Remove MemPalace from MCP client configs |\n| `mempalace doctor` | Inspect binary path, palace DB, and MCP config status |\n| `mempalace mcp` | Start the MCP stdio server |\n\n### `mine` flags\n\n```bash\nmempalace mine ~/my-project \\\n  --wing my_project          # Override wing name\n  --limit 100                # Cap at 100 files\n  --dry-run                  # Preview without storing\n  --no-gitignore             # Ignore .gitignore rules\n  --include vendor,third_party  # Force-include these paths\n```\n\n### `mine-convos` flags\n\n```bash\nmempalace mine-convos ~/Desktop/transcripts \\\n  --wing claude_sessions \\\n  --mode exchange   # or: general (decisions/milestones/emotions)\n  --limit 50\n  --dry-run\n```\n\n### `split` flags\n\n```bash\nmempalace split \\\n  --source ~/Desktop/transcripts \\\n  --min-sessions 2 \\\n  --dry-run\n```\n\n---\n\n## MCP Setup\n\nFor Cursor, Codex, and Claude Code:\n\n```bash\nmempalace install --all\n```\n\nThis writes the local `mempalace mcp` stdio server into:\n\n- Cursor: `~/.cursor/mcp.json`\n- Codex: `~/.codex/config.toml`\n- Claude Code: `~/.claude/mcp_servers.json`\n\nFor a project-local Cursor config:\n\n```bash\nmempalace install --client cursor --scope project --path /path/to/project\n```\n\nTo inspect the current setup:\n\n```bash\nmempalace doctor\n```\n\nManual Cursor / Claude JSON shape:\n\n```json\n{\n  \"mcpServers\": {\n    \"mempalace\": {\n      \"command\": \"mempalace\",\n      \"args\": [\"mcp\"]\n    }\n  }\n}\n```\n\nManual Codex TOML shape:\n\n```toml\n[mcp_servers.mempalace]\ncommand = \"mempalace\"\nargs = [\"mcp\"]\n```\n\nRestart your agent after changing MCP configuration.\n\n### MCP Tools\n\nThe server exposes tools for status, taxonomy, search, drawer CRUD, knowledge\ngraph operations, graph tunnels, hook acknowledgements, and agent diaries:\n\n| Tool | Description |\n|---|---|\n| `mempalace_status` | Palace overview + protocol |\n| `mempalace_list_wings` | List wings with drawer counts |\n| `mempalace_list_rooms` | List rooms within a wing |\n| `mempalace_get_taxonomy` | Full wing → room → count tree |\n| `mempalace_get_aaak_spec` | AAAK compressed memory dialect spec |\n| `mempalace_search` | Semantic search over drawers |\n| `mempalace_check_duplicate` | Check if content already exists |\n| `mempalace_add_drawer` | File content into the palace |\n| `mempalace_delete_drawer` | Remove a drawer by ID |\n| `mempalace_kg_query` | Query entity relationships |\n| `mempalace_kg_add` | Add a fact (subject → predicate → object) |\n| `mempalace_kg_invalidate` | Mark a fact as no longer true |\n| `mempalace_kg_timeline` | Chronological fact history |\n| `mempalace_kg_stats` | Knowledge graph overview |\n| `mempalace_traverse` | BFS graph walk from a room |\n| `mempalace_find_tunnels` | Rooms bridging two wings |\n| `mempalace_graph_stats` | Palace graph summary |\n| `mempalace_diary_write` | Write a diary entry in AAAK format |\n| `mempalace_diary_read` | Read recent diary entries |\n\n---\n\n## Migration from Python\n\nThe Rust version uses a new single-file database (`palace.db`). Your existing ChromaDB data cannot be migrated automatically.\n\n**Steps:**\n\n```bash\n# 1. Re-mine your projects\nmempalace init ~/my-project \u0026\u0026 mempalace mine ~/my-project\n\n# 2. Re-index conversations\nmempalace mine-convos ~/Desktop/transcripts\n\n# 3. Verify\nmempalace status\n```\n\nYour `identity.txt`, `people_map.json`, and `known_names.json` in `~/.mempalace/` are compatible and will be read automatically.\n\n---\n\n## Test on a Project\n\n```bash\nmempalace init /path/to/project\nmempalace mine /path/to/project\nmempalace status\n```\n\nRestart Cursor, Codex, or Claude Code, then ask the agent a project question that\nshould use memory, for example: \"Search MemPalace for how this project handles\ndatabase migrations.\" The agent should call `mempalace_search` through MCP\ninstead of re-indexing the repository from scratch.\n\n---\n\n## Configuration\n\n`~/.mempalace/config.json` is read on startup. Environment variables take highest priority:\n\n| Env Var | Default | Description |\n|---|---|---|\n| `MEMPALACE_PALACE_PATH` | `~/.mempalace/palace` | Palace data directory |\n\n### `mempalace.yaml` (per-project)\n\nCreated by `mempalace init`. Example:\n\n```yaml\nwing: my_project\nrooms:\n  - name: backend\n    description: Server and API code\n    keywords: [api, server, routes, models]\n  - name: frontend\n    description: UI components\n    keywords: [ui, components, pages, views]\n  - name: general\n    description: Everything else\n    keywords: []\n```\n\n---\n\n## Memory Stack\n\n| Layer | Name | Description |\n|---|---|---|\n| L0 | Identity | `~/.mempalace/identity.txt` — always loaded (~100 tokens) |\n| L1 | Essential Story | Top drawers by importance, grouped by room (~600–900 tokens) |\n| L2 | On-Demand | Wing/room filtered retrieval |\n| L3 | Deep Search | Full semantic search |\n\n`mempalace wake-up` prints L0 + L1. The AI uses MCP tools for L2/L3.\n\n---\n\n## Development\n\n```bash\ncargo build\ncargo test\ncargo clippy\n```\n\nTests use in-memory SQLite — no palace.db needed. The embedding model is not loaded in tests that don't require it.\n\n---\n\n## Hooks Compatibility\n\nShell hooks that previously called `python -m mempalace.mcp_server` can now call `mempalace mcp`. Update the binary path in your hooks:\n\n```bash\n# Before (Python)\nexec python -m mempalace.mcp_server\n\n# After (Rust)\nexec mempalace mcp\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fancientice%2Fmempalace-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fancientice%2Fmempalace-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fancientice%2Fmempalace-rs/lists"}