Ask your Obsidian vault, get cited answers, never hallucinate.
Project description
vault-ask
Ask your Obsidian vault. Get cited answers. Never hallucinate.
A tiny (~300-line, dependency-free) grounded question-answering tool over a folder
of Markdown notes. It finds the relevant notes, asks your LLM to answer only
from them, forces a [[wikilink]] citation on every claim, and refuses instead
of guessing when the answer isn't in your vault.
$ vault-ask "what did I decide about the pricing model?"
Q: what did I decide about the pricing model?
Flat 49 EUR/month, no per-seat pricing, decided after the churn analysis.
[[Decisions/2026-Pricing|2026-Pricing]]
Notes consulted:
- [[Decisions/2026-Pricing|2026-Pricing]]
- [[Meetings/2026-01-pricing-review|2026-01-pricing-review]]
Ask something that isn't in your notes and it won't make anything up:
$ vault-ask "what is my bank account number?"
Q: what is my bank account number?
No note in the vault answers this question.
Why
A second brain is only useful if knowledge comes back out. Most "chat with your
notes" tools either need a vector database and an indexing pipeline, or happily
hallucinate plausible answers — a dealbreaker when your notes are medical, legal,
or financial. vault-ask is the opposite: zero index, zero database, and a hard
refusal guarantee. It runs ripgrep over your vault, ranks notes by term rarity
(TF-IDF), and hands the best excerpts to whatever LLM you already use.
How it works
- Candidate search —
ripgrepscans the whole vault in milliseconds. - IDF ranking — notes are scored by the rarity of the query terms they contain, so a rare, specific word (a project codename) outweighs a word that appears in hundreds of notes. No embeddings, no index, no warm-up.
- Focused excerpts — only the headings and matching lines of the top notes are sent to the model (notes can be long).
- Grounded prompt — the model must cite each claim as a
[[link]], must not add outside knowledge, and must reply with a fixed refusal sentence if the excerpts don't answer the question. - Robust refusal check — a refusal (even reworded by the model) is never dressed up as a sourced answer; its citations are stripped.
Nothing leaves your machine except what your own LLM command chooses to send.
Install
Requires Python 3.9+ and ripgrep
(rg) on your PATH.
# pip (installs the `vault-ask` command)
pip install git+https://github.com/guillaumevele/vault-ask.git
Or run it as a single file, no install:
git clone https://github.com/guillaumevele/vault-ask.git
cd vault-ask
python3 vault_ask.py "your question"
No dependencies beyond the Python standard library and ripgrep.
Configure your LLM
vault-ask shells out to whatever LLM command you set in VAULT_ASK_LLM. The
prompt is piped on stdin by default, or substituted for {prompt} if the
command contains that placeholder.
# Local model via Ollama (prompt on stdin):
export VAULT_ASK_LLM='ollama run llama3.1'
# Simon Willison's `llm` CLI (any provider it supports):
export VAULT_ASK_LLM='llm -m gpt-4o-mini'
# A CLI that takes the prompt as an argument — use the {prompt} placeholder:
export VAULT_ASK_LLM='your-llm-cli --prompt {prompt}'
Point it at your vault once:
export OBSIDIAN_VAULT="$HOME/Obsidian/MyVault"
Usage
vault-ask "what did I decide about X?"
vault-ask --vault ~/notes "when is the contract renewal?"
vault-ask --limit 8 --json "summarize my pricing decisions"
No LLM? Use --sources-only to just rank the most relevant notes — a smart grep
for your vault that needs no model at all:
vault-ask --sources-only "pricing model"
# Most relevant notes for: pricing model
# - [[Decisions/2026-pricing|2026-pricing]]
# - [[Meetings/2026-01-pricing-review|2026-01-pricing-review]]
| Flag | Default | Description |
|---|---|---|
--vault |
$OBSIDIAN_VAULT or . |
path to the vault |
--limit |
5 |
max notes to consult |
--llm |
$VAULT_ASK_LLM |
LLM command (overrides env) |
--sources-only |
off | rank relevant notes, no LLM call |
--json |
off | raw structured output |
--version |
print version |
What it's good at — and what it isn't
Good at: factual lookups where the words of your question point at a note — decisions, numbers, names, "what did I say about …". It's fast and it never lies.
Not good at: abstract questions whose vocabulary differs from your notes (you ask "my funding strategy", the note says "tax credit"). That's the inherent limit of keyword retrieval — proper semantic recall needs embeddings, which this tool deliberately avoids to stay zero-dependency and zero-index. When it can't match, it refuses honestly rather than guessing.
Tests
python3 -m unittest discover -s tests
Related
voice-to-vault is the other
half of the loop: it routes your voice captures into the Obsidian vault that
vault-ask then answers questions about. One files your thoughts, the other
brings them back.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vault_ask-0.1.1.tar.gz.
File metadata
- Download URL: vault_ask-0.1.1.tar.gz
- Upload date:
- Size: 11.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc4722067bb8174ddfa23a870b230901820c655878bb743f20c1f8be8743abea
|
|
| MD5 |
dc7cfcd20ff2d583df654f8dd6384058
|
|
| BLAKE2b-256 |
93f387c46d5e467331b3865e998506a49b9ad2dbf030c961f5f9ca5770508ddd
|
File details
Details for the file vault_ask-0.1.1-py3-none-any.whl.
File metadata
- Download URL: vault_ask-0.1.1-py3-none-any.whl
- Upload date:
- Size: 10.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
81f5b7dbdcbf466bd19266bbc963cbb15648c572beb373e21a37e987318de0ac
|
|
| MD5 |
cfae45f83bcf8c9073f8bb5617602bbe
|
|
| BLAKE2b-256 |
3e1f707e3b632a8f58df21835c18e5c9a68cf0693e8ef0ff183aa38991209ed9
|