Index and search
Uploading files puts bytes in the knowledgebase tree. Search uses the index, which updates when you sync (and as background processing runs). After ingest or deletes, sync and wait until the knowledgebase is searchable before expecting new results.
Status
kobold-cli index status -kb kb_qc0rp0gz
GET /v1/knowledgebases/kb_qc0rp0gz/status
Authorization: Bearer <api_key>
Example fields you will see:
| Field | Meaning |
|---|---|
id |
Knowledgebase id |
status |
pending, checking, digesting, halted, error, or complete |
statusInfo |
Human-readable progress or error detail |
indexedHash / filesystemHash |
Digests used to detect drift between index and files |
fileCount / vectorCount |
How much is indexed |
files |
Per-path indexing progress (path, indexed, vectorCount, …) |
A brand-new knowledgebase may report pending with empty files until the first sync/index run.
Sync
Ask for an immediate sync check: compare the file tree to the last indexed state and enqueue work for changes.
kobold-cli index sync -kb kb_qc0rp0gz
POST /v1/knowledgebases/kb_qc0rp0gz/sync
Authorization: Bearer <api_key>
No request body. Acceptance is asynchronous. A successful accept looks like:
{
"accepted": true,
"status": "checking",
"statusInfo": "sync accepted"
}
HTTP status is 202. The CLI prints the JSON body.
You can accept at most one sync per knowledgebase per second. Faster repeats → 429. Poll index status until status is complete (or handle error / halted).
Recommended flow after uploads:
kobold-cli files ingest -kb kb_qc0rp0gz -file ./doc.md
kobold-cli index sync -kb kb_qc0rp0gz
# poll until ready
kobold-cli index status -kb kb_qc0rp0gz
kobold-cli search query -kb kb_qc0rp0gz -query "…"
Search
kobold-cli search query -kb kb_qc0rp0gz -query "how does billing work"
kobold-cli search query -kb kb_qc0rp0gz -query "how does billing work" -mode sparse -limit 10
kobold-cli search query -kb kb_qc0rp0gz -query "how does billing work" -mode full -byte-length 512
POST /v1/knowledgebases/kb_qc0rp0gz/search
Authorization: Bearer <api_key>
Content-Type: application/json
{
"query": "how does billing work",
"limit": 10,
"minScore": 0.0,
"mode": "sparse",
"byteLength": 512
}
| Field | Required | Notes |
|---|---|---|
query |
yes | Non-empty search string |
limit |
no | Max hits; default 10, max 100 |
minScore |
no | Drop hits below this score; default 0 |
mode |
no | sparse (default) or full |
byteLength |
for full |
Bytes of snippet per hit; 1–1024 |
Sparse mode (default)
Each hit is a coordinate map—no file body:
{
"hits": [
{
"path": "docs/billing.md",
"byteStart": 1024,
"byteEnd": 2048,
"score": 0.87,
"kind": "chunk"
}
]
}
Use these ranges with files content if you want exact bytes.
Full mode
Same fields, plus a short hydrated snippet starting at byteStart:
{
"path": "docs/billing.md",
"byteStart": 1024,
"byteEnd": 2048,
"score": 0.87,
"kind": "chunk",
"content": "Billing is invoiced monthly…",
"contentBytes": 512
}
Snippet length is at most byteLength, and never more than 1024 bytes per hit. Search never returns a whole file; use files content for larger reads.
In the CLI, -mode full without -byte-length defaults to 512.
If a snippet is not valid UTF-8, the API may return base64 in content with "encoding": "base64".
When search works
| Situation | Result |
|---|---|
Index complete |
Searchable |
checking / digesting with existing vectors |
Searchable (may be slightly stale vs in-flight work) |
pending / halted / error, or checking/digesting with zero vectors |
409 — not searchable yet |
| Searchable but nothing matches | 200 with "hits": [] |
Invalid query/mode/byteLength → 400.