npx claudepluginhub itsmostafa/qi --plugin qiThis skill uses the workspace's default tool permissions.
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.
Searches and retrieves markdown documents from local qmd knowledge bases using BM25 keyword, vector semantic, and hybrid LLM-re-ranked search. Use for querying notes, documentation, meeting transcripts.
Indexes and searches local files via CLI using BM25, vector embeddings, hybrid search, and reranking with Ollama. Supports MCP mode and includes security guardrails.
Share bugs, ideas, or general feedback.
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.
qi init # Create config + database
$EDITOR ~/.config/qi/config.yaml # Add collections and (optionally) providers
qi index # Index the current directory, or a named collection
qi doctor # Verify setup
qi search "your query" # BM25 keyword search (no provider needed)
qi query "your semantic question" # Hybrid search (needs embedding provider)
qi ask "what does X do?" # RAG Q&A (needs generation provider)
qi initWrites ~/.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.
qi index # indexes current working directory
qi index ~/notes # any absolute or relative path
qi index notes # named collection from config
# --name saves the directory as a named collection in config, then indexes it
qi index ~/notes --name notes # save + index ~/notes as "notes"
qi index --name notes # save + index current directory as "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 # BM25 only
qi query "deployment steps" --mode hybrid # BM25 + vector (default)
qi query "critical path" --mode deep # hybrid + reranking
qi query "question" --explain # show BM25/vector/RRF score breakdown
Modes:
lexical — BM25 onlyhybrid (default) — BM25 + vector fused with RRF; skips vector if BM25 has a clear winnerdeep — hybrid + optional reranking passqi ask <question>RAG Q&A: searches the knowledge base, sends relevant chunks to an LLM, returns an answer with citations.
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 listList all named collections defined in config (name and path).
qi list
qi delete <collection>Delete a named collection: removes all indexed data from the database and removes the collection entry from config. Irreversible.
qi delete notes
qi statsShow document counts, chunk counts, embedding counts, and database size per collection.
qi doctorHealth-check config, database, collection paths, and provider connectivity.
qi updateUpdate the binary from GitHub. If installed via Homebrew, it suggests brew upgrade qi instead.
| 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) |
~/.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: # optional — enables vector/hybrid search
base_url: http://localhost:11434 # Ollama, LM Studio, llama.cpp, OpenAI-compatible
model: nomic-embed-text
dimension: 768
rerank: # optional — enables deep mode
base_url: http://localhost:8080
model: bge-reranker-v2-m3
generation: # optional — enables `qi ask`
base_url: http://localhost:11434
model: llama3.2
api_key: "" # set for OpenAI or auth-gated services
search:
default_mode: hybrid # lexical | hybrid | deep
bm25_top_k: 50
vector_top_k: 50
rerank_top_k: 10
rrf_k: 60
chunk_size: 512
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-...
score = Σ 1/(k + rank)). Skips vector if BM25 has a dominant winner (top score > 3× second place).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.
Index and search (no provider needed):
qi init
qi index ~/notes --name notes # saves and indexes ~/notes as "notes"
qi search "my keyword" -c notes
Manage named collections:
qi list # see all configured collections
qi index ~/projects --name code # add a new collection
qi delete old-notes # remove collection data + config entry
Semantic search with Ollama:
# pull a model: ollama pull nomic-embed-text
# add embedding provider to config
qi index notes
qi query "how does X work" --explain
RAG Q&A:
# also add a generation provider to config
qi ask "Summarize the key decisions in my notes"
Debug / inspect:
qi doctor # check all providers are reachable
qi stats # see document/chunk/embedding counts
qi query "question" --explain # see score breakdown
qi get abc123 # read the full source document