Skip to content

v1.3.0

Choose a tag to compare

@github-actions github-actions released this 26 Jul 03:02

ken v1.3.0 — cold-start campaign

ken-mcp no longer rebuilds the index from scratch on every launch.

Warm search in ken was always fast (tens of ms). The rough edge was cold
start — every IDE restart re-walked, re-chunked, re-parsed, and re-embedded the
whole repo before serving a single query. This release makes cold start a
one-time cost, not a per-launch tax, and adds opt-in modes that serve a first
query almost immediately on a true-cold index.

Motivated by #61.


The headline (on by default)

Persistent index snapshots + reconcile-on-boot. ken-mcp now persists the
built index to <repo>/.ken/ and, on restart, loads it and drift-scans
(config-key + per-file mtime/size) instead of rebuilding when the repo hasn't
changed. Edit a few files and restart? It reconciles only the changed files
rather than the whole tree.

Time to a servable first query — yii2 PHP corpus (~12k chunks), hybrid, M1 Pro, median of 3:

scenario before after speedup
restart, repo unchanged 2.39 s 573 ms 4.2×
restart after a 1-file edit 2.39 s 746 ms 3.2×

It's safe by construction: any missing / corrupt / config-mismatched / drifted
snapshot silently falls back to a normal live build, and both on-disk loaders
are fuzzed against hostile input. .ken/ is a plain cache — delete it anytime;
add it to your .gitignore. Turn the whole thing off with KEN_MCP_SNAPSHOT=0.
(This is separate from, and coexists with, the ADR-024 operator prebuilt
.ken/index.bin.)

Serve-before-warm (opt-in)

For the first-ever index of a repo — where there's no snapshot to load yet —
three opt-in knobs move the expensive work off the first query:

env var what it does
KEN_MCP_STAGED=1 Serve BM25 lexical results instantly on a cold hybrid build (~4.2× faster first query), then embed to full hybrid in the background. Responses carry "semantic":"warming" until the upgrade lands.
KEN_MCP_LAZY_ENRICH=1 Defer the structural-enrichment tree-sitter parse off the cold path (serve raw, enrich in the background).
KEN_MCP_EMBED_CACHE=1 Persistent sha256(chunk)→vector cache at <repo>/.ken/embed.db, so a full rebuild re-embeds only never-seen text.

Also new:

  • ken index --write-snapshot — build once and persist, so a later
    ken-mcp launch on that repo loads instead of rebuilds (CI prewarming).
  • Lazy structural indexken-mcp defers the symbol index for the
    definition/references/callers/outline/symbols tools to first use,
    removing a redundant full-corpus parse from every cold start.
  • KEN_ENRICH_FILE_BUDGET_MS — a per-file wall-clock parse budget that
    skips (and logs) a pathological template-like file the size cap misses.

Honest notes

  • All numbers above are M1 Pro (10-core / 16 GB). The speedups should port,
    but absolute times won't hold on a 4-core laptop — so the serve-before-warm
    modes ship off by default until we've measured them on that hardware
    class. If you run ken on a constrained machine, try KEN_MCP_STAGED=1 and let
    us know how it lands.
  • Why "take the parse off the cold path" rather than "make it faster": the
    gotreesitter 0.20.5 → 0.47.0 bump we shipped in 1.1.1 (a correctness fix)
    regressed the PHP tree-sitter parse ~2.7×, and that parse is ~50% of cold
    index time. Details + the upstream data point are in the repo docs.
  • Index throughput and warm-search latency are unchanged — the opt-in modes are
    off by default, and the default index path is untouched.

Install / upgrade

brew upgrade ken            # Homebrew
scoop update ken            # Scoop
go install github.com/townsendmerino/ken/cmd/ken@v1.3.0
go install github.com/townsendmerino/ken/cmd/ken-mcp@v1.3.0

No config changes needed — snapshots turn on automatically. Full details in
CHANGELOG.md.