Local code search for AI coding agents. Six fast, purpose-built tools that hand Claude Code, Codex & friends ranked answers, not raw grep. Zero API keys, 100% on-device.

Maybe grep isn't all you needโ€ฆ ๐Ÿฌ Every coding agent today reaches for grep + Read by reflex. sweet-search challenges the narrative. ๐Ÿ˜Ž

npm GitHub stars license node platforms inference


โœจ Highlights

  • Hybrid retrieval โ€” one of the six tools uses BM25F lexical + dense semantic + structural graph signals, fused per query and reranked by late-interaction
  • Agent-native by design โ€” token-budgeted output tiers, an optional MCP server (and default zero-overhead CLI), and a GEPA-evolved system prompt โ€” one init installs it into Claude Code by default (Codex, Gemini CLI, and Cursor via flags)
  • Indexed grep, ~10ร— faster than ripgrep โ€” a sparse n-gram prefilter skips the files that provably can't match
  • ColBERT-style reranking, locally โ€” per-token MaxSim late interaction on hand-written SIMD kernels
  • GPU-accelerated indexing โ€” Apple Metal, CUDA, CoreML Neural Engine, or plain CPU via ORT; same engine, auto-selected
  • Never stale โ€” incremental indexing keeps the index aligned with your working tree, uncommitted edits included
  • No storage hassle โ€” indexed artifacts maximally optimized without any accuracy tradeoff; up to INT4 quantization
  • Local-first โ€” all models run on-device; nothing is sent anywhere, ever. CPU-inference supported for all models

๐Ÿ“š Table of Contents

GET STARTED

๐Ÿš€ Quickstart three commands to a searchable repo

๐Ÿ–ฅ๏ธ Platform Support macOS ยท Linux ยท WASM fallback

USE IT

๐Ÿงฐ The Six Tools search ยท grep ยท find ยท semantic ยท trace ยท read

๐Ÿง  The Evolved Agent Prompt GEPA-optimized search discipline

๐Ÿ”Œ Works With Your Agent MCP ยท Claude Code ยท Codex ยท Gemini ยท Cursor

UNDER THE HOOD

โšก GPU-Accelerated Indexing candle ยท fused kernels ยท cAST chunking

๐Ÿ”„ An Index That Never Goes Stale reconcile daemon tracks your working tree

๐Ÿฆ€ The Native Engine Room four Rust crates + INT4 LI compression

THE RECEIPTS

๐Ÿ“Š Benchmarks agent cost savings ยท engine speed ยท full-corpus MRR

๐Ÿงญ Where sweet-search Fits honest wins & trade-offs vs peers

๐Ÿ™ Prior Art & Acknowledgements the shoulders we stand on

๐Ÿ“„ License Apache-2.0

๐Ÿš€ Quickstart

Requirements: Node.js 18+ on macOS (Apple silicon or Intel) or Linux (x64 or ARM64). On Windows, run sweet-search inside WSL2.

npm install -g sweet-search

cd your-repo
sweet-search init     # one-time: downloads local models, wires up your agent
sweet-search index    # builds the index โ€” GPU-accelerated where available

sweet-search "where do we validate JWT tokens?"

That's it. init is idempotent and SHA256-verifies every model binary; re-running it is always safe. From then on, the index stays up to date automatically as you work.

To uninstall ๐Ÿ˜ข:

sweet-search uninstall --keep-models  # current repo only; keeps shared models and the global CLI
sweet-search uninstall                # current repo plus its shared model downloads; keeps the global CLI
npm uninstall -g sweet-search         # global CLI only; does not clean initialized repos

Run sweet-search uninstall inside each initialized repo before removing the global CLI.

sweet-search init --wizard          # interactive: shows your hardware, recommends a model tier
sweet-search init --profile core    # lexical-only, no model downloads (CI-friendly)
sweet-search init --li-model edge   # compact late-interaction model for constrained machines
sweet-search uninstall --dry-run    # preview cleanup for the current repo
  • Footprint: CPU-only hosts download a few hundred MB of INT8 models; GPU hosts add ~1.2 GB of FP32 backbones (skipped automatically where they'd be useless); M3+ Macs can additionally fetch a ~3.2 GB CoreML cascade for Neural Engine acceleration. Everything lands in ~/.cache/sweet-search/models/ and is used strictly on-device.
  • Agent wiring: init injects the tool-routing system prompt into CLAUDE.md (and AGENTS.md, GEMINI.md, Cursor rules via flags), registers a session-start prewarm hook so your first query hits a warm daemon, and installs a /sweet-index skill in Claude Code.
  • What gets indexed: what you'd expect โ€” .gitignore is respected, node_modules/build dirs/minified artifacts are denied, files over 1 MB skipped, with a .sweet-search-ignore for extra rules.

๐Ÿ“Š Benchmarks

We measure sweet-search four ways โ€” from how much it helps a real agent down to raw engine throughput:

๐Ÿค– โ‘  Code-retrieval (agent-in-the-loop) Does it make a real coding agent cheaper and more useful when it searches your repo? Paired against each model's own grep-and-read loop.

๐Ÿšง โ‘ก Task-completion (coming soon) Does cheaper, denser context compound into a higher resolve-rate on multi-step engineering tasks? Harness in progress.

๐Ÿ“„ โ‘ข Paper-type IR (academic) The standard NLโ†’code retrieval suites (GCSN, M2CRB, CoSQAโ€ฆ), full-corpus MRR@10.

โšก โ‘ฃ Engine speed Raw systems numbers โ€” grep throughput, query latency, rerank kernels, HNSW.


๐Ÿค– 1. Code-retrieval benchmarks โ€” the agent-in-the-loop test

One variable changes: how the agent searches a real repository.

  • ๐Ÿฌ sweet-search: the model gets our GEPA-evolved search discipline and search tools.
  • ๐ŸŒ Native: the same model uses its built-in grep-and-read loop.

Same tasks, same judge, paired probe-for-probe.

sealed vault ยท exact paired results ยท five representative profiles ยท full 11-cell matrix and held-out/OOD replication below

The headline, in four claims:

  • ๐Ÿ’ฐ Cheaper where the agent thrashes โ€” up to โˆ’34% realized cost on Codex; โˆ’18 to โˆ’32% across the GPT-5.5 / opencode / bare-API harnesses.
  • ๐Ÿ”ง Fewer round-trips โ€” up to โˆ’56% tool calls, significant on 9 of 11 cells.
  • โœจ More useful per response โ€” +0.18 to +0.31 on a 5-dimension usefulness score, and still denser when length-matched (significant on 8 of 11 cells).
  • ๐ŸŽฏ Accuracy held โ€” and lifted on the weak โ€” a statistical tie on flagship models (saturated at 0.94โ€“0.99), and +3 pp (up to +8 pp out-of-distribution) on weaker models like GLM-5.1 and DeepSeek.

The win is harness-adaptive: where the native loop is disciplined (Claude Code) it shows up as denser, more useful context per token; where it thrashes (Codex floods 30k+ tokens of its own grep output into context) it shows up as a large cost and tool-call cut. Either way, final-answer accuracy never significantly regresses.

๐Ÿงฐ Native agent harness ๐Ÿ’ฐ Realized cost ๐Ÿ”ง Tool calls โœจ Useful content / response ๐ŸŽฏ Final accuracy
๐Ÿค– Codex (GPT-5.5) โˆ’30 to โˆ’34% โˆ’44 to โˆ’56% +0.06 โ†’ +0.17 โ†‘ tie (saturated)
๐Ÿš opencode (GPT-5.5 / GLM-5.1) โˆ’18 to โˆ’22% โˆ’15 to โˆ’49% +0.23 to +0.31 โ†‘ tie
๐Ÿ”Œ bare API (GPT-5.5 / GLM / DeepSeek) โˆ’15 to โˆ’32% แตƒ โˆ’15 to โˆ’33% +0.08 to +0.24 โ†‘ tie ยท +3 pp on weak models
๐ŸŸฃ Claude Code (Sonnet / Opus) โˆ’10% to +14% แต‡ โˆ’5 to โˆ’33% +0.18 to +0.29 โ†‘ tie

โ†‘ "Useful content / response" is the per-response delta on a 5-dimension usefulness score (answer-grounding ยท workable-code ยท navigability ยท edit-locality ยท sufficiency), 0โ€“1 scale. "tie" = final-answer correctness statistically indistinguishable (saturated in the 0.94โ€“0.99 band on flagships).แตƒ the two cheapest bare models cost fractions of a cent either way (GLM +27% of $0.008; DeepSeek โˆ’15% of $0.004). แต‡ Opus โˆ’5/โˆ’10%; Sonnet +8โ€“14%, which is โ‰ˆ1ยข on a flat-rate subscription for a richer answer.

Denser, not just longer. The usefulness lift survives length-matching โ€” comparing sweet-search and native responses of equal token length, sweet-search's content is significantly higher on 8 of 11 cells. The validated single-number usefulness composite (grounding ร— content ร— density) is significant on all 11 sealed cells.

  • What's being compared: the installed sweet-search agent prompt + tools vs. the same model using only its built-in file-reading and shell-grep tools. Not a different model โ€” the same model, with and without sweet-search.
  • Design: 11 modelร—harness cells. Sealed vault (n=60/arm, the pre-registered primary) opened once; plus held-out (n=30) and out-of-distribution (n=40) sets for generalization. Stratified, fixed-seed splits.
  • Judging: 3-judge panel (DeepSeek-V4-flash + Gemini-3.1-flash-lite + MiniMax-M2.7), paired by probe, 20k-sample bootstrap CIs, Benjaminiโ€“Hochberg FDR multiplicity correction across each metric family. We report family-level survival counts, never a single cherry-picked cell.
  • What survives FDR (vault): useful-content 10/11, density-composite 11/11, length-matched content 8/11, fewer-tool-calls 9/11. Generalization (held-out + OOD): content 17โ€“18/20, fewer calls 14/20.
  • The token fact that drives everything: sweet-search's footprint is nearly constant (~1.3kโ€“3.3k tokens) because the tool responses are capped; native's footprint is whatever the model decides to grep โ€” up to 37k tokens on Codex. That single fact is what drives the cost and tool-call gaps.
  • Honest caveats we keep attached: (1) accuracy ties on flagship models โ€” it is not an accuracy win there, it's saturated; the accuracy gains are real only on weaker models. (2) The two weakest cells for length-matched density (Codex-low, DeepSeek) are correct-sign but underpowered โ€” Codex's responses are so token-divergent that too few equal-length pairs exist to reach significance, and DeepSeek is simply under-powered. Those are honest non-victories, not wins.
  • Full methodology and per-cell tables: docs/PHASE7.md.

๐Ÿšง 2. Task-completion benchmarks โ€” coming soon

Retrieval quality is necessary but not sufficient. Cheaper, denser context only matters if it compounds across a real, multi-step engineering task โ€” finding the code, understanding it, changing it, and not breaking anything. The next suite measures exactly that: resolve-rate on SWE-bench-style multi-file tasks, sweet-search-wired vs. native, on the same paired, multiplicity-controlled bar as above. Harness and pilot are in progress โ€” numbers land here when they clear that bar, and not before.


๐Ÿ“„ 3. Paper-type retrieval benchmarks โ€” academic NLโ†’code IR

Every number below is the ss-search pipeline end-to-end โ€” the same binary you install โ€” run against the full benchmark corpus (no 99-distractor shortcuts), zero-shot (we never fine-tune on these tasks). Where a benchmark's queries are docstrings, we strip the docstring out of the indexed code so the query can't trivially match itself โ€” the standard retrieval protocol.

We're SOTA in June 2026 on 3/4 attempted benchmarks at HARDER settings (running on full pool) than most other attempts!

๐Ÿ“š Benchmark ๐Ÿ” What it tests # Queries ๐Ÿ“‚ Pool ๐ŸŽฏ MRR@10 ๐Ÿ† SOTA?
๐ŸŒ GenCodeSearchNet NLโ†’code, 6 languages 6,000 full 6,000 86.6 YES โœ…
๐Ÿ CoSQA web queries โ†’ Python 500 full 6,267 65.5 โœ… (zero-shot)
๐Ÿ—บ๏ธ M2CRB multilingual NLโ†’code (ES/PT/DE/FR โ†’ Py/Java/JS) 5,795 full 5,795 54.0 YES โœ…
๐Ÿ›ก๏ธ AdvTest adversarial, identifier-obfuscated Python 19,210 full 19,210 51.4 NO โŒ

SOTA = best result we can find in the published literature as of June 2026; cross-metric/protocol comparisons are spelled out per benchmark below.

๐ŸŒ GenCodeSearchNet โ†’ 86.6 ย ยทย  ๐Ÿ† SOTA in June 2026

  • The BEST PUBLISHED number we can find, anywhere
  • The benchmark's own paper caps at MRR โ‰ค 0.42 for fine-tuned baselines (โ‰ค 0.10 cross-lingual); even zero-shot OpenAI Ada-2 reaches 0.79โ€“0.94 โ€” but all of it against a tiny 99-distractor pool.
  • We score 0.866 against the entire 6,000-document corpus โ€” a strictly harder setting โ€” and zero-shot. ๐Ÿ”ฅ

๐Ÿ CoSQA โ†’ 65.5 ย ยทย  ๐Ÿฅ‡ Zero-shot SOTA in June 2026

  • Beats EVERY PUBLISHED zero-shot model
  • Canonical setup: 500 real web queries โ†’ the fixed 6,267-code database, no fine-tuning.
  • Clears the strongest zero-shot results out there โ€” CodeSage-Large 47.5 ยท OpenAI text-embedding-3-large 55.4 ยท OASIS 55.8 โ€” and goes toe-to-toe with fine-tuned CodeBERT / GraphCodeBERT (64.7 / 67.5). ๐Ÿ’ช
  • CoSQA has known label noise, so we read the absolute height with a pinch of salt.

๐Ÿ—บ๏ธ M2CRB โ†’ 54.0 ย ยทย  ๐Ÿ† SOTA in June 2026

  • the BEST PUBLISHED number we can find, anywhere โ€” and zero-shot
  • ๐Ÿ‡ช๐Ÿ‡ธ Spanish ยท ๐Ÿ‡ต๐Ÿ‡น Portuguese ยท ๐Ÿ‡ฉ๐Ÿ‡ช German ยท ๐Ÿ‡ซ๐Ÿ‡ท French โ†’ Python / Java / JavaScript.
  • The paper's best โ€” a CodeBERT fine-tuned on the task โ€” reaches 52.7 auMRRc, a metric that averages over easier, smaller pools (so auMRRc โ‰ฅ full-pool MRR for any model). Our 54.0 is full-pool MRR@10 over all 5,795 functions in one pool โ€” a strictly harder measure, cleared with no fine-tuning. ๐Ÿ”ฅ

๐Ÿ›ก๏ธ AdvTest โ†’ 51.4 ย ยทย  ๐Ÿงช our honest worst case โ€” and we publish it anyway

  • Adversarial obfuscation (def Func(arg_0):) deletes the lexical + graph signals our hybrid feeds on โ€” yet we still beat the classic fine-tuned baselines (CodeBERT 27 ยท GraphCodeBERT 35 ยท UniXcoder 41), and our stack still lifts our own encoder ~3pp even here.
  • ๐Ÿ” Full transparency: we could not reproduce the often-cited 59.5 for the bare CodeRankEmbed encoder โ€” the reference FP32 model scores 54.7 on our leak-free corpus, our shipped INT8 build 51.4. The gap is stricter preprocessing + INT8 quantization, not the retrieval pipeline. We report exactly what we measured.
  • Reproduction: result artifacts live in eval/results/; rerun via eval/run_all.js. The canonical full-pool loaders are in eval/download_data.py.
  • Full corpus, not distractors. Published baselines for GCSN- and CoSQA-style benchmarks typically rank the gold against 99 sampled distractors; every number here ranks against the benchmark's full corpus (6kโ€“19k candidates) โ€” strictly harder.
  • Zero-shot + docstring-stripped. We never fine-tune on these tasks. For docstring-derived benchmarks (AdvTest, M2CRB) we strip the docstring from the indexed code โ€” otherwise the NL query matches itself verbatim (a no-strip AdvTest run scores a meaningless 0.98). This is the standard protocol; it is also why our AdvTest is lower than naรฏve setups that leave the docstring in.
  • Dev/held-out split. Our ranking work iterates against a fixed dev split of each benchmark (e.g. GCSN: 600 dev + 400 held-out per language, stratified, seed=42) and treats the remainder as held-out, inspected aggregate-only at milestones. The table figures are full-corpus runs โ€” they include the dev portion we tuned against; a held-out-only breakdown ships with the next results refresh.
  • What we deliberately don't claim yet. CoIR (official metric NDCG@10 over per-subtask corpora up to ~1M docs), CoSQA+ (multi-positive, MAP-primary), and CLARC (per-group pools) use protocols and metrics our single-pool MRR@10 harness doesn't currently match. Rather than publish apples-to-oranges numbers, we omit them; faithful per-subtask CoIR (NDCG@10) runs are queued.
  • M2CRB โ€” the paper's metric is auMRRc (area under the MRR-vs-pool-size curve; best published 52.7, fine-tuned). Because that area averages over easier small pools, auMRRc โ‰ฅ full-pool MRR for any model โ€” so our 54.0 full-pool MRR@10 (all 5,795 functions, zero-shot) clears their best on a strictly harder measure. No one publishes a plain full-corpus MRR@10 on M2CRB, so ours is the best available.
  • AdvTest honesty note. We could not reproduce the commonly-cited 59.5 for the bare CodeRankEmbed encoder on our corpus: the reference FP32 model scores 54.7 on our leak-free, docstring-stripped, full-19,210 setup, and our shipped INT8 build 51.4. We report our measured numbers and the reference check rather than the leaderboard figure.
  • Honesty corner: CrossCodeEval โ€” cross-file completion-context retrieval, a different task than NL search โ€” sits at 0.12. We don't optimize for it and report it anyway.

โšก 4. Engine speed โ€” systems benchmarks, measured in-repo

10.2ร— ripgrep's median grep ย ยทย  2.9 ms warm queries ย ยทย  47ร— MaxSim kernels ย ยทย  โˆ’33% HNSW search p50

โš™๏ธ What ๐Ÿ“ˆ Result ๐Ÿ“„ Source
โšก Indexed grep vs ripgrep 10.2ร— faster at the median (8.5โ€“17.7ร— across 5 repos, 353 realistic queries, 1 ms p50 โ€” identical match counts on every query) docs/GREP_INDEXING_STRATEGY.md
โฑ๏ธ Warm query latency (native CLI) 2.9 ms warm ยท 108 ms cold docs/INIT_STRATEGY.md
๐Ÿงฎ MaxSim rerank kernels 1.26 s โ†’ 27 ms for a 231-candidate pass (47ร— native Rust; 16ร— WASM SIMD) docs/MAXSIM_OPTIMIZATION.md
๐Ÿง  HNSW tuning for code โˆ’33% search p50, +5.9 pp recall@200 docs/HNSW_APPROACH.md
๐Ÿ’พ Indexing memory peak JS heap 785 MB โ†’ 213 MB docs/DISK_FLUSHING_STRATEGY.md
๐Ÿ CoreML cascade (M3 Max) 18% faster full indexing vs the Metal baseline docs/INIT_STRATEGY.md

๐Ÿงญ Where sweet-search Fits

Code search is a crowded space. Here's an honest read on where sweet-search wins and where it gives ground, against the trending leaders and our closest local peers.

Capability sweet-search claude-context Cursor index codebase-memory SocratiCode
100% local โ€” code never leaves your machine โœ… โœ…ยน โŒ โœ… โœ…
Works with zero API keys โœ… โœ…ยน โŒ โœ… โœ…
No external service to run (vector DB ยท Ollama ยท Docker) โœ… โŒ Milvus โŒ cloud โœ… โš ๏ธโต
ColBERT late-interaction rerank โœ… โŒ โŒ โŒ โŒ
Faster-than-ripgrep exact grep โœ… โŒ โœ…โท โŒ โŒ
Call-graph trace (callers ยท callees ยท impact) โœ… โŒ โŒ โœ… โœ…
Drives any terminal agent (Claude Code ยท Codex ยท Gemini CLI) โœ… โœ… โŒยฒ โœ… โœ…
Published NLโ†’code retrieval benchmarks โœ… โš ๏ธยณ โŒ โš ๏ธยณ โš ๏ธยณ
โ€ฆand where sweet-search gives ground
Native Windows โŒโด โœ… โœ… โœ… โš ๏ธโธ
Deep-AST language coverage โš ๏ธ 14 (+70 via regex) โš ๏ธ โš ๏ธ โœ… 158 โš ๏ธ
In-editor GUI ยท writes & edits code โŒ โŒ โœ… โŒ โŒโถ
Org-wide, multi-repo scale โŒ โš ๏ธ โš ๏ธ โš ๏ธ โœ…

โœ… yes ยท โš ๏ธ partial / with caveats ยท โŒ no. Verified June 2026; capabilities drift. ยน claude-context's local path (Milvus Lite + Ollama embeddings) needs no API key, but it defaults to OpenAI/Voyage embeddings + Zilliz Cloud โ€” and still runs Milvus + Ollama either way. ยฒ Cursor's index is editor-locked โ€” external terminal agents can't query it. ยณ Reports token-reduction / efficiency, not a public NLโ†’code retrieval-quality leaderboard. โด Runs on Windows via WSL2. โต SocratiCode manages a bundled Qdrant for you, but uses an auto-detected Ollama for local embeddings. โถ Ships an interactive HTML graph viewer, but doesn't edit code. โท Cursor's local Instant Grep โ€” a literal + regex index it benchmarks at ripgrep 16.8 s โ†’ 13 ms (the post that inspired our own n-gram prefilter). โธ SocratiCode runs on Windows via Docker only โ€” no native binary, and no GPU there.

Where we lose, plainly: no native Windows yet, no editor GUI, and we index one repo at a time. If you need org-wide search across many repos and branches, that's where SocratiCode and Sourcegraph are built to win. If you live inside one editor, Cursor's index is already there. sweet-search is for the terminal agent that wants the best local retrieval on the repo in front of it. No one else combines all of it: ColBERT late-interaction reranking and faster-than-grep search, fully on-device, with nothing to sign up for.

Also in the space: Sourcegraph/Cody (org-scale, server-based), Continue.dev (local-default RAG), Serena (LSP symbol search, no embeddings), grepai (local CLI + trace), and cocoindex-code (embedded AST search).

๐Ÿงฐ The Six Tools

Six small tools, one shared index. Each returns ranked, deduplicated, token-budgeted output designed to be consumed by an agent โ€” a useful answer, not a wall of matches to scroll through.

Tool What you give it What you get back
1. ss-search a natural-language query ranked, self-contained code blocks
2. ss-grep an exact regex/literal every file:line hit, ripgrep-identical
3. ss-find a regex + a query regex matches, semantically re-ranked, as code blocks
4. ss-semantic a file + a question just the relevant spans of that file
5. ss-trace a symbol callers + callees + impact, in one call
6. ss-read a file (ยฑ line range) exact bytes + symbol metadata

1. ๐Ÿ” ss-search โ€” hybrid search powerhouse

A hybrid search pipeline with late interaction reranking that returns actual code blocks.

Leading published-benchmark results โ€” strongest we can find on GenCodeSearchNet, and above every published zero-shot model on CoSQA. See benchmarks.

flowchart TD
    Q(["๐Ÿ”  natural-language query"]) --> ROUTE{{"๐Ÿงญ WASM CatBoost router ยท lexical / hybrid"}}

    ROUTE --> BM["๐Ÿ“‘ <b>BM25F</b><br/>field-weighted FTS5"]
    ROUTE --> ANN

    subgraph ANN ["๐Ÿงฌ three-stage ANN cascade"]
        direction LR
        BIN["binary <b>HNSW</b><br/>Hamming ยท ~100ยตs"] --> INT["INT8<br/>rescore"] --> FL["float32<br/>mmap sidecar"]
    end

    BM  --> FUSE
    ANN --> FUSE
    FUSE["๐Ÿ”€ <b>CCFusion</b><br/>convex combo ยท RRF fallback"] --> ROW1

    subgraph ROW1 [" "]
        direction LR
        IAR["โš“ <b>IAR</b><br/>exact-symbol injection"] --> INTENT["๐ŸŽฏ intent rerank<br/>demote docs ยท tests ยท config"]
    end

    ROW1 --> ROW2

    subgraph ROW2 [" "]
        direction LR
        GRAPH["๐Ÿ•ธ๏ธ graph expansion<br/>typed edges ยท 1โ€“2 hops ยท <b>PathRAG</b>"] --> MAXSIM["๐Ÿงฎ <b>Late-Interaction Rerank</b><br/>โšก native Rust MaxSim kernel"] --> OUT(["๐Ÿ <b>self-contained code blocks</b><br/>whole functions ยท 3k/8k/12k budget"])
    end

    classDef io    fill:#fde68a,stroke:#f59e0b,color:#000;
    classDef out   fill:#bbf7d0,stroke:#15803d,color:#000,stroke-width:3px;
    classDef route fill:#e0e7ff,stroke:#818cf8,color:#000;
    classDef lex   fill:#dbeafe,stroke:#60a5fa,color:#000;
    classDef fuse  fill:#f3e8ff,stroke:#c084fc,color:#000;
    classDef rank  fill:#ffe4e6,stroke:#fb7185,color:#000;

    class Q io;
    class OUT out;
    class ROUTE route;
    class BM,BIN,INT,FL lex;
    class FUSE,IAR fuse;
    class INTENT,GRAPH,MAXSIM rank;

    style ANN  fill:#eff6ff,stroke:#93c5fd,color:#000;
    style ROW1 fill:none,stroke:none;
    style ROW2 fill:none,stroke:none;

โ†‘ The diagram traces the hybrid route. A pure-lexical query โ€” or a literal file path โ€” short-circuits at the router straight to BM25F, skipping the vector cascade and fusion.

Stage What it actually does
๐Ÿงญ Route WASM-exported CatBoost ยท lexical / hybrid ยท ~10 ยตs routing ยท low-confidence โ†’ max-recall hybrid
๐Ÿงฌ Retrieve โ€ข Lexical โ€” BM25F over field-weighted FTS5 (name 10ร— ยท signature 5ร— ยท alias 4ร— ยท doc 1ร—)โ€ข Embed โ€” query vectorized by the local CodeRankEmbed model (swappable for Voyage / Jina / Codestral)โ€ข Vector cascade โ€” binary HNSW (Hamming, 64-byte, ~100 ยตs) โ†’ INT8 rescore โ†’ exact float32 from a memory-mapped sidecar
๐Ÿ”€ Fuse โ€ข CCFusion โ€” convex-combine both rankings ยท per-route weights ยท quantile-normalizedโ€ข MMR (ฮป=0.9) diversity pass over the fused listโ€ข auto RRF (k=60) fallback on degenerate score distributions
โš“ Anchor โ€ข IAR (Identifier Anchor Retrieval) โ€” a real symbol in the query fires an exact-name code-graph lookup that injects that entity, even when the encoder ranked it too low
๐ŸŽฏ Intent Rerank โ€ข demote docs / tests / config when you want implementationโ€ข log-scaled call-site boosts surface the most-referenced function
๐Ÿ•ธ๏ธ Graph Expansion โ€ข typed-edge walks (imports/extends/calls/uses) ยท adaptive 2-hop on the AST graph ยท edges picked by intentโ€ข PathRAG flow pruning + degree normalization โ†’ hubs can't dominate
๐Ÿงฎ Late interaction Rerank โ€ข Query embedded per-token by LateOn-Code (149M; a 17M edge variant auto-selected on low-RAM hosts)โ€ข MaxSim against the pre-indexed quantized token vectorsโ€ข native Rust+Rayon MaxSim kernel โšก ยท WASM-SIMD fallback (1.26 s โ†’ 27 ms on a 231-candidate rerank)
๐Ÿ“ฆ Package โ€ข entity-aware expansion โ†’ whole functions (imports, docstrings, decorators)โ€ข same-file overlap demotion โ†’ diverse, non-overlapping spansโ€ข symbol-family completion (agent mode) โ€” generated/width families surface as a compact indexed manifest instead of truncating silently, inside the same budgetโ€ข auto-selected 3k / 8k / 12k token budget

๐Ÿง  The HNSW, in full (full writeup). Stage 1 is a from-scratch binary HNSW, and every "advanced" trick ships on by default:

  • Heuristic neighbor selection (HNSW Algorithm 4) + M0 = 2M on layer 0 โ€” a real graph backbone, not naรฏve closest-M
  • Shuffled insertion order โ€” no filesystem-ordering bias baked into the highway structure
  • Discovery-rate adaptive early termination + adaptive ef โ€” easy queries stop early, hard ones keep their budget
  • A denser graph than most vendors ship (M=64 ยท efC=800 ยท efS=400) โ€” which broke an 80.6 % โ†’ 86.5 % recall@200 plateau and cut p50 latency ~33 %
  • Zero-GC search: typed-array heaps + generation-stamped visited lists โ€” no per-query allocation
  • 64-byte sign-bit vectors (Hamming) โ†’ INT8 โ†’ exact float32 from a memory-mapped sidecar

โšก Why it's quick. A native Rust + Rayon MaxSim kernel (47ร— over scalar; 16ร— WASM-SIMD fallback) ยท int4-quantized, binary-packed token vectors (plain INT4 is the shipped path โ€” the full TurboQuant algorithm is researched but deferred; binary packing alone cut the LI index ~3.4ร—, 1.34 GiB โ†’ ~396 MiB) ยท a memory-mapped float32 sidecar that skips SQL on the rescore hot path ยท score-spread adaptive pooling (decisive queries shrink the rescore pool, ambiguous ones widen it) ยท and a warm daemon that answers in a single NAPI call โ€” no process is ever forked.

๐ŸŽ›๏ธ Priors & structure.

  • Quality priors: every chunk carries a 0โ€“1 prior from test proximity, git recency, symbol centrality (PageRank), comment density, and complexity โ€” production code surfaces, stale fixtures sink.
  • Community structure: a canonical Leiden pass detects code communities on the entity graph at index time, feeding vocabulary prewarming and structural signals โ€” it understands your modules, not just your directories.
  • Multilingual: 14 languages get full tree-sitter AST treatment; a 39-config registry covers 70+ extensions beyond that. Router features handle camelCase/snake_case, CJK density, and German compounds.
  • Format-gated signals: structure-aware boosts and demotions (symbol-exact, path-token, anomalous-chunk, mega-entity) fire only in agent mode โ€” they help agent-shaped queries and would hurt plain NL, so they stay gated by default.

๐Ÿ›Ÿ Rescues & honest trade-offs.

  • Long-query rescue: wordy NL queries that FTS5 would tokenize into an unsatisfiable AND fall back to multi-query BM25F + RRF โ€” one query per content keyword, fused.
  • Near-duplicate dedup: a SimHash + MinHash-LSH pass (Jaccard ฯ„=0.9) clusters copy-paste and vendored code at index time; aliases reuse their exemplar's vectors and skip both the bi-encoder and late-interaction encoding.
  • A negative result we ship anyway: we built a full cross-encoder rerank cascade behind an adaptive confidence gate, measured it on our eval sets โ€” and it didn't beat MaxSim at 3ร— the latency. So it ships disabled (SWEET_SEARCH_CASCADE_ENABLED=true to try it). We'd rather ship the faster path than a fancier diagram.
  • Budget tiers: the expensive 8k/12k tiers fire on ~1โ€“5 % of queries โ€” the default stays cheap. Force one with --full / --xl, or pick a mode with --mode lexical|semantic|hybrid|pattern.

Also available as sweet-search "<query>" on the CLI and the search MCP tool.


2. โšก ss-grep โ€” grep, minus every wasted millisecond

10.2ร— faster than ripgrep end-to-end at the median โ€” measured across 353 realistic queries on 5 real repos (range 8.5โ€“17.7ร— per repo, 1 ms p50), with identical match counts on every single query. Three things buy that:

  • A sparse n-gram index (inspired by Cursor's fast-regex-search and GitHub's Blackbird): instead of a fixed trigram table, gram boundaries adapt to your codebase's character-pair frequencies, so common trigrams get absorbed into longer, more selective grams.
  • Regex-AST literal extraction + SIMD intersection: required substrings are pulled from the pattern's syntax tree, posting lists are intersected with NEON/SSE2 block merges (galloping search for skewed sizes), and only the files that can match โ€” typically 0.1โ€“5% of the corpus โ€” see the real regex.
  • Fully in-process: verification runs on Rust's regex crate with Rayon across all cores, inside the warm daemon, in a single NAPI call. No child process is ever spawned โ€” zero fork/exec, zero pipe I/O, zero JSON re-parsing.

Every match comes back in stable file:line order โ€” ripgrep-identical counts, optional context lines โ€” with no relevance guessing, no subprocess, in one warm call.

  • Full methodology, per-repo table, and the optimization log: docs/GREP_INDEXING_STRATEGY.md.
  • Regexes with no extractable literals fall back to native grep over the indexed file set; fixed-string and glob queries use a ripgrep fallback.
  • Dialect recovery (agent mode): patterns written in GNU-grep BRE muscle memory (foo\|bar, \(group\)) are literals in Rust's regex dialect and used to silently match nothing โ€” a zero-hit exact search now gets one gated auto-retry with the translated pattern instead of a false "no matches".

3. ss-find โ€” ColGrep, on a faster engine

ss-find "token refresh logic" --regex "refresh.*[Tt]oken"

Inspired by LightOn's ColGrep โ€” regex precision, semantically ranked โ€” but rebuilt on our own substrate:

  • The regex stage runs on the same indexed sparse-gram engine as ss-grep (in-process, no subprocess), not a filesystem scan.
  • The ranking stage scores candidates with per-token MaxSim over pre-indexed late-interaction embeddings โ€” no model inference over documents at query time โ€” on our custom kernels: native Rust + Rayon takes a 231-candidate MaxSim pass from 1.26 s down to 27 ms (WASM SIMD fallback at 16ร—).
  • Regex tokens are merged into the semantic query, so the ranking sees both what you typed and what you matched.
  • Like ss-search, it answers with ranked, self-contained code snippets โ€” not bare file:line โ€” so the find and the read collapse into one tool call. In our 30-question agent-workflow eval that eliminated every follow-up read and cut tokens 25.4% vs a grep + read workflow, at quality parity (gap of 0.01 on a 5-point scale).
  • On the 60-query pattern benchmark, MaxSim ranking lifts MRR@10 to 0.45 vs 0.11 for raw grep ordering โ€” 4ร— more likely the right hit lands on top.
  • Requires the late-interaction index (built by default; --li-model none disables pattern mode).
  • Also available as sweet-search --mode pattern and via the search MCP tool's regex argument.

4. ss-semantic โ€” hybrid retrieval, scoped to one file

ss-semantic src/auth/session.ts "where does the cookie get its expiry?"

You know the file; this finds the lines. Every indexed chunk of the file is scored by three independent signals โ€” BM25-style lexical term match, exact symbol-name match (weighted 1.5ร—), and per-token MaxSim late interaction over the LateOn-Code embeddings โ€” fused with Reciprocal Rank Fusion (k=60), with symbol-less fragment chunks demoted 0.85ร— so real definitions win ties. The top spans are then re-read from disk (ยฑ2 context lines, overlapping spans merged), so the answer is filesystem ground truth even mid-edit; if the file is newer than its index entry you get an explicit staleness warning.

The useful answer: just the relevant spans with line numbers โ€” not the whole file through your context window.

  • Unindexed files degrade gracefully to a plain read. Defaults: top 5 spans, relevance threshold 0.4, 8k-char cap.
  • Also available as sweet-search read-semantic and the read-semantic MCP tool.

5. ss-trace โ€” graph algorithms, not grep guesswork

ss-trace processOrder --in src/orders/service.py

One call returns a symbol's callers, callees, and transitive impact paths from the AST-derived code graph (entities + typed calls/imports/extends/uses edges, persisted in SQLite at index time). Ranking fuses three signals:

  • Query-time Personalized PageRank via Forward Push โ€” a local algorithm that spreads mass directionally from your target symbol and touches only the neighborhood it reaches, never the whole graph;
  • Index-time edge-weighted global PageRank (damping 0.85), precomputed into a page_rank column โ€” a function called from five sites carries five units of mass, and it costs zero at query time;
  • Structural heuristics โ€” relationship type, depth, exported-API status, fan-in โ€” with penalties for test-only and external paths.

Because the graph is prebuilt, the global ranking is precomputed, and the personalized walk is local, a full three-section trace costs milliseconds. The relation word (callers / callees / impact) re-weights how the response token budget is split; --in disambiguates duplicate names; --depth bounds impact traversal (1โ€“4).

  • Honest caveat: call-graph extraction is precise but incomplete on highly dynamic code (bare-name dispatch, metaprogramming) โ€” traces can be sparse there, and the agent prompt teaches a recovery strategy for exactly that case.
  • Also available as sweet-search trace and the trace MCP tool.

6. ss-read โ€” exact bytes, with the index's knowledge attached

ss-read src/db/pool.js 120 180

A read tool that is filesystem-grounded by construction: bytes come straight from disk (never from the index, so never stale), but each indexed file arrives annotated with its cAST chunk metadata โ€” symbol name, entity type, signature, line span โ€” joined from the AST chunk index. The agent gets the code and the structural map of what it's looking at in one call: cite, navigate, or trace next without another search.

  • The CLI/MCP form scales it up: sweet-search read <file...> (and the read MCP tool) batches 1โ€“20 files in a single call, each with the same symbol metadata โ€” twenty files for the price of one tool invocation.
  • Query-aware continuation (agent mode): a range read that stops before EOF names the unread symbols below it โ€” ranked by relevance to the session's recent queries, not just declaration order โ€” plus the exact command to continue.
  • Shown-span receipts (agent