____ ____ ______ _____ ____ ____
/\ _`\ /\ _`\ /\__ _\ /'\_/`\/\ __`\/\ _`\ /\ _`\
\ \ \L\_\ \ \L\ \/_/\ \/ /\ \ \ \/\ \ \ \L\ \ \ \L\_\
\ \ \L_L\ \ , / \ \ \ \ \ \__\ \ \ \ \ \ \ , /\ \ _\L
\ \ \/, \ \ \\ \ \_\ \__\ \ \_/\ \ \ \_\ \ \ \\ \\ \ \L\ \
\ \____/\ \_\ \_\/\_____\\ \_\\ \_\ \_____\ \_\ \_\ \____/
\/___/ \/_/\/ /\/_____/ \/_/ \/_/\/_____/\/_/\/ /\/___/
An automated knowledge engine for your document vault
Grimore watches your vault — Markdown, PDF, EPUB, DOCX, ODT, RTF, HTML, TXT — auto-tags every document, builds a hybrid semantic index, and answers questions against it. Entirely through local LLMs. Nothing leaves your machine, and no API keys are required.
One sweep over a mixed-format vault. Preflight verifies every adapter; watchdog keeps the index live thereafter.
Type a question, the Oracle streams back an answer with citations into your own notes.
![]() |
![]() |
Categories and tags discovered automatically by the cognition pipeline — explore them from the shell.
![]() |
![]() |
Live counters, chosen models, daemon state — all from inside the shell.
![]() |
![]() |
/help lists every slash-command at the prompt — no doc-diving required.
Requires Python 3.11+, Ollama with a chat model (e.g. qwen2.5:3b) and an embedding model (e.g. nomic-embed-text) pulled, and a git-initialised vault.
git clone https://github.com/kahz12/Grimore-MD.git
cd Grimore-MD
python -m venv .venv && source .venv/bin/activate
pip install -e .
cp grimore.toml.example grimore.toml # then set [vault].path
grimore preflight # validate config + adapters
grimore scan --no-dry-run # first full pass
grimore daemon start # keep the index live
grimore shell # conversational modegrimore.toml is yours and is not tracked — grimore.toml.example is the
annotated template, and every key in it is optional bar [vault].path. Note
that [output].dry_run ships on: a scan writes tags, summaries and
categories into your notes' frontmatter, so the first run shows you what it
would change and nothing else.
Supported on Linux, Windows, and Termux/Android (heavy engines like PyMuPDF / OCR stay opt-in to keep the mobile install lean).
ask can be pointed at part of the vault instead of all of it:
grimore ask "retention policy?" --category infra # and its descendants
grimore ask "retention policy?" --tag compliance --tag security
grimore ask "what do the PDFs say?" --format pdfFilters combine with AND, repeated --tag included, and restrict what is
searched at all — so the Oracle can only cite from what survives them. The same
narrowing is available on POST /api/search as category / tags / formats.
| Surface | What it does |
|---|---|
grimore mcp |
Stdio MCP server for Claude Desktop / Cursor / Zed. See docs/mcp-setup.md. |
grimore serve |
Read-only HTTP API + minimal browser UI. Loopback by default; --allow-lan + --api-token for LAN. |
grimore graph export |
Dump the vault's link graph to JSON, Graphviz DOT, or Obsidian Canvas. |
--profile <name> |
Switch between named vault profiles defined as [profiles.<name>] in grimore.toml. |
/thread save|resume|list |
Persist shell conversations as JSONL under ~/.grimore/threads and resume them across sessions. |
| OpenAI-compatible backend | Point Grimore at llama.cpp server, vLLM, LM Studio, OpenRouter or OpenAI by setting [cognition].llm_backend = "openai". |
graph TD
A["Document Vault<br/>md · pdf · epub · docx · odt · rtf · html · txt"] -->|watchdog| B["Adapter dispatch<br/>extension → extractor"]
B -->|file_hash + content_hash| C{"Changed?"}
C -->|no| Z["Skip"]
C -->|yes| D["Git Guard snapshot"]
D --> E["Cognition<br/>tags · category · summary<br/>section-aware chunks · vectors"]
E --> F[("SQLite<br/>WAL + FTS5<br/>+ page/heading anchors")]
F --> G["Sidecar writer<br/>(non-MD) / inline (MD)"]
G --> A
F --> H["Oracle RAG<br/>BM25 + cosine → RRF"]
H --> I["CLI / Shell"]
- Ingest — one adapter per format behind a registry. Two-tier change detection: cheap SHA-256 of the bytes gates the expensive extraction step, so re-scans of unchanged documents cost nothing.
- Cognition — local LLM tags, summarises and files each document into one hierarchical category. Section-aware chunking preserves PDF page numbers and DOCX/EPUB headings so citations come back as
[[Title#p.42]]. - Memory — SQLite in WAL mode with FTS5 alongside per-chunk vectors keyed by
sha256(model ‖ chunk), so swapping embedders invalidates cleanly. - Retrieval — BM25 and cosine fused via Reciprocal Rank Fusion. Degrades to either side alone if the other is unavailable.
- Writeback — Markdown sources get inline frontmatter + a
## Suggested Connectionsblock. Binary formats (PDF, EPUB, DOCX, ODT) get a sidecar.mdunder.grimore/sidecars/— originals are never mutated.
Local-first by construction: with cognition.allow_remote = false (the default), LLM calls are rejected unless the endpoint resolves to a loopback address — and the connection is pinned to that validated IP so DNS can't rebind it mid-request. Every destructive operation defaults to --dry-run. PII detection, prompt-injection neutralisation (note content and client-supplied conversation history), hardened XML parsing for office/EPUB documents (entity-expansion DoS defence), constant-time and brute-force-throttled API-token checks on every /api/* route (with --strict-token to require the token even from localhost — recommended on Android, where apps share the loopback interface), automatic git snapshots, and path containment via SecurityGuard round out the safety model — see the user guide for the full picture.
- 🇬🇧 English User Guide — every command, the shell, configuration, troubleshooting.
- 🇪🇸 Guía de Usuario (Español) — recorrido completo en español.
Terminal: grimore <cmd> --help. In the shell: /help.
Python 3.11+ · Ollama · SQLite (WAL + FTS5) · Typer + Rich · prompt-toolkit · pypdf · beautifulsoup4 · striprtf · watchdog · structlog · GitPython
Released under the MIT License.







