Basic query
docmancer query "How do I set up authentication?"
Returns a compact Markdown context pack with source attribution and a token-savings line.
Retrieval modes
docmancer query "auth setup" --mode lexical
docmancer query "auth setup" --mode dense
docmancer query "auth setup" --mode sparse
docmancer query "auth setup" --mode hybrid
| Mode | What it does |
|---|---|
lexical | SQLite FTS5 with BM25. Best for exact API names, flags, config keys, error strings. The default for bare configs. |
dense | FastEmbed bge-base-en-v1.5 vectors in Qdrant. Catches semantic neighbours ("login" matches "sign in"). |
sparse | SPLADE vectors in Qdrant. Splits the difference between lexical exactness and dense recall. |
hybrid | Fans out across all three in parallel and fuses ranks with Reciprocal Rank Fusion. Auto-selected when vector_store: is configured. |
Explain mode
docmancer query "auth setup" --mode hybrid --explain
Annotates each result with the per-source rank that contributed:
[lexical#1, dense#3, sparse#2] Authentication > OAuth 2.0 > Scopes
Useful for tuning router rules or diagnosing why a hit ranked the way it did.
Control output size
Set a token budget:
docmancer query "auth setup" --budget 2000
Default is 2400 tokens. You can also cap the number of sections:
docmancer query "auth setup" --limit 5
Expand context
Include adjacent sections around matches:
docmancer query "auth setup" --expand
Or include the full page content within the budget:
docmancer query "auth setup" --expand page
JSON output
docmancer query "auth setup" --format json
Useful for piping into other tools.
How it works under the hood
query dispatches through the retrieval dispatcher, which runs the selected mode against the SQLite FTS5 index, the Qdrant dense collection, and the Qdrant sparse collection in a thread pool, then fuses ranks with RRF.
Two extensions ride on top:
- Hierarchical retrieval runs a wide-net first pass, picks the top-N documents by aggregated score, then re-retrieves sections filtered to those documents. Auto-enabled when the index has at least 10 distinct documents.
- Query routers match the question against an ordered list of regex patterns and merge filters into the dispatcher call (e.g. route "billing" queries to a specific docset). See Router recipes.
The lexical-only mode bypasses the dispatcher and reads SQLite directly, so router rules only fire under dense, sparse, or hybrid.
When to skip vectors
If you want pure FTS5 (no embeddings, no Qdrant), set:
DOCMANCER_AUTO_VECTORS=0 docmancer ingest ./docs
Or for a single ingest:
docmancer ingest ./docs --no-vectors
The index remains queryable in --mode lexical.