RFC 001 — Koder Krep (search engine & CLI)
RFC 001 — Koder Krep (search engine & CLI)
*tatus:*DRAFT — initial scoping. Naming *ecided*(
krep, see §10). Module *caffolded*atengines/search/krep/(20260502). 8/10 open questions resolved (§13). Now lives at its permanent home; the file atmeta/docs/stack/rfcs/search-RFC-001-engine-and-cli.kmdis a symlink back here. Promotion to Approved status pending closure of items 9 (/k-benchreference dataset versions — depends on F1 setup).
1. Summary
This RFC proposes *oder Krep*— a modern search engine and CLI for the Koder Stack, a from-scratch replacement for grep and ripgrep (rg) in all our agent loops, developer workflows, and human-facing search experiences (chat transcripts, log triage, code navigation).
The engine is a single library written in *oder Koda (Native AOT)*that exposes search through multiple frontends: a CLI binary (krep), an MCP server, an LSP-style server, an HTTP/gRPC daemon, and bindings for DartGoRust. It supports three orthogonal search modes over the same engine: *ext*(regex/literal), *tructural*(AST per-language), and *ecord*(JSONL, NDJSON, structured logs, chat transcripts).
The non-negotiable success criterion is *erformance parity with rg*in plain-text search, evaluated against a fixed reference benchmark suite per §6, with a *wo-gate progression*that maps directly onto the policies/self-hosted-first.kmd status enum:
- *1 done / opt-in /
status: stable*— geomean ≤ 1.10×rgplusthe structural criteria below. AI may prefer Krep case
bycase. - *efault flip /
status: official*— geomean ≤ 1.05×rg(matchespolicy default for hot-path G2). AI MUST prefer Krep.
The dual gate decouples the engineering finish-line of F1 from the policy threshold for becoming the Stack default — both are real milestones, the first faster, the second binding.
2. Motivation
2.1 What grep and rg get right
ripgrep is the current reference: SIMDoptimized matchers, RE2style regex (no catastrophic backtracking), gitignoreaware walk, multithread by default, sensible UX. It's a ~10yeartuned tool and the rational baseline. For most plain-text needs, it is excellent.
2.2 What we hit constantly that they don't solve
- *ST-aware queries.*"All call sites of
KoderApp(...)" returns matchesinside comments, doc strings, similarly-named functions. We end up filtering by hand.
ast-grepandcombyexist but are not drop-in, not unified across our languages (KL, Dart, Go, Rust), and not integrated with our other tooling.
- *ulti-line as a default.*Finding a TOML block, a JSON value spanning
lines, a function body — all require
(?s)flags, awkward-A 50guesses, or shelling out to a structural tool.
- *earch
andreplace as a first-class operation.*rgdoesn't replace.We pipe through
sedsdxargs, lose preview/dry-run, and have no awareness of "don't replace inside string literals or comments".
- *esult ranking.*
rgreturns matches in walk order. For "where is Xdefined?" we get every mention equally weighted instead of "the one declaration first, the 50 references after".
- *cope
aware context.*`A/-B` with line counts is a guess. We want"the enclosing functionclassblock" — needs a parser, not a buffer.
- *ecord-aware search.*Our agent loops, log pipelines, and chat
transcripts are JSONL/NDJSON. Grep returns line matches, losing record boundaries (turns, log entries, transactions). We re-implement record reconstruction in every tool that consumes search output.
- *erver mode.*Each
rginvocation pays startup + walk cost. In agentloops where Claude Code, Codex, Gemini call grep dozens of times per session, this is dominant overhead. A long-running daemon with a walker cache and optional incremental index turns repeated queries from ~50ms to sub-millisecond.
- *irst
class structured output and integration.*`rg -json` exists butis a second-class citizen. We want NDJSON as the canonical output, with human rendering as a pretty-printer. We want native MCP and LSP, not wrappers.
2.3 Why now
Three convergent pressures:
- *gent-driven development.*Claude Code, Codex CLI, and Gemini are
now primary consumers of grep in our workflow. Each call costs tokens (output) and permission prompts (in Claude Code). A grep designed for agent loops — server mode, MCP
native, structuredoutput-canonical — measurably reduces both.
- *oder Koda flagship readiness.*KL Native AOT is the official
compilation target for performance-sensitive Stack components (
koder-jet,kodec, etc.). A search engine is a textbook KL showcase: tight loops, SIMD, zeroalloc, IObound under load.
- *euse-first policy demands consolidation.*Today every Stack
component that searches text rolls its own thing on top of
grep,rg,find, or adhoc Go regex. `/ksearch,/k-housekeep,kauditlandings,k-evolve` would all benefit from a shared library — and they need to feel native to the Stack, not shell out.
3. Non-goals
Equally important to declare upfront. This RFC explicitly does *ot*propose:
- *eating
rgon plain-text raw regex by ≥1.10×.*The last 5–10% ofperf is ~10 years of tuning by
@BurntSushiand not worth chasing. Parity within geomean 1.10× is the bar (see §6). - *rapping or embedding
rgfor any release.*Norgdependency atany point; design is pure-KL from day one. (Rejected option discussed and discarded during scoping conversation 2026
0502.) - * general-purpose code intelligence platform.*No symbol resolution,
no type inference, no go
todefinition. AST-aware search uses parsers for matching, not for semantic analysis. LSP-style server is for search queries from editors, not for replacingclangd/gopls. - * full-text search platform*(ZoektSourcegraphElasticsearch).
Optional indexing exists for repeated-query speedup in server mode, but the default mode is index
less adhoc search likegrep. - * replacement for
find.*File enumeration is part of the engine butnot the primary surface;
find-style queries are out of scope for v1. - * shell language.*Composable pipelines exist (§7.5) but the syntax
is flag
driven, not a new minilanguage to learn.
4. Design principles
4.1 Engine = library; CLI = thin shell
The single source of truth is a library written in KL Native AOT. Every frontend (CLI, MCP server, LSP server, HTTP/gRPC daemon, language bindings) is a thin wrapper that calls into the library. There is no "CLI-only logic". This pattern matches the Koder Stack engine+product split (cf. project memory engine_product_pattern).
4.2 Three search modes, one engine
The engine exposes three orthogonal modes, each over the same indexing, walk, and output infrastructure:
- *text`*— regex/literal text matching. Default mode. Compatible
conceptually with
grep/rg. - *structural`*— AST
aware queries via perlanguage parsers. "Allfunction declarations matching name
foo*", "all calls ofbarin scope of classBaz", etc. - *record`*— record
oriented for linedelimited structured formats(JSONL, NDJSON, structured logs, chat transcripts). Returns whole records, not lines. Knows about turn boundaries in transcripts.
Modes are selected by flag (--mode=text|structural|record) or by auto-detection from input shape (extension/content sniff). They share the walk, output, and ranking infrastructure.
4.3 Streaming-first I/O
mmap for large files, read for small/streaming. Walk is parallel across CPUs with bounded queue depth. Output is streamed (no materialize all results before printing). Bounded memory: search runs over a 100 GB tree without loading the tree into memory.
4.4 Structured output is canonical
NDJSON is the engine's canonical output format. Every match emits a record with: file path, byte range, line number, line text, captures, mode-specific metadata (AST node kind for structural, record offset for record mode). The humanfriendly TUI output is a prettyprinter over the NDJSON stream. This makes machine consumption (other tools, agents) the zero-friction path.
4.5 Server mode is first-class, not an afterthought
A daemon mode (koder-search serve) keeps the walker cache hot, supports optional incremental indexing, and serves queries over a local HTTP+gRPC socket. CLI invocations can transparently route to the daemon if it's running, falling back to standalone otherwise. Agent loops (MCP) talk to the daemon directly.
4.6 Hyperscale-first
Per policies/hyperscale-first.kmd: design for 10M files, 100 GB repositories, 1000 concurrent queries in server mode. Where two implementations have similar effort, choose the one that scales. This is not "we'll optimize later" — the architecture starts there.
5. Architecture overview
┌─────────────────────────────────────┐
│ Frontends (thin shells) │
├─────────────────────────────────────┤
│ • CLI (k<slug>) │
│ • MCP server │
│ • LSP-style server │
│ • HTTP / gRPC daemon │
│ • Bindings: Dart, Go, Rust, KL │
└─────────────────┬───────────────────┘
│
┌─────────────────▼───────────────────┐
│ Engine library (KL Native AOT) │
├─────────────────────────────────────┤
│ • Query planner │
│ • Mode dispatch (text/struct/rec) │
│ • Result ranker & formatter │
└──┬───────────────┬──────────────────┘
│ │
┌──────────▼────┐ ┌───────▼─────────┐
│ Match engines │ │ I/O subsystem │
├───────────────┤ ├─────────────────┤
│ • RE2-style │ │ • Walker │
│ NFA→DFA │ │ (gitignore, │
│ • Aho-Corasick│ │ parallel) │
│ • SIMD literal│ │ • mmap reader │
│ • AST parsers │ │ • Stream reader │
│ (per-lang) │ │ • Index │
│ • Record split│ │ (optional) │
└───────────────┘ └─────────────────┘5.1 Match engines
- *E2
style NFA→DFA matcher.*No backreferences in the highperf path(matches
rg'sregex-automatadesign choice). Backreferences fall back to a slower path or are rejected with a clear message. - *ho-Corasick for literal sets.*When the pattern is a literal or
alternation of literals, switch to AC. Same trick
rguses. - *IMD literal scanning.*AVX2/SSE2 on x86_64, NEON on aarch64. Used
for the prefilter pass. Per-arch dispatch resolved at process start.
- *ST parsers per language.*v1 set: KL, Dart, Go, Rust, Python,
JavaScript/TypeScript, Markdown, KMD. Extensible. Likely tree-sitter for breadth, with custom KL parser for KL itself.
- *ecord splitter.*Format-aware split for JSONLNDJSONstructured
log formats and for our chat transcript JSONL.
5.2 I/O subsystem
- *alker.*Respects
.gitignore,.koderignore,.ignore. Parallelacross CPUs with work
stealing. Filetype detection by extension and content sniff. - *map reader.*For files above a threshold; bounded virtual memory
budget per query.
- *tream reader.*For stdin and small files; preserves streaming
semantics for
tail | search. - *ndex (optional).*Trigram
based, Zoektstyle. Off by default.Enabled per
tree via `kodersearch index path. Incremental update on filesystem changes (inotify/fsevents). Stored under~.cachekoder-search/` keyed by tree path.
5.3 Result ranker
Default ranking is walk-order (deterministic, no surprise). Optional flags:
--rank=relevance— score by file type weight (source > doc > generated),match kind (definition > reference > comment string), match density.
--rank=mtime— most recently modified first.--rank=size— smallest files first (often the best signal for "findthe canonical definition").
Ranking happens after match collection but before output streaming; output is bounded by --limit=N to keep ranker memory finite.
6. Performance bar (two-gate progression)
*esolved 2026
0502:*the perf bar uses *wo gates* not one. Gate 1 marks F1 engineering completion (Krep becomes opt-in /status: stable); Gate 2 matches thepolicies/self-hosted-first.kmdG2 hot- path default of ≤ 1.05× and triggers the default-flip across the Stack (status: official). This decouples engineering completion from policy compliance without loosening the policy floor for default- by-default usage. Calibration discussion summary: option (b) tolerant 1.10× was chosen as the F1 finish line beforeself-hosted-firstbecame canonical; option (c) dual-bar reconciles it with the policy default without slipping the F1 schedule.
All four structural criteria below (datasets, outlier cap, parityorwin count) apply at *oth*gates. Only the *eomean threshold*changes.
6.1 Gate 1 — F1 done / optin / status: stable (plaintext case)
status: stable (plainWhen all four criteria pass on the reference benchmark suite via /k-bench:
- *eomean ≤ 1.10×
rg*(average at most 10% slower). - *o single benchmark > 1.5×
rg*(no catastrophic outlier). - * 3 benchmarks at ≤ 1.0×
rg*(parity or wins) — proves theSIMD path, parallel walk, and matcher are pulling weight, not just an "ok average from luck".
- *eference datasets, fixed and versioned:*
- Koder monorepo snapshot (heterogeneous languages, ~5 GB)
- Linux kernel snapshot (massive C codebase)
- Chromium snapshot (massive C++/JS codebase)
- 10 GB synthetic JSONL (chat transcripts realistic shape)
- "Pathological regex" set — patterns that exhibit catastrophic
backtracking on PCRE but should not on RE2. We must match
rghere (both engines avoid the trap).
Effect: koder.toml [self_hosted].status = "stable" for the plain-text case. AI may prefer Krep casebycase. CLAUDE.md and command defaults *tay on rg*
6.2 Gate 2 — Default flip / status: official (plain-text case)
Same four criteria, *ith one tightened threshold*
- *eomean ≤ 1.05×
rg*(policy default for hot-path G2 inself-hosted-first.kmd). - No single benchmark > 1.5×
rg(unchanged). - ≥ 3 benchmarks at ≤ 1.0×
rg(unchanged). - Same reference datasets (unchanged).
Plus G3 + G5 from the policy:
- ≥ 3 stable releases without breaking changes (G3 stability).
- ≥ 2 production Stack consumers actively using Krep (G5).
Effect: koder.toml [self_hosted].status = "official" for the plain- text case. Default flips: krep becomes the default in CLAUDE.md, Claude Code config, /k-search, /k-housekeep, etc. AI MUST prefer Krep unless an explicit gate fails for the specific case.
6.3 Why dual-bar instead of single ≤ 1.05× from the start
A single ≤ 1.05× gate would:
- Inflate F1 from ~3
4 months to ~56 months focused (the marginalperf wins from 1.10× to 1.05× cost more than the previous 0× to 1.10×, by diminishing returns). No usable Krep in the meantime.
- Block any case
bycase opt-in (e.g. agents preferring Krep in agentloops where the new dimensions matter, even at 1.08× plain-text) until the strict bar is met.
The dualbar lets F1 ship at ~34 months as stable, validates the architecture and dimensions in real use, and reserves the strict default-flip threshold for what it is in the policy: the gate to become the universal default, not the gate to exist.
Stricter geomean (always ≤ 1.0×) was discussed and rejected during scoping as unmeasurable in practice (some inputs always favor 10year tuned rg).
7. CLI surface (sketch)
Binary: krep (per binaries-and-cli/naming.kmd — k<slug> convention).
krep <pattern> [path...] # default text mode, like rg
krep --mode=structural 'fn:foo' # AST query
krep --mode=record '.level=ERROR' # JSONL record query
krep replace 'old' 'new' [path] # search-and-replace with preview
krep scope --fn -p 'pattern' # match + return enclosing function
krep serve # start daemon
krep index <path> # build optional index
krep bench # compare against rg on local repo7.5 Composable pipeline
krep find 'KoderApp' --json \
| krep narrow --scope fn \
| krep filter --not-in-comments \
| krep rank --relevanceEach subcommand reads NDJSON on stdin, writes NDJSON on stdout, with human pretty-printing only at terminal end. No new shell language.
8. Frontends
8.1 CLI
Standalone binary krep, KL Native AOT compiled, statically linked where possible. DebrpmAppImagemacOS pkgWindows MSI per specs/binaries-and-cli/naming.kmd. D-Bus ID dev.koder.krep, symlink /usr/local/bin/krep.
8.2 MCP server
Native MCP implementation. Exposes tools: search_text, search_struct, search_record, replace, scope_match. Direct integration with Claude Code (dropin for builtin Grep tool), Codex CLI, Gemini.
8.3 LSP-style server
Speaks LSPflavored JSONRPC for editor integration (Zed, VSCode, Helix, Emacs). Provides "find references" / "find definitions" / "workspace symbol" semantics where they overlap with our search modes. Not a full LSP server — search subset only.
8.4 HTTP / gRPC daemon
ks serve opens on 127.0.0.1:9870 (TBD port) and Unix socket /run/user/$UID/koder-search.sock. CLI invocations transparently route to the daemon when running. Agents talk to the daemon directly to skip process startup cost.
8.5 Language bindings
- *L*— native, the engine itself.
- *art*— for Flutter UIs (in-app search in Koder products).
- *o*— for CLI tooling and existing Go components.
- *ust*— for
kodecand other Rust components, via FFI.
Bindings ship via the SDKs (engines/sdk/), not as separate distributions.
9. Module placement — decided
Following the *hared name*variant of the engine+product pattern (audience is the same — devs and agents — so engine and CLI share the brand krep, similar to kicon, kodec, kdb, jet):
- *ngine + CLI:*
engines/search/krep/(decided 20260502).- Domain:
engines/(per RFC-003 — Krep is consumed by embedding +execution, not via API or UI).
- Area: *search
** (new top-level area underengines`). - Sector:
krep. - Internal layout per RFC-006:
engine/— the KL Native AOT library (the search engine itself).app/cli/— thekrepbinary frontend.landing/— landing page deployed tokrep.koder.dev.docs/— RFC, ADRs, CHANGELOG, README.backlog/—pending/,in-progress/,done/.koder.toml— module manifest including the[self_hosted]block (see §15).
- Domain:
- *hy new area
search/:*Krep doesn't fit cleanly under existingengines/areas (kodec/is media codecs,lang/is the Koder Language toolchain,sdk/is consumerside SDKs). Searchand- indexing is a distinct architectural concern with future components likely to join (e.g. an index daemon, query federation, semantic embeddings). Singlepurpose area is futureproof.
- *aemon*(long-running server frontend) ships as part of the same
module under
engines/search/krep/exposed viakrep serve. If it later grows into a shared multi-tenant service across hosts, it spins out toservices/foundation/krep/per RFC-003 §7 decision tree. This is a future migration, not a v1 concern.
- *uture search-area neighbors*(not part of this RFC): a dedicated
index daemon (
engines/search/index/), federation layer (engines/search/federation/), semantic search engine (engines/search/semantic/). Mentioned only to validate the area choice — not in scope here.
10. Naming — decided
*rand: krep*(shared engine + CLI). Decided 20260502 via Brand score session per specs/naming/brand-score.kmd.
- *ngine:*
koder-krep(library + daemon) - *LI binary:*
krep - *omain:*
krep.koder.dev(future landing) - *-Bus ID:*
dev.koder.krep
Rationale
| Dimension | Score | Rating | Notes |
|---|---|---|---|
| Type | 59 | Fair-high | only sub |
| Pron | 100 | Excellent | clean CVCV, no clusters, no rare bigrams |
| Son | 100 | Excellent | perfect alternation across all 3 pairs |
| Mem | 100 | Excellent | length 4 (lower-ideal), 100% CV alternation |
| *rand* | *6* | *reat* | exceeds product-flagship target of 75+ and engine target of 60+ |
Concept
"Krep into codetextrecords to find matches." Action verb, energetic, short, memorable. Pairs naturally with the existing Koder Stack name family (Tune, Talk, Pass, Keys, Eye, Koru, Take, Sky, Drive, Mosaic), all of which are short concrete nouns/verbs in the same register.
Why shared instead of split engine+CLI
Existing Stack precedent for shared single-name (engine + CLI under one brand): kicon, kodec, kdb-next, koder-jet. The split pattern (Kompass+Mosaic, Raven+Kmail, Keys+Pass) applies when engine is B2B infrastructure and product is B2C end-user — different audiences. For Krep, both engine and CLI address the same audience (devs and AI agents), so a single brand minimizes naming overhead and avoids brand fragmentation across our developer surface.
Collision check
- No major dev-tool collision in code search (DuckDuckGo Krep, Apache
Hudi DiVE — both obscure or unrelated).
- No CLI command collision in PATH (
krepis a Docker layer inspectorby
wagoodman/krep— niche, not a default install, and our binary iskrepso there is no shell-level collision). - Domain
krep.koder.devcontrolled.
Runners-up considered
scour(Brand 71) — semantically more precise, less collision; lowerBrand score overall.
probe(Brand 71) — more abstract/technical, less energetic.sense,lens,vista,hawk— Brand 75–80 but each had a heavierpre-existing brand collision (Sense*, Google/Apple Lens, MS Vista, Hawk security tools).
fish,dig,find(Brand 81–86 as raw scores) — fatal CLIcollision with shellDNSUNIX tools regardless of
k-prefix.
Full session log of 25 scored candidates is in the conversation transcript of 20260502.
11. Phased roadmap
Phases gate on concrete deliverables, not time. Each phase ends with a release tag and /k-bench report.
F1 — Text mode + perf parity (estimated 3–4 months focused)
The hardest phase. Deliverable:
- Engine library with
textmode endtoend. - CLI binary (one frontend), no daemon yet.
- RE2-style matcher in KL with SIMD literal prefilter.
- Aho-Corasick for literal sets.
- Parallel walker with gitignore awareness.
- NDJSON output canonical, human pretty-printer.
/k-benchintegration with all reference datasets from §6.
*ate to F1 done:*§6.1 Gate 1 criteria met on /k-bench report (geomean ≤ 1.10× plus structural criteria). At this point the component flips to status: stable in the registry; AI may prefer Krep casebycase but defaults stay on rg.
*ubsequent perf tuning*(in F2+ in parallel) closes §6.2 Gate 2 (geomean ≤ 1.05×). Together with G3 (≥3 stable releases) and G5 (≥2 prod consumers) it triggers status: official and the default-flip across the Stack.
F2 — Record mode (estimated 3–4 weeks)
- JSONL/NDJSON record splitter.
- Chat transcript turn
aware splitter (for `/ksearch`). - Structured log format awareness (jet/observe formats).
- Record-level operations (filter, project, sort).
F3 — Server mode + MCP (estimated 4–6 weeks)
ks servedaemon with walker cache.- HTTP+gRPC over local socket.
- CLI auto-routing to daemon when running.
- Native MCP server integrated with Claude Code, Codex, Gemini.
- Optional incremental trigram index.
F4 — Structural mode (estimated 6–8 weeks)
- Parser integration (tree-sitter for most languages, custom KL parser
for KL).
- Structural query language (TBD; possibly
ast-grep-compatiblesubset to ease adoption).
- Scope
aware context (`-scope=fn|class|block`).
F5 — Replace + LSP + bindings (estimated 4–6 weeks)
- Search
andreplace with preview, dryrun, structuralawareexclusions (don't touch comments / strings unless flagged).
- LSP-style server.
- DartGoRust bindings via SDKs.
Total realistic timeline: *7–10 months*to complete all five phases. F1 can ship as v1.0 standalone if needed, with subsequent phases as feature releases.
12. Risks
- *erf parity is harder than it looks.*RE2-style matcher in a new
language without 10 years of tuning may miss the bar. Mitigations: port the proven algorithms (not invent new ones), profile early and often, accept option (b) as the bar (geomean 1.10×, not strict ≤ 1.0×).
- *ST parser maintenance.*Tree
sitter grammars drift; perlanguageAST queries are surface area to maintain. Mitigation: ship structural mode with limited language set in F4, expand only when usage justifies.
- *aemon reliability.*A long-running daemon adds operational
complexity (zombie processes, stale caches, version mismatch with CLI). Mitigation: daemon is opt-in; CLI works standalone always; daemon failures fall back to standalone transparently.
- *CP ecosystem instability.*The MCP spec is young; Claude Code and
Codex implementations diverge. Mitigation: design MCP server as a thin wrapper around the engine library; rewriting it for spec changes is contained.
- *aming bikeshed.*Naming session can drag. Mitigation: use the
brand
score policy (objective scoring), timebox to one session.
13. Open questions
- ~*Module home for the engine.*~ *esolved 2026
0502:*newarea
engines/search/, sectorkrep→engines/search/krep/. See §9.
- ~*Performance bar alignment with
self-hosted-first.kmdG2.*~*esolved 2026
0502:*dual-gate progression — Gate 1 (§6.1) geomean ≤ 1.10× forstatus: stable, Gate 2 (§6.2) geomean ≤ 1.05× (policy default for hot-path) forstatus: officialand default flip. Decouples F1 engineering finish-line from policy compliance for defaultbydefault usage. See §6 and §15.1.
- ~*Search
tooling capability subpolicy (G4).*~ *esolved 20260502:*draft new
policies/reuse/search-tooling-first.kmdsub-policy. Rationale: search-tooling has a distinct capability surface (MCP contract stability, structural-mode language coverage, daemon graceful-shutdown, index format versioning, NDJSON output contract) that does not fit cleanly underbuild-tooling-first(which covers determinism + idempotence for build pipelines). Krep is the seed consumer; future search-area components inherit. Sub-policy lands as a separate PR before F1 ratification, drafted in parallel with module scaffold.
- *L standard library readiness for SIMD intrinsics.*Investigation
completed 2026
0502:- *VX2SSE on x86_64:*Koder Koda already emits AVX2SSE
instructions.
compiler_backend.kdcontains 158 asm_emit lines referencing AVXSSE registers (ymmxmm) and instructions (vmovaps,vpaddd,movdqu, etc.). Runtime detects SSE4.2 via CPUID (line ~4490). SIMD intrinsics surface exists at AST level (simd.zero_i8x16,simd.f32x4, etc.). Auto-vectorizer hook exists (try_auto_vectorize_simd). Registry confirmssimdis ingates_passedfor Koder Koda'shot-path libuse. *ate G2 viable for x86_64.* - *EON on aarch64:**ap.*
arm64_codegen.kdandarm64_encoder.kdcontain zero NEON-related symbols (grep -E "neon|NEON|ld1|st1|fmla"returns 0). ARM64 backend today emits scalar arithmetic only. - *mplication for Krep perf bar:*
rguses NEON on aarch64(Apple Silicon, Linux ARM SBCs). Krep on aarch64 without NEON codegen will not hit Gate 1 (geomean ≤ 1.10×) on aarch64. Mitigation: scope F1's perf bar to *86_64 only* aarch64 parity becomes a follow
up gate in a NEONcodegen RFC againstengines/lang/lang/. Add to RFC §6 datasets that the reference benchmark suite is x86_64; aarch64 parity tracked separately.
- *VX2SSE on x86_64:*Koder Koda already emits AVX2SSE
- ~*Tree
sitter integration.*~ *esolved 202605-02:*embedtree-sitter (C library) via FFI for F4 (structural mode). Rationale: ship velocity (tree
sitter has battletested grammars for KL, Dart, Go, Rust, Python, JS/TS, Markdown — much faster than writing parsers in KL). KLnative parsers tracked as a followup v2 RFC once the structural API stabilizes. Acceptable cost: a C-library FFI dependency, contained behind thebackends/structural.kdinterface and only enabled when--mode=structuralis used.
- ~*Optional index storage location.*~ *esolved 2026
0502:*~/.cache/koder-krep/<tree-hash>/for index storage. Rationale: follows XDG cache dir convention familiar to users; survivesgit clean; doesn't bloat repo working trees.<tree-hash>is the SHA-256 of the canonical tree path so multiple checkouts of the same repo share an index. Override viaKODER_KREP_CACHEenv var.
- ~*CLI backwards
compat with05-02:*rgflags.*~ *esolved 2026yes,
krepacceptsrg's common flags directly (-i,-n,-A/-B/-C,-e,--type=..., plus the.gitignore/.ignoreresolution rules). Required to satisfy G1 (feature parity) for the plaintext caseofuse. Krepspecific flags use long form (--mode=,--scope=,--rank=) to avoid colliding withrgshort-flags. A formal compatibility table goes inengines/search/krep/docs/cli-compat.kmdonce the module is scaffolded.
- ~*Adoption order across the Stack.*~ *esolved 2026
0502:*ordered rollout:
- */k-search`*— first. Lowest risk: it operates over chat
transcripts (JSONL), so it benefits primarily from Krep's record mode (F2). Plain-text perf bar (Gate 1) doesn't gate this adoption — record mode has its own gates.
- */k
housekeep` audit walk*— second. Readonly across themonorepo; failures observable and reversible.
- */k
auditlandings`*— third. Larger surface; needs Krepstable on diverse file types.
- */k-evolve` ticket discovery*— fourth. Heaviest
integration; uses all three modes (textrecordstructural).
Adoption #1 + #2 satisfy G5 (≥ 2 production consumers). After that, default-flip in CLAUDE.md per §6.2 Gate 2.
- */k-search`*— first. Lowest risk: it operates over chat
14. References
policies/hyperscale-first.kmd— design principlespolicies/reuse-first.kmd— engine library reuse patternpolicies/self-hosted-first.kmd— gates + decision protocol for Koder vs externalpolicies/document-format.kmd—.kmdfor new docsregistries/self-hosted-pairs.md— registry of self-hosted ↔ external pairsspecs/binaries-and-cli/naming.kmd—k<slug>binary namingspecs/naming/brand-score.kmd— naming methodology- RFC-003 (monorepo taxonomy) — module placement rules
- RFC-006 (sector internal layout) — engineapplanding structure
- RFC-009 (specs and policies location) — RFC hosting convention
policies-RFC-002-self-hosted-first— design rationale for the selfhostedfirst frameworkengine_product_pattern(project memory) — engine + product splitkoder_grep(project memory) — perf bar and adoption gateself_hosted_first(project memory) — gates + registry summaryripgrepsource — reference for matcher and walker design(
regex-automata,ignore,aho-corasickcrates)ast-grep,comby— prior art for structural searchZoekt— prior art for trigram index in code search
15. Selfhostedfirst alignment
Krep replaces an external dependency (rg / grep) used widely in the Stack and across all our agent loops. It is unambiguously a self-hosted ↔ external pair under policies/self-hosted-first.kmd and must declare a [self_hosted] block in its koder.toml once scaffolded, joining the registry at meta/docs/stack/registries/self-hosted-pairs.md.
15.1 Gate mapping (Krep ↔ rg/grep, plain-text case)
| Gate | Krep milestone that closes it | Maps to RFC section |
|---|---|---|
| *1 — Feature parity* | Text mode endrg, , , , -ype=...`, gitignore |
§4.2 (text mode), §7 (CLI surface), F1 deliverables (§11) |
| *2 — Performance parity* | Twostatus: stable. Gate 2 = §6.2 (geomean ≤ 1.05×, matching policy default for hotstatus: official. All four structural criteria (datasets, outlier cap, parity |
§6.1, §6.2 |
| *3 — Stability* | Engine library + CLI hold a stable public API for ≥ 3 releases without breaking changes. Maps to koder.toml [self_hosted].status: stable for the plain-text case. |
§11 phase gates (after F1 + soak time) |
| *4 — Capability gate (search |
Sub, runtime, build, protocol — none cover "search". This RFC opens a follow-up to either reuse build (if Krep is classified as build-tooling) or add a search |
§13 new open question (15.x) |
| *5 — Critical-path readiness* | Used by ≥ 2 production Stack consumers, not behind a feature flag. Plausible early adopters: /k-search (transcript search), /k-housekeep (audit walk), /k-evolve (ticket discovery). |
§11 F3+ rollout |
15.2 Status trajectory
| Phase done | koder.toml status |
Meaning for AI/devs |
|---|---|---|
| Module scaffolded, no F1 yet | experimental |
AI keeps using rg; ticket pending to close gates. |
| F1 done, *6.1 Gate 1*criteria met (geomean ≤ 1.10×) | stable (plain-text case) |
AI may prefer krep; caserg. |
| *6.2 Gate 2*met (geomean ≤ 1.05×) + ≥3 stable releases (G3) + ≥2 prod consumers (G5) | official (plain-text case) |
AI MUST prefer krep for plain |
| F2/F4 modes (record, structural) close their own G1+G2 with same dual-gate logic | stable then official per case |
Perofficial for plainexperimental for structural simultaneously. |
15.3 Implications
- *koder.toml [self_hosted]` block at scaffold time*— mandatory per
the policy's anti-drift heuristic for components under
engines/with akoder--prefixed name. - *er-case gate evaluation*— Krep's status is not a single global
value. Plain-text, record, and structural modes are evaluated independently, matching the policy's per
caseof-use semantics. - *HANGELOG entry on first adoption*— when the first production
Stack consumer flips from
rgtokrep, log it per the policy's decision protocol question 3.
Status of ratification items (live tracker)
| # | Item | Status | Reference |
|---|---|---|---|
| 1 | Naming | ✅ resolved 2026krep (Brand 86) |
§10 |
| 2 | Perf bar G2 alignment | ✅ resolved 2026 |
§6, §15.1 |
| 3 | Module home | ✅ resolved 2026engines/search/krep/ |
§9 |
| 4 | rg flag compat | ✅ resolved 2026 |
§13.7 |
| 5 | KL SIMD readiness | ✅ resolved 2026 |
§13.4 |
| 6 | Tree |
✅ resolved 2026 |
§13.5 |
| 7 | Search |
✅ resolved 2026policies/reuse/search-tooling-first.kmd; Krep is seed consumer |
§13.3, §15.1 |
| 8 | Index storage location | ✅ resolved 2026~/.cache/koder-krep/<tree-hash>/; override via KODER_KREP_CACHE |
§13.6 |
| 9 | /k-bench reference dataset versions |
⏳ pending concrete commit (depends on scaffold) | §6 |
| 10 | Adoption order across Stack | ✅ resolved 2026 |
§13.8 |
Next concrete steps for promotion DRAFT → Approved
- Resolve items 5, 6, 7, 8 (eng + arch decisions requiring user input).
- Scaffold module via
/new-productor manual layout per RFC-006. - Write
koder.tomlwith[self_hosted]block (statusexperimental,gates_pendinglisting all G1–G5). - Move this RFC to
engines/search/krep/docs/rfcs/001-engine-and-cli.kmdwith symlink-back at
meta/docs/stack/rfcs/search-RFC-001-engine-and-cli.kmd. - Open F1 tracking ticket in
engines/search/krep/backlog/pending/. - Lock
/k-benchreference datasets (item 9) as part of F1 setup. - Re-circulate RFC for Approved status; bump frontmatter
statusfield.