kiwifs reindex without touching your data.
Choose an engine
Set the engine with a flag or in config. The flag wins when both are set.DQL, computed views, trust ranking, and stale-page detection read the SQLite index. With
--search grep, those endpoints return 501.Tier 1: grep
A pure-Go line scanner with no index. Matching is a case-insensitive substring match, line by line, over every.md file outside hidden directories. Each file contributes at most 20 matching lines.
Tier 2: SQLite FTS5
BM25-ranked full-text search. KiwiFS keeps the index in.kiwi/state/search.db and updates it on every write.
Query syntax
Plain words are matched as separate terms, and a page must contain all of them. KiwiFS passes your query to FTS5 unchanged as soon as it contains an uppercase operator or one of the characters", (, ), *, ^, or :.
Lowercase
and, or, and not are ordinary words. If a query is not valid FTS5, KiwiFS retries it as a list of quoted terms instead of failing.
When a search returns nothing, the response can include suggestions: page titles within a small edit distance of your query.
Trust ranking
The default search applies a soft trust boost from frontmatter. Pages withstatus: verified, source-of-truth: true, or a high confidence move up. Pages with status: deprecated or status: outdated move down. No result is removed. Pass boost=none to rank by BM25 alone.
GET /api/kiwi/search/verified uses much stronger multipliers, so verified and source-of-truth pages dominate and deprecated pages sink to the bottom.
Filters
What the index leaves out
Search stores what a reader would want to find, not every byte of the file.- Quiz answer keys. Each Kiwi Quiz callout is reduced to its question. Correct answers, accepted answers, and feedback never reach the index or a search snippet.
- Widget fence data. Typed widget fences such as
array,matrix, orgraphare reduced to their captions, step notes, and a short sample of labels. Coordinates and styling keys stay out, so diagrams do not crowd out prose in BM25 ranking.
Tier 3: vector search
Semantic search embeds each page in chunks and finds the chunks nearest to your query. Turn it on in.kiwi/config.toml. Both an embedder and a store are required.
.kiwi/config.toml
kiwifs reindex. Add --vector to make the command fail if the vector index cannot be built.
Embedders
Vector stores
Chunks default to 1,500 characters with 150 characters of overlap. See Configuration for chunk size, context templates, and every embedder field.
Hybrid search
Hybrid mode runs BM25 and vector search, then fuses the two ranked lists with Reciprocal Rank Fusion (RRF). Pages that both engines rank highly rise to the top.Terminal
fts_rank, semantic_rank, and the fused score. The response lists the engines that contributed. Without a vector index, hybrid still returns 200 and engines contains only fts. Tune fusion with rrf_k (default 60); smaller values let one engine’s top hit dominate.
Context packs
POST /api/kiwi/brief turns a question into one token-budgeted pack. It runs hybrid retrieval and includes each page whole when it fits, or its best-matching sections when it does not. It never summarizes. Anything that did not fit is listed with its token cost, so you can raise the budget or ask for it by name.
Terminal
Measure retrieval quality
kiwifs eval scores FTS, semantic, and hybrid retrieval against a golden set in .kiwi/eval/. A set is a pair of TREC files: <name>.qrels for relevance judgements and <name>.topics for the queries. Metrics are hit rate, MRR, precision, and nDCG at a rank cutoff.
Terminal
--exclude-prefix hides a subtree before ranking, which keeps held-out evaluation honest. A --min-hit-rate, --min-mrr, or --min-ndcg threshold makes the command exit non-zero when it is missed, so you can gate CI on it. Over HTTP, call POST /api/kiwi/eval.
Interfaces
- REST
- MCP
- CLI
Related
Search API
Parameters and response fields for every search endpoint.
DQL
Query frontmatter instead of text.
Ollama vector search
Run semantic search fully locally.
Configuration
Every
[search] key and default.