Skip to content
Talk to our solutions team

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.

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.

Terminal window
kis code parse src/chunk/chunk.go
kis code parse server.py --json | jq '.units[].name'
cat snippet.ts | kis code parse - # read from stdin
file: src/chunk/chunk.go
language: go (confidence=exact)
imports: 4 symbols: 21 units: 21 parse-errors: 0
units:
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.

A depth-annotated symbol tree for a file (the editor breadcrumb data).

Terminal window
kis code symbols src/parse/extract.go
kis 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.

Terminal window
kis code chunk src/chunk # a whole directory
kis code chunk server.go --show # print each chunk's content
kis code chunk server.go --strategy hierarchical --json

Strategies (-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]).

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).

Terminal window
# all functions/methods whose name matches a glob
kis code search ./src --kind function --name 'Handle*'
# all call-sites of a function
kis 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.)

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.)

Terminal window
kis code metrics ./src/parse
kis code metrics ./service --json | jq '.aggregates.cyclomatic'
files: 6 units: 79 lines: 1354
unit lines: mean 14.8 p90 35 max 82
cyclomatic: mean 3.9 p90 9 max 16
call 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.

Terminal window
kis code read src/chunk/sliding.go --unit emitSliding # whole unit + its doc
kis code read src/chunk/chunk.go --lines 23:29 # exact lines
kis code read server.go # no selector → outline

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)
Terminal window
# Offline quick start: no model, no DB. Snapshot the index to a JSON file.
kis code index ./src --save idx.json
indexed 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)
Terminal window
kis code retrieve "how are oversized units split into windows" --load idx.json -k 3
query: "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:46

Add --show to print each hit’s full content, or --json for {id, score, content, metadata} records.

Terminal window
kis code read src/chunk/sliding.go --lines 24:46
  • Same embedder for index and retrieve. Vectors must come from the same embedder to be comparable: keep --provider/--model identical (or, for the local embedder, the same --dim). Mismatched embedders → meaningless scores.
  • Same store (or snapshot) for both. Use the same --store DSN on index and retrieve. The default memory store lives for one process only, so for the index-then-query flow either (a) --save idx.json on index and --load idx.json on retrieve, or (b) use a persistent backend (below) with the same DSN on both.
  • Same --collection on both (default code).
  • The local embedder is lexical — good for proving the loop and for tests/CI, weaker on paraphrase. Switch to a real provider for quality.

index and retrieve pick the embedder with the same flags as kis ai embed:

--providerNeedsNotes
local (default)nothingbuilt-in feature-hashing embedder; offline, deterministic, lexical. --dim sets size (default 256).
ollamaa running ollamae.g. --model nomic-embed-text; no key
openaiOPENAI_API_KEYe.g. --model text-embedding-3-small
gemini / cohere / vllm / tei / gateway (AI Gateway)provider/keysame resolution as kis ai embed

Key resolution: --api-key → provider env var (OPENAI_API_KEY, …). Local engines (ollama, vllm, tei, local) need no key.

Terminal window
# real semantic embeddings
kis code index ./pkg --provider openai
kis code retrieve "validate edits before writing" --provider openai

The store is lib-ai/vector (backend-agnostic), picked by --store:

--storeBackendNotes
memory (default)in-processlives for ONE command — pair with --save/--load for index-then-query
pgvector://user:pass@host:5432/db?sslmode=disablePostgres + pgvectorproduction-shaped, shared, persistent
duckdb:///abs/path.dbDuckDB fileserverless single file, HNSW-indexed; absolute path, three slashes (only in the kis.ai build, which ships with DuckDB)
qdrant://host:6333Qdrantremote
chroma://host:8000Chromaremote

Persistent recipe (same DSN on both steps; no snapshot needed):

Terminal window
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.

  • stdout = the result, stderr = diagnostics — pipes stay clean.
  • --json / -j is on parse, chunk, symbols, search, metrics, retrieve — prefer it for machine consumption.
  • Non-zero exit on failure.
Terminal window
# functions over 80 lines, as JSON
kis code metrics ./svc --json | jq '.aggregates.unit_lines.max'
# every exported function name in a package
kis code search ./pkg --kind function --json | jq -r '.[].unit.name'
# top hit's file:lines for a query, then read it
loc=$(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#* }

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.

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.

  • 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/-u prints a unit (with its doc); --lines/-L A:B prints a 1-based inclusive range.
  • Environment: provider keys (OPENAI_API_KEY, …) for real embedders; NO_COLOR to disable any styling.
  • Tip: the offline local embedder makes the whole RAG loop runnable with zero setup — ideal for demos, tests, and CI; switch --provider for real quality.