sgrep README

The project's README from github.com/context-dot-dev/sgrep. As one markdown file: README.md.

Context.dev

sgrep

Search code and documents in plain English. Runs locally.

Why sgrep

Agents often know what code should do before they know a name to search. sgrep finds local passages by words and meaning. It can also rank the results of a focused ripgrep command. No account, hosted index, or model server is needed.

When to use ripgrep, CK, or mgrep
  • ripgrep is the right tool for known names, exact text, and regexes. For an intent query, an agent must first choose useful patterns. Broad patterns can return too much; narrow ones can miss relevant code.
  • CK offers local semantic and hybrid search, several embedding models, and an MCP server. Account for index construction and updates as well as query time. Its semantic mode beats sgrep on our CoSQA test. Our CK results use BGE Small, not every CK model or mode.
  • mgrep offers hosted semantic search, reranking, and agent integrations. It syncs files to Mixedbread and needs authentication. Agents must account for sync completion, network access, and upload limits. It is not measured in this benchmark.

Use sgrep when local semantic discovery and a small CPU model suit the job. The benchmark notes also record CK query-parser failures and missing indexed files.

Install

Requires Rust 1.90 or later and ripgrep.

brew install ripgrep
cargo install --git https://github.com/context-dot-dev/sgrep --locked

Or download a macOS Apple Silicon binary. Remove any older Python install with uv tool uninstall sgrep or pip uninstall sgrep first.

sgrep "when does a failed scrape consume credits" ./src

Results show the file, line range, and source. Use -n 10 for ten results or --json for JSON output.

To rank only the results from ripgrep:

rg --json -C 3 'creditCost|shouldBill' ./src \
  | sgrep "when does a failed scrape consume credits" --stdin

Run both commands from the same directory. Use ripgrep for exact matches; sgrep can return approximate matches.

The first search downloads a model (32–34 MB) and any required code parsers. Later searches can run offline. Source and queries stay on your machine. The local index stores copies of source passages.

Code and documents

Auto mode selects the text model only when all candidate passages have prose extensions, such as .md or .txt. Mixed code and prose use the code model. Text mode targets general English prose. To choose explicitly:

sgrep "retry with exponential backoff" ./src --model code
sgrep "how do refunds work" ./docs --model text

Code uses syntax-aware chunks where supported. Other text uses text chunks. This does not parse PDFs or images. Both modes return source passages, not generated answers. The benchmarks below measure code retrieval, not document search.

Static embeddings

A static model stores one learned vector per token. The code model distills CodeRankEmbed and trains on code/query pairs. sgrep looks up those vectors, averages them, and normalizes the result to 256 numbers. Related text can have similar vectors without sharing exact words. There is no transformer pass at search time. This supports local CPU search with a small model and no per-query API call.

Averaging loses token order and can miss context. sgrep combines semantic scores with BM25 and gives exact identifiers priority. A high score is a ranking signal, not proof that code performs a task.

Benchmarks

SWE-bench Verified: LLM API cost per attempt versus solved attempts, using GPT-6 Luna on 50 tasks with two repeats.

Piped sgrep used 21.3% less LLM API spend than ripgrep, with 70/100 vs. 68/100 solved attempts. Costs include prompt caching and retrieval LLM calls. Code, results, methodology and chart exclusions.

Bar charts comparing sgrep, CK, Jevgrep and ripgrep on RepoQA and CoSQA.

600 RepoQA questions and 500 CoSQA questions. sgrep leads on complete-function retrieval; CK semantic leads on snippet retrieval.

Repeated local CLI latency on RepoQA and CoSQA.

Latency uses 120 fixed queries, six repeats, and fresh CLI processes. Models and indexes are warm. Results, setup costs, and method.

Reference

Search options
  • --stdin: rank only the supplied ripgrep match and context blocks.
  • --rg-json FILE: add saved ripgrep results to a search. Use - to read from stdin.
  • --model code or --model text: select a model. Auto mode selects text when all candidate passages are prose, and code otherwise.
  • --json --explain: include lexical, semantic, and combined scores.

Ripgrep paths are relative to the current directory. Files must be within the search path and match the current source. Added ripgrep results can include hidden or ignored files. Normal searches follow ripgrep's ignore rules and skip hidden and binary files.

Auto mode treats .md, .mdx, .txt, .rst, .adoc, .org, and .text as prose. Extension matching ignores case.

Exit codes: 0 for results, 1 for no results, 2 for errors. Empty piped input returns [] with --json.

Cache controls
  • --refresh-cache: rebuild the search index. Cached models allow offline use.
  • --no-cache: search without reading or writing the index.
  • --cache-dir DIR: store indexes, models, and parsers in one directory.
  • --fresh-assets: use temporary model and parser downloads. Requires network access.
  • HF_HUB_OFFLINE=1: prevent model and parser downloads.

Each search checks file content. Changes to files, ignore rules, or models invalidate the index. Source is checked again before results are returned. Freeze files when you need repeatable measurements. Warm search still checks files and scans stored vectors. Changed source rebuilds the scope's index. Piped ranking does not use the index.

The index cache has limits of 256 MiB and 128 entries. Cleanup removes the least recently used entries and entries unused for 30 days. Set SGREP_CACHE_MAX_BYTES to change the size limit; use 0 to disable the index cache. Large entries are not saved. Cache failures fall back to a search without the index. Source copies remain until cleanup or manual deletion. Models and parsers are outside these limits.

Cache locations, in priority order:

  • Index: SGREP_CACHE_DIR, XDG_CACHE_HOME/sgrep, ~/.cache/sgrep.
  • Models: HF_HUB_CACHE, HUGGINGFACE_HUB_CACHE, HF_HOME/hub (default ~/.cache/huggingface/hub).
  • Parsers: TREE_SITTER_LANGUAGE_PACK_CACHE_DIR, then the platform cache under tree-sitter-language-pack/v<version>.

--cache-dir overrides these paths. Index files have private permissions on Unix. Model files are checked against pinned hashes. Parser downloads use archive checksums. Temporary downloads are removed on normal exit; forced termination can leave files behind. Refresh options do not clear the operating system's file cache.

How search works

Ripgrep lists files. Rust splits them into passages with Chonkie and Tree-sitter. Code parsers support Python, C/C++, C#, Go, Java, Rust, JavaScript/JSX, and TypeScript/TSX. Other files use text splitting. Passages target 2,048 characters and keep whole lines.

Search combines the top 200 lexical matches with the top 200 semantic matches. Each embedding uses the file path and passage text. Scores combine 75% semantic and 25% BM25 after scaling each to 0–1. Exact, case-sensitive identifier matches rank first. In longer queries, this applies to names with camelCase, underscores, dollar signs, or digits. Scores are relative to the candidates, not confidence values. Piped mode ranks only the supplied passages. Results fully contained in earlier results are removed.

The models are Minish Lab's Potion Code 16M v2 and Potion Base 8M. Both use fixed revisions and an MIT license.

Development
cargo build --release --locked
PATH="$PWD/target/release:$PATH" python3 tests/e2e.py > e2e-results.json
PATH="$PWD/target/release:$PATH" python3 tests/codechunker.py > chunker-results.json
PATH="$PWD/target/release:$PATH" python3 tests/hybrid.py > hybrid-results.json
PATH="$PWD/target/release:$PATH" python3 tests/discovery.py > discovery-results.json
SGREP_BASELINE=/path/to/before SGREP_CANDIDATE="$PWD/target/release/sgrep" python3 tests/index.py > index-results.json
python3 tests/cache_lifecycle.py target/release/sgrep target/cache-lifecycle-results.json
python3 tests/cache.py target/release/sgrep target/asset-cache-results.json --online

These E2E checks use real models and save JSON receipts. To compare builds, run python3 tests/benchmark.py BEFORE AFTER queries.json results. Each query needs id, query, and an absolute root path. Add --refresh-cache to rebuild indexes before timing.

MIT · Context.dev

sgrep (context-dot-dev/sgrep)

Searching Database…

307 ·GitHub
这是做什么的?sgrep 是一个本地搜索工具,用大白话描述需求就能找到代码和文档中的相关内容。它把语义向量匹配和 ripgrep 式的精确文本匹配结合起来,不需要注册账号,也没有托管索引。
sgrep 是命令行工具还是程序库?它是一个命令行工具,用来包装 ripgrep 的搜索结果并做排序,不是可以导入到代码里使用的程序库。
怎么安装和运行 sgrep?先安装 Rust 1.90+ 和 ripgrep,然后自己构建 sgrep;或者直接下载现成的 macOS Apple Silicon 二进制文件。如果装过旧版 Python 版本,先用 'uv tool uninstall sgrep' 或 'pip uninstall sgrep' 卸载掉。
用 sgrep 之前需要准备什么?你需要在系统上装好 Rust 1.90 或更新版本以及 ripgrep;不过如果你用的是 macOS Apple Silicon 的预编译二进制文件,就不需要这些。
sgrep 能处理 PDF 或图片吗?不能。sgrep 只索引纯文本的源代码和文档,不支持解析 PDF 或图片。另外第一次搜索前需要先下载一次模型,之后才能离线使用。
sgrep 可以在没有网络的情况下用吗?可以。第一次搜索会下载一个很小的向量模型(32-34 MB)和解析器,之后所有搜索都可以完全离线进行。
我的代码或搜索内容会传到外面去吗?不会。sgrep 完全在本地运行,没有账号、托管索引或模型服务器,你的源代码和搜索内容都只留在自己的电脑上。
sgrep 和 ripgrep、CK 或 mgrep 有什么区别?ripgrep 擅长精确匹配名字、文本和正则表达式,但需要使用者自己写出合适的搜索模式;CK 通过 MCP 服务器提供本地语义搜索和混合搜索,但需要维护索引,而且在 CoSQA 数据集上的表现比 sgrep 好;mgrep 是托管服务,需要登录认证和文件同步。sgrep 主打本地、免账号的语义搜索,用的模型很小,在 CPU 上就能跑。
sgrep 用的是什么向量模型?代码用的是 Minish Lab 的 Potion Code 16M v2,文本用的是 Potion Base 8M,两者都是静态向量模型,版本固定,采用 MIT 许可证。
sgrep 是怎么给搜索结果排序的?它会取出文本匹配前 200 条和语义匹配前 200 条,归一化后按语义 75%、BM25 25% 的权重打分,同时会优先考虑大小写完全一致的标识符精确匹配。
sgrep 在做代码感知分块时支持哪些编程语言?它用 Tree-sitter 解析 Python、C/C++、C#、Go、Java、Rust、JavaScript/JSX 和 TypeScript/TSX;其他类型的文件则退回到按纯文本切分。
Size
2.7 MB
Stars
307
Age
10d
Commits · 90 Days