achekulaev859 downloadsSemantic-first search for your vault using QMD (Quick Markdown Search). Provides vector-based semantic search with keyword fallback.
A fully local, privacy-first semantic search plugin for Obsidian. Powered by QMD (Quick Markdown Search), it brings AI-powered vector search to your vault without sending a single byte to any cloud service, API, or remote LLM. All embedding generation and search runs entirely on your machine.
This plugin requires QMD to be installed on your system. QMD is a standalone CLI tool for semantic markdown search that runs entirely locally.
search and vsearch)macOS:
# Install Homebrew SQLite (required for QMD extensions)
# If you don't have Homebrew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install sqlite
# Install Bun if needed
curl -fsSL https://bun.sh/install | bash
# Install QMD globally
bun install -g https://github.com/tobi/qmd
Linux:
# Install Bun if needed
curl -fsSL https://bun.sh/install | bash
# Install QMD globally
bun install -g https://github.com/tobi/qmd
Windows:
bun install -g https://github.com/tobi/qmdVerify installation:
qmd --version
When you first use QMD, it automatically downloads AI models from HuggingFace:
| Model | Purpose | Size | When Downloaded |
|---|---|---|---|
| embeddinggemma-300M-Q8_0 | Vector embeddings | ~300MB | First embed |
| qwen3-reranker-0.6b-q8_0 | Re-ranking | ~640MB | First query |
| Qwen3-1.7B-Q8_0 | Query expansion | ~2.2GB | First query |
Models are cached in ~/.cache/qmd/models/ and only downloaded once.
Note: This plugin uses search (keyword) and vsearch (semantic), which only require the embedding model (~300MB). The larger query expansion and reranking models are only needed if you use QMD's query command directly.
main.js, manifest.json, styles.css)obsidian-qmd in your vault's .obsidian/plugins/ directory# Clone the repository
git clone https://github.com/achekulaev/obsidian-qmd.git
cd obsidian-qmd
# Install dependencies
npm install
# Build the plugin
npm run build
# For development with hot reload
npm run dev
After enabling the plugin, it will automatically:
Semantic search requires AI embeddings. By default, embeddings are generated automatically when the plugin detects they're missing.
On first run:
You can disable auto-generation in Settings → QMD Semantic Search → "Auto-generate embeddings".
To manually regenerate embeddings, use Command Palette: "QMD: Generate Embeddings" or "QMD: Force Rebuild Embeddings".
This plugin prioritizes semantic (AI/vector) search over traditional keyword search:
qmd vsearchqmd searchWhen you search:
Tip: If you start typing again while a search is running, the previous search is cancelled immediately.
| Mode | Description | When Used |
|---|---|---|
| Semantic | AI-powered meaning-based search | Default, when embeddings exist |
| Keyword | Traditional BM25 text matching | Fallback, or when explicitly selected |
Access settings via Obsidian Settings → QMD Semantic Search
| Setting | Description | Default |
|---|---|---|
| QMD Binary Path | Path to QMD executable | qmd |
| Collection Name | QMD collection name | (derived from vault name) |
| Index Name | Optional QMD index override | (none) |
| File Mask | Glob pattern for files to index | **/*.md |
| Setting | Description | Default |
|---|---|---|
| Debounce Delay | Wait time after changes before indexing | 45 seconds |
| Periodic Updates | Enable timed index updates | On |
| Update Interval | Minutes between periodic updates | 15 |
| Setting | Description | Default |
|---|---|---|
| Default Search Mode | Primary search method | Semantic |
| Fallback on Failure | Use keyword if semantic fails | On |
| Fallback on Zero Results | Use keyword if no semantic results | Off |
| Show Embeddings Banner | Notify when embeddings missing | On |
| Auto-generate Embeddings | Generate embeddings automatically | On |
| Setting | Description | Default |
|---|---|---|
| Ribbon Icon | Show search icon in sidebar | On |
| Search Pane | Enable persistent sidebar pane | Off |
| Show Scores | Display relevance scores | On |
| Command | Description |
|---|---|
| QMD: Search | Open the search modal |
| QMD: Open Search Pane | Open search in sidebar (if enabled) |
| QMD: Update Index Now | Manually trigger index update |
| QMD: Generate Embeddings | Build AI embeddings |
| QMD: Force Rebuild Embeddings | Rebuild all embeddings from scratch |
| QMD: Ensure Collection | Create collection if missing |
Ensure QMD is installed and accessible from your terminal:
which qmd # macOS/Linux
where qmd # Windows
If QMD is installed but not in PATH, specify the full path in settings.
If embedding generation fails on first run:
brew install sqlitebun --version to verify Bun is installedqmd embed in terminal to see detailed errorsThis means embeddings haven't been generated. Either:
First-time embedding involves:
For large vaults (1000+ files), this can take 5-10 minutes. Subsequent runs are faster.
This plugin requires direct filesystem access and only works on:
Mobile platforms (iOS/Android) are not supported as they don't provide direct filesystem access to Obsidian plugins.
obsidian-qmd/
├── src/
│ ├── main.ts # Plugin entry point
│ ├── settings.ts # Settings types and defaults
│ ├── qmd.ts # QMD CLI wrapper
│ ├── searchModal.ts # Search modal UI
│ ├── searchPane.ts # Sidebar search pane
│ ├── settingsTab.ts # Settings UI
│ └── __mocks__/ # Test mocks
├── manifest.json # Obsidian plugin manifest
├── package.json # Dependencies and scripts
└── tsconfig.json # TypeScript configuration
# Development build with watch
npm run dev
# Production build
npm run build
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Lint code
npm run lint
# Auto-fix lint issues
npm run lint:fix
# Run all tests
npm test
# Watch mode
npm run test:watch
# With coverage report
npm run test:coverage
Contributions are welcome! Please:
MIT License - see LICENSE for details.