
QMD
FreeEfficient local search for your personal knowledge base.
Free · Opens the source repo
What QMD does
QMD is a powerful local search engine designed specifically for personal knowledge management. It enables users to index and search through markdown notes, meeting transcripts, documentation, and any text-based files stored on their devices. By combining traditional keyword matching with advanced semantic understanding and LLM-powered reranking, QMD provides a hybrid search experience that enhances the retrieval of relevant information. This tool is particularly useful for those who maintain extensive collections of text documents and need a reliable way to find specific content quickly.
The setup process for QMD is straightforward, requiring Node.js and SQLite with extension support for optimal performance. Once installed, users can create collections of their documents, add context metadata to improve search relevance, and generate vector embeddings to enhance the search capabilities. QMD supports multiple search modes, including fast keyword searches for exact terms, semantic vector searches for natural language queries, and hybrid searches that leverage all available models for the best results.
Developers, researchers, and anyone who deals with large amounts of text data will find QMD invaluable. It is particularly beneficial for those looking to establish a local knowledge base without relying on cloud services, ensuring that sensitive information remains private and secure. The tool's flexibility allows for structured multi-mode queries, making it adaptable to various search needs and scenarios.
Overall, QMD stands out as an efficient solution for anyone needing to manage and search through their personal knowledge bases effectively. Its local operation, combined with advanced search capabilities, makes it a compelling choice for enhancing productivity and information retrieval.
When to use it
Use QMD when you need to search through markdown notes, documentation, or meeting transcripts on your device, especially when semantic understanding is important.
When not to use it
QMD may not be suitable for users who require cloud-based search solutions or need to search across multiple devices simultaneously.
What you can build with it
Searching Meeting Transcripts
Quickly find specific discussions or action items from your meeting notes by searching through indexed transcripts.
Retrieving Documentation
Efficiently locate technical documentation or project notes without sifting through multiple files manually.
Creating a Personal Knowledge Base
Set up a local knowledge base to manage and search your personal notes and ideas, enhancing your productivity.
How to install QMD
View source1. Install with the skills CLI
npx skills add nousresearch/hermes-agent/qmd --agent claude-code2. Or install it manually
Download the skill folder and drop it into ~/.claude/skills/ for all projects, or .claude/skills/ to scope it to one repo. Restart Claude Code so it picks up the new skill.
Anthropic's agentic coding CLI, and the reference implementation of Agent Skills. Drop a skill folder into ~/.claude/skills and Claude Code loads it automatically whenever a task matches the skill's description. Claude Code docs
Inside SKILL.md
Written by nousresearchQMD — Query Markup Documents
Local, on-device search engine for personal knowledge bases. Indexes markdown notes, meeting transcripts, documentation, and any text-based files, then provides hybrid search combining keyword matching, semantic understanding, and LLM-powered reranking — all running locally with no cloud dependencies.
Created by Tobi Lütke. MIT licensed.
When to Use
- User asks to search their notes, docs, knowledge base, or meeting transcripts
- User wants to find something across a large collection of markdown/text files
- User wants semantic search ("find notes about X concept") not just keyword grep
- User has already set up qmd collections and wants to query them
- User asks to set up a local knowledge base or document search system
- Keywords: "search my notes", "find in my docs", "knowledge base", "qmd"
Prerequisites
Node.js >= 22 (required)
# Check version
node --version # must be >= 22
# macOS — install or upgrade via Homebrew
brew install node@22
# Linux — use NodeSource or nvm
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejs
# or with nvm:
nvm install 22 && nvm use 22
SQLite with Extension Support (macOS only)
macOS system SQLite lacks extension loading. Install via Homebrew:
brew install sqlite
Install qmd
npm install -g @tobilu/qmd
# or with Bun:
bun install -g @tobilu/qmd
First run auto-downloads 3 local GGUF models (~2GB total):
| Model | Purpose | Size |
|---|---|---|
| embeddinggemma-300M-Q8_0 | Vector embeddings | ~300MB |
| qwen3-reranker-0.6b-q8_0 | Result reranking | ~640MB |
| qmd-query-expansion-1.7B | Query expansion | ~1.1GB |
Verify Installation
qmd --version
qmd status
Quick Reference
| Command | What It Does | Speed |
|---|---|---|
qmd search "query" | BM25 keyword search (no models) | ~0.2s |
qmd vsearch "query" | Semantic vector search (1 model) | ~3s |
qmd query "query" | Hybrid + reranking (all 3 models) | ~2-3s warm, ~19s cold |
qmd get <docid> | Retrieve full document content | instant |
qmd multi-get "glob" | Retrieve multiple files | instant |
qmd collection add <path> --name <n> | Add a directory as a collection | instant |
qmd context add <path> "description" | Add context metadata to improve retrieval | instant |
qmd embed | Generate/update vector embeddings | varies |
qmd status | Show index health and collection info | instant |
qmd mcp | Start MCP server (stdio) | persistent |
qmd mcp --http --daemon | Start MCP server (HTTP, warm models) | persistent |
Setup Workflow
1. Add Collections
Point qmd at directories containing your documents:
# Add a notes directory
qmd collection add ~/notes --name notes
# Add project docs
qmd collection add ~/projects/myproject/docs --name project-docs
# Add meeting transcripts
qmd collection add ~/meetings --name meetings
# List all collections
qmd collection list
2. Add Context Descriptions
Context metadata helps the search engine understand what each collection contains. This significantly improves retrieval quality:
qmd context add qmd://notes "Personal notes, ideas, and journal entries"
qmd context add qmd://project-docs "Technical documentation for the main project"
qmd context add qmd://meetings "Meeting transcripts and action items from team syncs"
3. Generate Embeddings
qmd embed
This processes all documents in all collections and generates vector embeddings. Re-run after adding new documents or collections.
4. Verify
qmd status # shows index health, collection stats, model info
Search Patterns
Fast Keyword Search (BM25)
Best for: exact terms, code identifiers, names, known phrases. No models loaded — near-instant results.
qmd search "authentication middleware"
qmd search "handleError async"
Semantic Vector Search
Best for: natural language questions, conceptual queries. Loads embedding model (~3s first query).
qmd vsearch "how does the rate limiter handle burst traffic"
qmd vsearch "ideas for improving onboarding flow"
Hybrid Search with Reranking (Best Quality)
Best for: important queries where quality matters most. Uses all 3 models — query expansion, parallel BM25+vector, reranking.
qmd query "what decisions were made about the database migration"
Structured Multi-Mode Queries
Combine different search types in a single query for precision:
# BM25 for exact term + vector for concept
qmd query $'lex: rate limiter\nvec: how does throttling work under load'
# With query expansion
qmd query $'expand: database migration plan\nlex: "schema change"'
Query Syntax (lex/BM25 mode)
| Syntax | Effect | Example |
|---|---|---|
term | Prefix match | perf matches "performance" |
"phrase" | Exact phrase | "rate limiter" |
-term | Exclude term | performance -sports |
HyDE (Hypothetical Document Embeddings)
For complex topics, write what you expect the answer to look like:
qmd query $'hyde: The migration plan involves three phases. First, we add the new columns without dropping the old ones. Then we backfill data. Finally we cut over and remove legacy columns.'
Scoping to Collections
qmd search "query" --collection notes
qmd query "query" --collection project-docs
Output Formats
qmd search "query" --json # JSON output (best for parsing)
qmd search "query" --limit 5 # Limit results
qmd get "#abc123" # Get by document ID
qmd get "path/to/file.md" # Get by file path
qmd get "file.md:50" -l 100 # Get specific line range
qmd multi-get "journals/*.md" --json # Batch retrieve by glob
MCP Integration (Recommended)
qmd exposes an MCP server that provides search tools directly to Hermes Agent via the native MCP client. This is the preferred integration — once configured, the agent gets qmd tools automatically without needing to load this skill.
Option A: Stdio Mode (Simple)
Add to ~/.hermes/config.yaml:
mcp_servers:
qmd:
command: "qmd"
args: ["mcp"]
timeout: 30
connect_timeout: 45
This registers tools: mcp_qmd_search, mcp_qmd_vsearch,
mcp_qmd_deep_search, mcp_qmd_get, mcp_qmd_status.
Tradeoff: Models load on first search call (~19s cold start), then stay warm for the session. Acceptable for occasional use.
Option B: HTTP Daemon Mode (Fast, Recommended for Heavy Use)
Start the qmd daemon separately — it keeps models warm in memory:
# Start daemon (persists across agent restarts)
qmd mcp --http --daemon
# Runs on http://localhost:8181 by default
Then configure Hermes Agent to connect via HTTP:
mcp_servers:
qmd:
url: "http://localhost:8181/mcp"
timeout: 30
Tradeoff: Uses ~2GB RAM while running, but every query is fast (~2-3s). Best for users who search frequently.
Keeping the Daemon Running
macOS (launchd)
cat > ~/Library/LaunchAgents/com.qmd.daemon.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.qmd.daemon</string>
<key>ProgramArguments</key>
<array>
<string>qmd</string>
<string>mcp</string>
<string>--http</string>
<string>--daemon</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/qmd-daemon.log</string>
<key>StandardErrorPath</key>
<string>/tmp/qmd-daemon.log</string>
</dict>
</plist>
EOF
launchctl load ~/Library/LaunchAgents/com.qmd.daemon.plist
Linux (systemd user service)
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/qmd-daemon.service << 'EOF'
[Unit]
Description=QMD MCP Daemon
After=network.target
[Service]
ExecStart=qmd mcp --http --daemon
Restart=on-failure
RestartSec=10
Environment=PATH=/usr/local/bin:/usr/bin:/bin
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable --now qmd-daemon
systemctl --user status qmd-daemon
MCP Tools Reference
Once connected, these tools are available as mcp_qmd_*:
| MCP Tool | Maps To | Description |
|---|---|---|
mcp_qmd_search | qmd search | BM25 keyword search |
mcp_qmd_vsearch | qmd vsearch | Semantic vector search |
mcp_qmd_deep_search | qmd query | Hybrid search + reranking |
mcp_qmd_get | qmd get | Retrieve document by ID or path |
mcp_qmd_status | qmd status | Index health and stats |
The MCP tools accept structured JSON queries for multi-mode search:
{
"searches": [
{"type": "lex", "query": "authentication middleware"},
{"type": "vec", "query": "how user login is verified"}
],
"collections": ["project-docs"],
"limit": 10
}
CLI Usage (Without MCP)
When MCP is not configured, use qmd directly via terminal:
terminal(command="qmd query 'what was decided about the API redesign' --json", timeout=30)
For setup and management tasks, always use terminal:
terminal(command="qmd collection add ~/Documents/notes --name notes")
terminal(command="qmd context add qmd://notes 'Personal research notes and ideas'")
terminal(command="qmd embed")
terminal(command="qmd status")
How the Search Pipeline Works
Understanding the internals helps choose the right search mode:
- Query Expansion — A fine-tuned 1.7B model generates 2 alternative queries. The original gets 2x weight in fusion.
- Parallel Retrieval — BM25 (SQLite FTS5) and vector search run simultaneously across all query variants.
- RRF Fusion — Reciprocal Rank Fusion (k=60) merges results. Top-rank bonus: #1 gets +0.05, #2-3 get +0.02.
- LLM Reranking — qwen3-reranker scores top 30 candidates (0.0-1.0).
- Position-Aware Blending — Ranks 1-3: 75% retrieval / 25% reranker. Ranks 4-10: 60/40. Ranks 11+: 40/60 (trusts reranker more for long tail).
Smart Chunking: Documents are split at natural break points (headings, code blocks, blank lines) targeting ~900 tokens with 15% overlap. Code blocks are never split mid-block.
Best Practices
- Always add context descriptions —
qmd context adddramatically improves retrieval accuracy. Describe what each collection contains. - Re-embed after adding documents —
qmd embedmust be re-run when new files are added to collections. - Use
qmd searchfor speed — when you need fast keyword lookup (code identifiers, exact names), BM25 is instant and needs no models. - Use
qmd queryfor quality — when the question is conceptual or the user needs the best possible results, use hybrid search. - Prefer MCP integration — once configured, the agent gets native tools without needing to load this skill each time.
- Daemon mode for frequent users — if the user searches their knowledge base regularly, recommend the HTTP daemon setup.
- First query in structured search gets 2x weight — put the most important/certain query first when combining lex and vec.
Troubleshooting
"Models downloading on first run"
Normal — qmd auto-downloads ~2GB of GGUF models on first use. This is a one-time operation.
Cold start latency (~19s)
This happens when models aren't loaded in memory. Solutions:
- Use HTTP daemon mode (
qmd mcp --http --daemon) to keep warm - Use
qmd search(BM25 only) when models aren't needed - MCP stdio mode loads models on first search, stays warm for session
macOS: "unable to load extension"
Install Homebrew SQLite: brew install sqlite
Then ensure it's on PATH before system SQLite.
"No collections found"
Run qmd collection add <path> --name <name> to add directories,
then qmd embed to index them.
Embedding model override (CJK/multilingual)
Set QMD_EMBED_MODEL environment variable for non-English content:
export QMD_EMBED_MODEL="your-multilingual-model"
Data Storage
- Index & vectors:
~/.cache/qmd/index.sqlite - Models: Auto-downloaded to local cache on first run
- No cloud dependencies — everything runs locally
References
Frequently asked questions about QMD
Similar skills
Slidev
Create interactive web-based presentations with Markdown.
Axiom
Audit your assumptions for clearer decision-making.
2slides Presentation Generation
Generate professional presentations with AI.
Performance Review Writer
Draft personalized performance reviews effortlessly.
Legal Team Briefing
Generate contextual briefings for legal workflows.
Search
Efficiently find documents and discussions across connected sources.
