| name | qi-cli |
| description | Guide for using qi, a local knowledge search CLI for macOS and Linux. Use this skill whenever the user asks about qi commands, indexing documents, searching a knowledge base, asking questions with RAG, configuring providers (Ollama, OpenAI), understanding search modes (BM25, hybrid, vector), or anything related to the qi tool. Triggers on phrases like "qi index", "qi search", "qi ask", "qi query", "how do I use qi", "set up qi", "configure qi", "search my notes with qi", or any mention of the qi CLI. |
qi is a local-first knowledge search CLI. It indexes documents into SQLite and supports BM25 full-text search, vector/hybrid search (with a local or remote embedding provider), and LLM-powered Q&A with citations.
Quick Start
qi init
$EDITOR ~/.config/qi/config.yaml
qi index
qi doctor
qi search "your query"
qi query "your semantic question"
qi ask "what does X do?"
Command selection guidance
Prefer qi index when the task is about adding, refreshing, or organizing source material.
Prefer qi search or qi query when the task is about finding relevant documents, passages, or citations.
Use qi ask sparingly, only when the user specifically needs a synthesized answer from an LLM rather than retrieved source results.
Commands
qi init
Writes ~/.config/qi/config.yaml (if absent) and initializes the SQLite database.
qi init
qi index [path|collection]
Indexes documents. SHA-256 content hashing means unchanged files are skipped. Embeddings are generated at index time — if you add an embedding provider to config after an initial index run, re-run qi index to populate the missing embeddings.
qi index
qi index ~/notes
qi index notes
qi search <query>
BM25 full-text search. Fast, offline, no provider needed.
qi search "authentication"
qi search "deploy" -c code -n 5
qi query <query>
Semantic/hybrid search. Falls back gracefully to BM25 if the embedding provider is unavailable.
qi query "how does auth work"
qi query "deploy pipeline" --mode lexical
qi query "deployment steps" --mode hybrid
qi query "critical path" --mode deep
qi query "question" --explain
Modes:
lexical — BM25 only
hybrid (default) — BM25 + vector fused with RRF; skips vector if BM25 has a clear winner
deep — hybrid + optional reranking pass
qi ask <question>
RAG Q&A: searches the knowledge base, sends relevant chunks to an LLM, returns an answer with citations.
Use this sparingly; prefer qi query for normal exploration, evidence gathering, and source lookup.
qi ask "What authentication methods are supported?"
qi ask "Explain the chunking algorithm" -c code
Requires a generation provider in config.
qi get <id>
Retrieve a document by its 6-character hash prefix (shown in search results).
qi get abc123
qi list
List all collections defined in config (name and path).
qi list
qi delete <collection>
Delete a collection: removes all indexed data from the database and removes the collection entry from config. Irreversible.
qi delete notes
qi stats
Show document counts, chunk counts, embedding counts, and database size per collection. If Embeddings count is much lower than Chunks count, vector search has no data to work with — re-run qi index.
qi doctor
Health-check config, database, collection paths, and provider connectivity. If the embedding provider shows SKIP instead of OK, qi query will silently fall back to BM25 regardless of your config.
qi update
Update the binary from GitHub. If installed via Homebrew, it suggests brew upgrade qi instead.
Global Flags
| Flag | Description |
|---|
-v, --verbose | Verbose/debug output |
-f, --format text|json|markdown | Output format (default: text) |
--config <path> | Override config path |
-c, --collection <name> | Limit to a specific collection |
-n, --limit <N> | Number of results (default: 10) |
Configuration (~/.config/qi/config.yaml)
database_path: ~/.local/share/qi/qi.db
collections:
- name: notes
path: ~/notes
extensions: [.md, .txt]
ignore: [.git]
- name: code
path: ~/Projects/myproject
extensions: [.go, .ts, .py]
ignore: [vendor, dist]
providers:
embedding:
base_url: http://localhost:11434
model: nomic-embed-text
dimension: 768
rerank:
base_url: http://localhost:8080
model: bge-reranker-v2-m3
generation:
base_url: http://localhost:11434
model: llama3.2
api_key: ""
search:
default_mode: hybrid
bm25_top_k: 50
vector_top_k: 50
rerank_top_k: 10
rrf_k: 60
chunk_size: 512
Common provider setups
Ollama (fully local):
providers:
embedding:
base_url: http://localhost:11434
model: nomic-embed-text
dimension: 768
generation:
base_url: http://localhost:11434
model: llama3.2
OpenAI:
providers:
embedding:
base_url: https://api.openai.com/v1
model: text-embedding-3-small
dimension: 1536
generation:
base_url: https://api.openai.com/v1
model: gpt-4o
api_key: sk-...
Mixed (local embeddings, cloud generation):
providers:
embedding:
base_url: http://localhost:11434
model: nomic-embed-text
dimension: 768
generation:
base_url: https://api.openai.com/v1
model: gpt-4o
api_key: sk-...
How search works
- BM25 — SQLite FTS5. Always available, very fast, good for keyword queries.
- Vector KNN — Cosine similarity over embedding BLOBs in SQLite. Requires an embedding provider. Captures semantic intent.
- Hybrid (RRF) — Runs both, fuses rankings with Reciprocal Rank Fusion (
score = Σ 1/(k + rank)). Skips vector if BM25 has a dominant winner (top score > 3× second place).
- Deep — Hybrid + a second-pass reranker for best accuracy.
Document references
Search results show locations like qi://notes/2024/jan.md [Section > Subsection] and a 6-character ID. Use qi get <id> to view the full document.
Typical workflows
Index and search (no provider needed):
qi init
qi index ~/notes
qi search "my keyword" -c notes
Manage collections:
qi list
qi index ~/projects
qi delete old-notes
Semantic search with Ollama:
qi index notes
qi query "how does X work" --explain
RAG Q&A (use sparingly):
qi ask "Summarize the key decisions in my notes"
Debug / inspect:
qi doctor
qi stats
qi query "question" --explain
qi get abc123
Troubleshooting
qi query returns keyword-only results despite embedding provider being configured
Work through these steps in order:
1. Check if the provider is actually wired up
qi doctor
Look for OK next to the embedding provider. SKIP means qi didn't parse the provider config — common causes: wrong YAML key name (embedding not embeddings), missing dimension field, or bad indentation (must be under providers:).
2. Check if embeddings were actually generated
qi stats
If Embeddings is 0 or far less than Chunks, the vectors were never written. This happens when the embedding provider was added to config after the initial qi index run — re-index to fix it:
qi index <collection-name>
Only chunks missing embeddings are re-processed; unchanged files aren't re-parsed.
3. Verify the provider is reachable at query time
qi query embeds the query string at runtime. If the provider is down, qi silently falls back to BM25 without an error. Test connectivity:
curl http://localhost:11434/v1/embeddings -H "Content-Type: application/json" \
-d '{"model":"nomic-embed-text","input":["test"]}'
Also confirm the model is pulled: ollama list.
4. Use --explain to see what's actually happening
qi query "your question" --explain
This shows each result's BM25 rank, vector rank, and fused RRF score. If every result is missing a vector rank, the vector path isn't contributing — confirming one of the issues above.
Note: hybrid mode also skips vector search if the top BM25 score is more than 3× the second result (intentional optimization for dominant keyword matches). If your queries are exact keyword matches, try a more paraphrased, natural-language query to avoid this shortcut.