mimirs
v1.3.0
Published
Persistent project memory for AI coding agents — semantic search, AST-aware chunking, dependency graphs, and conversation history
Downloads
911
Maintainers
Readme
Your agent starts every session blind — guessing filenames, grepping for keywords, burning context on irrelevant files, and forgetting everything you discussed yesterday.
On one real project, a typical prompt was burning 380K tokens and ~12 seconds end-to-end.
After indexing with mimirs: 91K tokens, ~3 seconds — a 76% drop on that codebase. Your numbers will vary with repo size, query, and model.
Quick start
1. Prerequisites
Bun (curl -fsSL https://bun.sh/install | bash) and, on macOS, a modern SQLite — Apple's bundled one doesn't support extensions:
brew install sqliteLinux and Windows ship with a compatible SQLite already.
2. Set up your editor (automatic)
bunx mimirs init --ide claude # or: cursor, windsurf, copilot, jetbrains, allThis creates the MCP server config, editor rules, .mimirs/config.json, and .gitignore entry. Run with --ide all to set up every supported editor at once.
init covers Claude Code, Cursor, Windsurf, Copilot, and JetBrains (Junie). For everything else — Codex, Zed, custom clients — copy one of the snippets below.
3. Set up your editor (manual reference)
The mimirs MCP server runs over stdio. Every client needs the same three things: a command (bunx), args (["mimirs@latest", "serve"]), and a RAG_PROJECT_DIR env var pointing at your project root.
{
"mcpServers": {
"mimirs": {
"command": "bunx",
"args": ["mimirs@latest", "serve"],
"env": {
"RAG_PROJECT_DIR": "/absolute/path/to/your/project"
}
}
}
}{
"mcpServers": {
"mimirs": {
"command": "bunx",
"args": ["mimirs@latest", "serve"],
"env": {
"RAG_PROJECT_DIR": "/absolute/path/to/your/project"
}
}
}
}Windsurf reads MCP servers from your home directory, not the project. JetBrains plugin variant uses ~/.codeium/mcp_config.json.
{
"mcpServers": {
"mimirs": {
"command": "bunx",
"args": ["mimirs@latest", "serve"],
"env": {
"RAG_PROJECT_DIR": "/absolute/path/to/your/project"
}
}
}
}{
"mcpServers": {
"mimirs": {
"command": "bunx",
"args": ["mimirs@latest", "serve"],
"env": {
"RAG_PROJECT_DIR": "/absolute/path/to/your/project"
}
}
}
}Codex uses TOML, not JSON, and reads from ~/.codex/config.toml. One block per project — pick a unique table name if you wire up multiple repos (mimirs-frontend, mimirs-api, etc).
[mcp_servers.mimirs]
command = "bunx"
args = ["mimirs@latest", "serve"]
env = { RAG_PROJECT_DIR = "/absolute/path/to/your/project" }Or, equivalently, with an expanded env table:
[mcp_servers.mimirs]
command = "bunx"
args = ["mimirs@latest", "serve"]
[mcp_servers.mimirs.env]
RAG_PROJECT_DIR = "/absolute/path/to/your/project"If the project lives in a read-only mount, set RAG_DB_DIR to a writable location. The index lives there instead of <project>/.mimirs/.
{
"mcpServers": {
"mimirs": {
"command": "bunx",
"args": ["mimirs@latest", "serve"],
"env": {
"RAG_PROJECT_DIR": "/read/only/project",
"RAG_DB_DIR": "/home/me/.cache/mimirs/myproject"
}
}
}
}4. First index
The MCP server indexes lazily on the first query, so once it's wired up you can just ask your agent something. To force a full index up front (useful for large repos):
bunx mimirs index # current directory
bunx mimirs status # how many files, chunks, embeddings5. Try the demo (optional)
bunx mimirs demoSearch quality
90–98% Recall@10. Benchmarked on four real codebases across three languages (120 queries total) — from 97 files to 8,553 — with known expected results per query. Full methodology in BENCHMARKS.md.
| Codebase | Language | Files | Queries | Recall@10 | MRR | Zero-miss | |---|---|---|---|---|---|---| | mimirs | TypeScript | 97 | 30 | 98.3% | 0.683 | 0.0% | | Excalidraw | TypeScript | 693 | 30 | 96.7% | 0.442 | 3.3% | | Django | Python | 3,090 | 30 | 93.3% | 0.688 | 6.7% | | Kubernetes | Go | 8,553 | 30 | 90.0% | 0.589 | 10.0% |
Kubernetes excludes test files and demotes generated files. With searchTopK: 15, recall reaches 100%. See Kubernetes benchmarks for details.
How it compares
| | mimirs | No tool (grep + Read) | Context stuffing | Cloud RAG services | |---|---|---|---|---| | Setup | One command | Nothing | Nothing | API keys, accounts | | Token cost | ~91K/prompt | ~380K/prompt | Entire codebase | Varies | | Search quality | 90–98% Recall@10 | Depends on keywords | N/A (everything loaded) | Varies | | Code understanding | AST-aware (24 langs) | Line-level | None | Usually line-level | | Cross-session memory | Conversations + checkpoints | None | None | Some | | Privacy | Fully local | Local | Local | Data leaves your machine | | Price | Free | Free | High token bills | $10-50/mo + tokens |
Why not an existing tool?
- Continue.dev's
@codebase— closest overlap (local RAG, open source), but retrieval lives inside the editor extension. Mimirs is a standalone MCP server with explicit tools (search,read_relevant,project_map,search_conversation,annotate) the agent can plan around, plus conversation tailing and a wiki generator built in. - Aider's repo-map — static tree-sitter summary of the repo, no embeddings. Clever and lightweight, but a summary isn't retrieval — mimirs ranks chunks per query with vector + BM25 and boosts by graph centrality.
- Sourcegraph Cody / OpenCtx — excellent at code search, but indexing leans on cloud infra and an account. Mimirs is one
bunxaway and never leaves your machine. - llama-index / LangChain / roll-your-own — those are libraries. Mimirs is batteries-included: AST-aware chunking, hybrid retrieval, file watcher, conversation tail, and annotations already wired together.
How it works
Parse & chunk — Splits content using type-matched strategies: function/class boundaries for code (via tree-sitter across 24 languages), headings for markdown, top-level keys for YAML/JSON. Chunks that exceed the embedding model's token limit are windowed and merged.
Embed — Each chunk becomes a 384-dimensional vector using all-MiniLM-L6-v2 (in-process via Transformers.js + ONNX, no API calls). Vectors are stored in sqlite-vec.
Build dependency graph — Import specifiers and exported symbols are captured during AST chunking, then resolved to build a file-level dependency graph.
Hybrid search — Queries run vector similarity and BM25 in parallel, blended by configurable weight. Results are boosted by dependency graph centrality and path heuristics.
read_relevantreturns individual chunks with entity names and exact line ranges (path:start-end).Watch & re-index — File changes are detected with a 2-second debounce. Changed files are re-indexed; deleted files are pruned.
Conversation & checkpoints — Tails Claude Code's JSONL transcripts in real time. Agents can create checkpoints at important moments for future sessions to search.
Annotations — Notes attached to files or symbols surface as
[NOTE]blocks inline inread_relevantresults.Analytics — Every query is logged. Analytics surface zero-result queries, low-relevance queries, and period-over-period trends.
Supported languages
AST-aware chunking via bun-chunk with tree-sitter grammars:
TypeScript/JavaScript, Python, Go, Rust, Java, C, C++, C#, Ruby, PHP, Scala, Kotlin, Lua, Zig, Elixir, Haskell, OCaml, Dart, Bash/Zsh, TOML, YAML, HTML, CSS/SCSS/LESS
Also indexes: Markdown, JSON, XML, SQL, GraphQL, Protobuf, Terraform, Dockerfiles, Makefiles, and more. Files without a known extension fall back to paragraph splitting.
Documentation
- Example tool outputs — what your agent actually receives over MCP
- MCP tools, CLI & analytics
- Configuration & examples
- Benchmarks
Stack
| Layer | Choice |
|---|---|
| Runtime | Bun (built-in SQLite, fast TS) |
| AST chunking | bun-chunk — tree-sitter grammars for 24 languages |
| Embeddings | Transformers.js + ONNX (in-process, no daemon) |
| Embedding model | all-MiniLM-L6-v2 (~23MB, 384 dimensions) — configurable |
| Vector store | sqlite-vec (single .db file) |
| MCP | @modelcontextprotocol/sdk (stdio transport) |
| Plugin | Claude Code plugin with skills + hooks |
All data lives in .mimirs/ inside your project — add it to .gitignore.
