Code Intelligence
Everything below is backed by lib-code (structural parsing, chunking, search, edit/diff intelligence, metrics) and, for the retrieval loop, lib-code + lib-ai (embeddings + vector store). These are the same calls a long-running service (e.g. AI Knowledge) will make — the CLI just lowers the barrier to using them today.
What it does (and doesn’t)
Section titled “What it does (and doesn’t)”lib-code answers questions about code structure and performs structural transformations. It parses with tree-sitter (multi-language, no toolchain, resilient to broken code), chunks at structural boundaries, finds symbols and references, searches by structure, interprets diffs, and measures point-in-time metrics.
It does not run your code, manage git, persist anything, or judge behavior. The CLI walks the filesystem and the vector store persists — lib-code itself is a pure, stateless engine.
Turn a file into the structural model — units (functions/methods/classes/…), imports, symbols, and parse-error nodes for broken code.
kis code parse src/chunk/chunk.gokis code parse server.py --json | jq '.units[].name'cat snippet.ts | kis code parse - # read from stdinfile: src/chunk/chunk.golanguage: go (confidence=exact)imports: 4 symbols: 21 units: 21 parse-errors: 0units: function Chunk L23-29 exported struct Chunker L33-33 exported method Chunk L41-52 exported ...Broken/half-typed files still parse to a partial model (with parse-errors > 0
and confidence=low) — never a crash. An unrecognized extension degrades to
plain text (confidence=low, no units), still chunkable.
Symbols / outline
Section titled “Symbols / outline”A depth-annotated symbol tree for a file (the editor breadcrumb data).
kis code symbols src/parse/extract.gokis code outline server.java --json # `outline` is an alias for `symbols`The load-bearing capability. Structure-driven chunks — never split a unit mid-body, each kept with its signature/doc and carrying enclosing scope + relevant imports. This is exactly what you embed for retrieval.
kis code chunk src/chunk # a whole directorykis code chunk server.go --show # print each chunk's contentkis code chunk server.go --strategy hierarchical --jsonStrategies (-s / --strategy):
unit(default) — one chunk per structural unit, kept whole.unit-grouped— pack small adjacent units up to a token target.hierarchical— a class/module “header” chunk + per-method child chunks.sliding-structural— split an oversized unit at safe boundaries (flagged).
--max-tokens N sets the oversized-unit threshold (a unit over it falls back to
a flagged sliding split, shown as [split k/n]).
Search
Section titled “Search”Find code by structure, not text — what grep can’t do (it won’t match a
name inside a comment or string, and it understands kinds/scopes).
# all functions/methods whose name matches a globkis code search ./src --kind function --name 'Handle*'
# all call-sites of a functionkis code search ./src --calls dangerousFn
# anything expressible as a tree-sitter query (full power)kis code search ./src --raw '(type_spec name:(type_identifier) @n type:(struct_type)) @struct'2 matches src/chunk/chunk.go:23-29 Chunk func Chunk(ctx context.Context, … src/chunk/chunk.go:41-52 Chunker.Chunk func (c *Chunker) Chunk(ctx …--kind: function|method|class|struct|interface|enum. Add --json for the
full matches with captures. (Plain text grep is the agent’s job — run grep
directly; kis code search is for when the structure is the query.)
Metrics
Section titled “Metrics”Point-in-time structural facts: complexity, nesting, fan-out, and call/dependency graph shape. (Over-time drift is a service’s job — this is the present-tense substrate it composes.)
kis code metrics ./src/parsekis code metrics ./service --json | jq '.aggregates.cyclomatic'files: 6 units: 79 lines: 1354unit lines: mean 14.8 p90 35 max 82cyclomatic: mean 3.9 p90 9 max 16call graph: nodes 56 edges 88 maxdepth 8 cycles 3 (approx=true)Fetch the exact code behind a result — by unit name or line range. This is how a retrieval hit (which carries provenance) is resolved back to source.
kis code read src/chunk/sliding.go --unit emitSliding # whole unit + its dockis code read src/chunk/chunk.go --lines 23:29 # exact lineskis code read server.go # no selector → outlineRAG over code
Section titled “RAG over code”The end-to-end loop: chunk → embed → store → search → read.
kis code index kis code retrieve source ───────────────────► vectors + content ──────────────────────► ranked hits (lib-code chunk) (embed) (vector store) (embed query, search) │ ▼ kis code read (exact code)1) Index — chunk, embed, store
Section titled “1) Index — chunk, embed, store”# Offline quick start: no model, no DB. Snapshot the index to a JSON file.kis code index ./src --save idx.jsonindexed 665 chunks from 67 files embedder: local-hash(dim=256) (dim=256) store: memory collection=code snapshot: idx.json (use: kis code retrieve <q> --load idx.json)2) Retrieve — semantic search
Section titled “2) Retrieve — semantic search”kis code retrieve "how are oversized units split into windows" --load idx.json -k 3query: "how are oversized units split into windows" (3 hits, embedder=local-hash(dim=256))
[1] score=0.36 src/chunk/sliding.go:24-46 method builder.emitSliding // emitSliding splits a single oversized unit at safe internal line boundaries… → read: kis code read src/chunk/sliding.go --lines 24:46Add --show to print each hit’s full content, or --json for {id, score, content, metadata} records.
3) Read — resolve a hit to exact code
Section titled “3) Read — resolve a hit to exact code”kis code read src/chunk/sliding.go --lines 24:46Rules that matter
Section titled “Rules that matter”- Same embedder for index and retrieve. Vectors must come from the same
embedder to be comparable: keep
--provider/--modelidentical (or, for the local embedder, the same--dim). Mismatched embedders → meaningless scores. - Same store (or snapshot) for both. Use the same
--storeDSN onindexandretrieve. The defaultmemorystore lives for one process only, so for the index-then-query flow either (a)--save idx.jsonon index and--load idx.jsonon retrieve, or (b) use a persistent backend (below) with the same DSN on both. - Same
--collectionon both (defaultcode). - The local embedder is lexical — good for proving the loop and for tests/CI, weaker on paraphrase. Switch to a real provider for quality.
Embedders
Section titled “Embedders”index and retrieve pick the embedder with the same flags as kis ai embed:
--provider | Needs | Notes |
|---|---|---|
local (default) | nothing | built-in feature-hashing embedder; offline, deterministic, lexical. --dim sets size (default 256). |
ollama | a running ollama | e.g. --model nomic-embed-text; no key |
openai | OPENAI_API_KEY | e.g. --model text-embedding-3-small |
gemini / cohere / vllm / tei / gateway (AI Gateway) | provider/key | same resolution as kis ai embed |
Key resolution: --api-key → provider env var (OPENAI_API_KEY, …). Local
engines (ollama, vllm, tei, local) need no key.
# real semantic embeddingskis code index ./pkg --provider openaikis code retrieve "validate edits before writing" --provider openaiVector stores
Section titled “Vector stores”The store is lib-ai/vector (backend-agnostic), picked by --store:
--store | Backend | Notes |
|---|---|---|
memory (default) | in-process | lives for ONE command — pair with --save/--load for index-then-query |
pgvector://user:pass@host:5432/db?sslmode=disable | Postgres + pgvector | production-shaped, shared, persistent |
duckdb:///abs/path.db | DuckDB file | serverless single file, HNSW-indexed; absolute path, three slashes (only in the kis.ai build, which ships with DuckDB) |
qdrant://host:6333 | Qdrant | remote |
chroma://host:8000 | Chroma | remote |
Persistent recipe (same DSN on both steps; no snapshot needed):
kis code index ./pkg --provider openai --store "pgvector://user:pass@localhost:5432/codebase?sslmode=disable"kis code retrieve "…" --provider openai --store "pgvector://user:pass@localhost:5432/codebase?sslmode=disable"Re-running index upserts by chunk id (file#start-end), so re-indexing
replaces changed chunks.
Scripting & JSON
Section titled “Scripting & JSON”- stdout = the result, stderr = diagnostics — pipes stay clean.
--json/-jis onparse,chunk,symbols,search,metrics,retrieve— prefer it for machine consumption.- Non-zero exit on failure.
# functions over 80 lines, as JSONkis code metrics ./svc --json | jq '.aggregates.unit_lines.max'
# every exported function name in a packagekis code search ./pkg --kind function --json | jq -r '.[].unit.name'
# top hit's file:lines for a query, then read itloc=$(kis code retrieve "auth middleware" --load idx.json -k1 --json \ | jq -r '.[0].metadata | "\(.file) \(.start_line):\(.end_line)"')kis code read ${loc% *} --lines ${loc#* }Languages
Section titled “Languages”25 languages, detected by extension/content: Go, Python, JavaScript,
TypeScript/TSX, Java, C, C++, C#, Rust, Ruby, PHP, Kotlin, Swift, Scala, Bash,
SQL, HTML, CSS, YAML, TOML, CUE, HCL. The directory walk skips .git,
node_modules, vendor, dist, build, target, hidden dirs, and files a
language doesn’t claim (binaries) or that exceed --max-file-bytes.
From CLI to a service
Section titled “From CLI to a service”What you run here is the production path minus the service wrapper. A retrieval
service (AI Knowledge) makes the same calls: code.ChunkFile for ingestion,
embed.Embedder for vectors, vector.Store (pgvector) for storage,
and the same query path for search — adding tenancy (CPET scoping), scheduling,
an API, and incremental re-index on top. Prototype with kis code, then lift
the same composition into the block.
Defaults appendix
Section titled “Defaults appendix”- chunk: strategy
unit, doc kept with the unit, imports + enclosing signature carried. - index:
--store memory,--collection code,--strategy unit,--provider local,--dim 256,--max-file-bytes 1048576. - retrieve:
--store memory,--collection code,--top/-k 5,--provider local,--dim 256. - read: no selector prints the file outline;
--unit/-uprints a unit (with its doc);--lines/-L A:Bprints a 1-based inclusive range. - Environment: provider keys (
OPENAI_API_KEY, …) for real embedders;NO_COLORto disable any styling. - Tip: the offline
localembedder makes the whole RAG loop runnable with zero setup — ideal for demos, tests, and CI; switch--providerfor real quality.