QMD Semantic Search

pending

by Oleksii Chekulaiev

Semantic-first search for your vault using QMD (Quick Markdown Search). Provides vector-based semantic search with keyword fallback.

24 starsUpdated 2mo agoMITDiscovered via Obsidian Unofficial Plugins
View on GitHub

QMD Semantic Search for Obsidian

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.

Features

  • 100% Local - No API keys, no cloud services, no remote LLMs. Your notes never leave your machine
  • Semantic Search - Find notes by meaning, not just keywords. Ask questions like "notes about productivity" or "ideas related to machine learning"
  • Automatic Fallback - Gracefully falls back to keyword (BM25) search when semantic search is unavailable
  • Automatic Indexing & Embedding - Keeps your vault indexed and embedded in the background as you create and edit notes
  • Responsive Search - 1-second debounce waits for you to stop typing, with animated progress indicator
  • Cancellable - Typing while searching cancels the previous search immediately
  • Native UX - Search modal and optional sidebar pane follow Obsidian design patterns
  • Desktop Only - Requires filesystem access (macOS, Windows, Linux)

Prerequisites

Install QMD

This plugin requires QMD to be installed on your system. QMD is a standalone CLI tool for semantic markdown search that runs entirely locally.

System Requirements

  • Bun >= 1.0.0 - Required runtime for QMD
  • Disk space: ~300MB for embedding model (this plugin only uses search and vsearch)
  • Network: Internet connection required for first-time model download

Installation

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:

  1. Install Bun from bun.sh
  2. Run: bun install -g https://github.com/tobi/qmd

Verify installation:

qmd --version

First-Time Model Download

When you first use QMD, it automatically downloads AI models from HuggingFace:

ModelPurposeSizeWhen Downloaded
embeddinggemma-300M-Q8_0Vector embeddings~300MBFirst embed
qwen3-reranker-0.6b-q8_0Re-ranking~640MBFirst query
Qwen3-1.7B-Q8_0Query expansion~2.2GBFirst 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.

Installation

From Obsidian Community Plugins

  1. Open Obsidian Settings → Community Plugins
  2. Browse and search for "QMD Semantic Search"
  3. Install and enable the plugin

Manual Installation

  1. Download the latest release (main.js, manifest.json, styles.css)
  2. Create a folder obsidian-qmd in your vault's .obsidian/plugins/ directory
  3. Copy the downloaded files into this folder
  4. Enable the plugin in Obsidian Settings → Community Plugins

Development Installation

# 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

Getting Started

1. First-Time Setup

After enabling the plugin, it will automatically:

  1. Create a QMD collection for your vault
  2. Build an initial keyword index

2. Embeddings for Semantic Search

Semantic search requires AI embeddings. By default, embeddings are generated automatically when the plugin detects they're missing.

On first run:

  • QMD downloads ~300MB embedding model (one-time)
  • Generates embeddings for all markdown files (may take a few minutes for large vaults)
  • Shows a notice when complete

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".

3. Start Searching

  • Command Palette: Run "QMD: Search"
  • Ribbon Icon: Click the search icon in the left sidebar (if enabled)
  • Keyboard Shortcut: Assign a hotkey in Settings → Hotkeys

How It Works

Semantic-First Philosophy

This plugin prioritizes semantic (AI/vector) search over traditional keyword search:

  1. Primary: Semantic search using qmd vsearch
  2. Fallback: Keyword (BM25) search using qmd search

When you search:

  1. The plugin waits 1 second after you stop typing (debounce)
  2. An animated progress bar appears below the search input
  3. Semantic search is attempted first
  4. If semantic search fails (no embeddings, error, or optionally zero results), it falls back to keyword search
  5. A subtle notice indicates when fallback is used

Tip: If you start typing again while a search is running, the previous search is cancelled immediately.

Search Modes

ModeDescriptionWhen Used
SemanticAI-powered meaning-based searchDefault, when embeddings exist
KeywordTraditional BM25 text matchingFallback, or when explicitly selected

Configuration

Access settings via Obsidian Settings → QMD Semantic Search

Core Settings

SettingDescriptionDefault
QMD Binary PathPath to QMD executableqmd
Collection NameQMD collection name(derived from vault name)
Index NameOptional QMD index override(none)
File MaskGlob pattern for files to index**/*.md

Indexing

SettingDescriptionDefault
Debounce DelayWait time after changes before indexing45 seconds
Periodic UpdatesEnable timed index updatesOn
Update IntervalMinutes between periodic updates15

Search Behavior

SettingDescriptionDefault
Default Search ModePrimary search methodSemantic
Fallback on FailureUse keyword if semantic failsOn
Fallback on Zero ResultsUse keyword if no semantic resultsOff
Show Embeddings BannerNotify when embeddings missingOn
Auto-generate EmbeddingsGenerate embeddings automaticallyOn

User Interface

SettingDescriptionDefault
Ribbon IconShow search icon in sidebarOn
Search PaneEnable persistent sidebar paneOff
Show ScoresDisplay relevance scoresOn

Commands

CommandDescription
QMD: SearchOpen the search modal
QMD: Open Search PaneOpen search in sidebar (if enabled)
QMD: Update Index NowManually trigger index update
QMD: Generate EmbeddingsBuild AI embeddings
QMD: Force Rebuild EmbeddingsRebuild all embeddings from scratch
QMD: Ensure CollectionCreate collection if missing

Troubleshooting

"QMD binary not found"

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.

First-time embedding fails

If embedding generation fails on first run:

  1. Check internet connection - Models must be downloaded from HuggingFace
  2. Check disk space - Need ~300MB free for embedding model
  3. macOS users - Ensure Homebrew SQLite is installed: brew install sqlite
  4. Check Bun installation - Run bun --version to verify Bun is installed
  5. Try manually - Run qmd embed in terminal to see detailed errors

"Semantic search unavailable"

This means embeddings haven't been generated. Either:

  • Wait for auto-generation to complete (check for notice)
  • Manually run "QMD: Generate Embeddings"
  • Check Settings → Diagnostics for errors

Embedding generation is slow

First-time embedding involves:

  1. Downloading ~300MB embedding model (one-time)
  2. Processing all markdown files in your vault

For large vaults (1000+ files), this can take 5-10 minutes. Subsequent runs are faster.

Search is slow

  • Large vaults may take time to search
  • Consider reducing the file mask to index fewer files
  • Ensure QMD has enough system resources

Index seems outdated

  • Run "QMD: Update Index Now"
  • Check that the debounce delay isn't too long
  • Verify file watching is working (check vault events)

Desktop Only

This plugin requires direct filesystem access and only works on:

  • macOS
  • Windows
  • Linux

Mobile platforms (iOS/Android) are not supported as they don't provide direct filesystem access to Obsidian plugins.

Development

Project Structure

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

Scripts

# 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

Testing

# Run all tests
npm test

# Watch mode
npm run test:watch

# With coverage report
npm run test:coverage

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run tests and linting
  5. Submit a pull request

License

MIT License - see LICENSE for details.

Credits

  • QMD by Tobi Lütke - The underlying search engine
  • Obsidian - The incredible knowledge base app

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.