# qmd qmd (Quick Markdown Search) is a local, on-device search engine for personal knowledge management. It indexes markdown files, meeting transcripts, documentation, and other text-based content stored across multiple collections on your computer. It combines BM25 full-text search, vector semantic search, and LLM re-ranking—all running locally. ## Key Features ### Search Modes - `search`: Fast BM25 keyword matching - `vsearch`: Semantic similarity via embeddings - `query`: Hybrid approach with query expansion and intelligent re-ranking ### Collection Management - Index multiple directories as named collections - Filter searches within specific collections - Add contextual descriptions to help search understand content ### Output Flexibility Supports multiple output formats: JSON (ideal for AI agents), CSV, markdown, and XML. Results can be displayed with line numbers, full content, or snippets. ### MCP Integration qmd exposes a Model Context Protocol server, making it accessible to Claude Desktop and Claude Code. #### Configuration for Claude Desktop Location: `~/Library/Application Support/Claude/claude_desktop_config.json` ```json { "mcpServers": { "qmd": { "command": "qmd", "args": ["mcp"] } } } ``` #### Configuration for Claude Code Location: `~/.claude/settings.json` ```json { "mcpServers": { "qmd": { "command": "qmd", "args": ["mcp"] } } } ``` #### Available MCP Tools - `qmd_search`: Fast BM25 keyword search with optional collection filtering - `qmd_vsearch`: Semantic vector search supporting collection filters - `qmd_query`: Hybrid search combining retrieval and re-ranking - `qmd_get`: Document retrieval by path or docid (includes fuzzy matching suggestions) - `qmd_multi_get`: Batch document retrieval via glob patterns, lists, or docids - `qmd_status`: Provides index health metrics and collection information ## Technical Architecture ### Search Pipeline The hybrid `query` command uses Reciprocal Rank Fusion (RRF) to combine results from multiple search strategies: - Query expansion using a local 1.7B parameter model - Parallel full-text and vector index searches - Position-aware score blending - Re-ranking using a local reranker model ### Models Used - embedding-gemma-300M (vector embeddings, ~300MB) - qwen3-reranker-0.6b (re-ranking, ~640MB) - Qwen3-1.7B (query expansion, ~2.2GB) All models run locally via node-llama-cpp using GGUF format and are automatically downloaded on first use. ### Data Storage The index lives in `~/.cache/qmd/index.sqlite`. The database includes tables for documents, full-text indexes, vector embeddings, and cached LLM responses. ## Installation & Setup Requires Bun (≥1.0.0). macOS users need Homebrew SQLite for extension support. ```bash bun install -g https://github.com/tobi/qmd ``` ## Usage Examples ### Basic workflow ```bash qmd collection add ~/notes --name notes --mask "**/*.md" qmd context add qmd://notes "Personal Knowledge Base" qmd embed qmd query "pkm" ``` Add qmd mcp to claude: `claude mcp add qmd qmd mcp` ### Advanced retrieval - Fetch by document path: `qmd get notes/meeting.md` - Fetch by auto-generated ID: `qmd get "#abc123"` - Retrieve multiple files: `qmd multi-get "journals/2025-05*.md"` - Export for agents: `qmd search "API" --json --all` ## Score Interpretation Results range from 0.0-1.0: - Above 0.8: High relevance - 0.5-0.8: Moderate relevance - Below 0.2: Low relevance ## Tips - Create embeddings using the CPU: `alias qmd='NODE_LLAMA_CPP_GPU=false qmd embed'` - Exclude noise directories from a collection with an `ignore` list in `~/.config/qmd/index.yml`. This field is **not** shown in `qmd --help` or `qmd collection show`, but it is supported per collection: ```yaml collections: notes: path: /path/to/vault pattern: "**/*.md" ignore: - "**/.stversions/**" # Syncthing version archive - "**/.obsidian/**" - "**/.smart-env/**" # Smart Connections cache ``` qmd's `update` walker `scandir`s every subdirectory regardless of `pattern` (the pattern only filters results, it does not prune traversal). So an unreadable directory — e.g. a corrupt file inside a cloud-synced folder — crashes `qmd update` with an `EIO: i/o error, scandir ...`. The `ignore` patterns are passed to fastGlob's `ignore` option, which prunes those directories from the walk entirely — fixing the crash and noticeably speeding up indexing. ## References - https://github.com/tobi/qmd ## Related - [[Model Context Protocol (MCP)]] - [[Obsidian]] - [[Personal Knowledge Management (PKM)]]