An open API service indexing awesome lists of open source software.

https://github.com/bvolpato/ivygrep

Semantic Grep - Superpower Your LLM
https://github.com/bvolpato/ivygrep

embedding fastgrep ivygrep llm mcp mit productivity ripgrep

Last synced: 6 days ago
JSON representation

Semantic Grep - Superpower Your LLM

Awesome Lists containing this project

README

          


ivygrep logo


Semantic code search that never uploads your code.

Ask questions in English. Get answers in code. Local inference.


CI
Security
Relevance
Latest Release
License: MIT
Downloads


ivygrep semantic code search


Website ·
Benchmarks ·
AI Agents ·
Architecture ·
Contributing

---

## ⚡ Quick Start

**Install via Homebrew (recommended):**
```bash
brew install bvolpato/tap/ivygrep
```

**Linux / macOS:**
```bash
curl -fsSL https://raw.githubusercontent.com/bvolpato/ivygrep/main/install.sh | sh
```

**Windows PowerShell:**
```powershell
irm https://raw.githubusercontent.com/bvolpato/ivygrep/main/install.ps1 | iex
```

Installers pick the right archive, verify its SHA-256 checksum, install `ig`,
and print the installed version. PowerShell also updates the user `PATH`.
Windows uses the same USearch ANN backend as Linux and macOS, Rust-managed
persistence, long-path support, and a statically linked Visual C++ runtime.

Every release ships checksums, SPDX JSON SBOMs, and provenance sidecars. CI
extracts and runs the exact archive bytes before publishing:

| Target | Release behavior | Offline fallback |
|---|---|---|
| Linux x86_64 musl | Static binary, baseline x86-64 exercised under QEMU `qemu64` | Hash search, no model or service |
| Linux aarch64 musl | Static binary exercised under ARM64 QEMU in Alpine | Hash search, no model or service |
| macOS Intel | Native archive with Accelerate-backed local neural inference | Hash search |
| macOS Apple Silicon | Native archive with Accelerate-backed local neural inference | Hash search |
| Windows x86_64 | Native USearch ANN plus local CPU neural inference | Hash search |

Archive checks cover startup, indexing, hybrid/hash/literal/regex search,
daemon equivalence, status/doctor, stale-index rebuild, and removal. `ig`
needs no Python, compiler, system database, or external service. Neural mode
may download its pinned model once; `--hash` and hash-only builds do not.

Quality, latency, footprint, release size, unavailable comparisons, and the
claim policy live in the
[evidence dashboard](https://bvolpato.github.io/ivygrep/benchmarks/evidence-dashboard.html).

**Build from source:**
```bash
git clone https://github.com/bvolpato/ivygrep.git && cd ivygrep
./build.sh
install -m 0755 ./target/release/ig ~/.local/bin/ig
```

**Developer targets:**
```bash
./build.sh --help
./test.sh --help
./bench.sh --help

./build.sh # release binary
./build.sh --features accelerate,metal # opt-in macOS Metal neural inference
./build.sh --features cuda # opt-in Linux CUDA neural inference
./test.sh --quick # fast local check
./test.sh # fmt, clippy, unit/integration tests
./bench.sh # critical Criterion benchmark, no stale local baseline comparison
```

**Your first search:**
```bash
ig "authentication flow" # auto-indexes on first run, then searches
ig "error handling" src/api/ # scope to a directory
ig --all "database migrations" # search across all indexed projects
```

No config, prompts, or API keys. First run auto-indexes the workspace and
starts a background daemon for incremental updates. Neural mode may download
model artifacts once; `--hash` and hash-only builds do not.


ivygrep demo: searching the opencode repo

---

## 🤖 MCP server for AI agents

Use `ig --mcp` when an agent needs code search without loading whole files into
context.

```bash
ig --mcp # starts MCP server on stdio
```

Before connecting an agent, run `ig --version` in the same environment that
launches it. GUI applications may not inherit your interactive shell's `PATH`;
use the absolute path to `ig` or `ig.exe` in that case.

### Setup for coding agents

Claude Code

```bash
claude mcp add -s user ig -- ig --mcp
```
Or add to `~/.claude.json`:
```json
{
"mcpServers": {
"ig": { "type": "stdio", "command": "ig", "args": ["--mcp"] }
}
}
```

Cursor

Add to `.cursor/mcp.json` or `~/.cursor/mcp.json`:
```json
{
"mcpServers": {
"ig": { "type": "stdio", "command": "ig", "args": ["--mcp"] }
}
}
```
Then refresh MCP servers in Cursor settings.

Gemini

```bash
gemini mcp add --scope user --transport stdio ig ig --mcp
```
Or add to `~/.gemini/settings.json`:
```json
{
"mcpServers": {
"ig": { "command": "ig", "args": ["--mcp"] }
}
}
```

Codex

```bash
codex mcp add ig -- ig --mcp
codex mcp get ig --json
```

The CLI and IDE extension share `~/.codex/config.toml`. Trusted repositories
can instead use a project-scoped `.codex/config.toml`.

OpenCode

Add to `opencode.json`:
```json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"ig": {
"type": "local",
"command": ["ig", "--mcp"],
"enabled": true
}
}
}
```

### Recommended agent behavior

Give the agent this persistent instruction in `AGENTS.md`, `CLAUDE.md`,
`GEMINI.md`, or the equivalent rules file:

```text
Use the ivygrep MCP tools for code discovery before broad filesystem scans.
Pass the absolute current repository or worktree path to ig_search.
Use natural-language queries for concepts and literal=true for exact identifiers.
Use limit to choose retrieval breadth and context to choose source lines per hit.
Start with limit=5-10 and context=2. Increase context when a promising hit needs
more evidence; increase limit when you need more candidate files.
Use ig_status when indexing health is unclear.
```

`ig_search` is restricted to the supplied workspace, auto-indexes on first use,
starts incremental watching, and accepts subdirectory or file paths for narrower
scope. In a Git worktree, pass that worktree's root: ivygrep reuses the shared
base index and stores only overlay deltas and tombstones.

See [Coding agent integration](AGENT_INTEGRATION.md) for verified configs,
tool-selection guidance, worktree behavior, and troubleshooting.

---

## 🤔 What is ivygrep?

**ivygrep (`ig`)** is local semantic code search. It mixes BM25/literal lookup
with vector search, so queries can describe intent instead of exact tokens.

| Feature | `grep` / `rg` | GitHub Search | [zoekt](https://github.com/google/zoekt) | **ivygrep** |
|---------|:---:|:---:|:---:|:---:|
| Works offline | ✅ | ❌ | ✅ | ✅ |
| Natural language queries | ❌ | ⚠️ | ❌ | ✅ |
| Semantic understanding | ❌ | ❌ | ❌ | ✅ |
| Warm indexed query latency | ✅ | ❌ | ✅ | ✅ |
| Privacy-first (no upload) | ✅ | ❌ | ✅ | ✅ |
| Git-native worktrees/branches | ❌ | ❌ | ❌ | ✅ |
| Structural code chunking | ❌ | ❌ | ⚠️ | ✅ |
| Incremental indexing | ❌ | ❌ | ❌ | ✅ |
| MCP server for AI agents | ❌ | ❌ | ❌ | ✅ |

### 🌍 45 language/file types

ivygrep indexes 45 language/file types. 24 use Tree-sitter AST chunking:
Rust, Python, Go, JavaScript, TypeScript/TSX, Java, C, C++, C#, Scala, Kotlin,
PHP, Ruby, Swift, Elixir, Zig, Bash, Haskell, OCaml, Lua, Dart, Objective-C,
Perl, and Starlark macros/targets in very large BUILD-like sources.

- **Systems:** Rust, C, C++, Zig, Nim
- **Backend:** Python, Go, Java, Kotlin, Scala, C#, Ruby, PHP, Perl, Groovy
- **Web & Mobile:** JavaScript, TypeScript, HTML, CSS, GraphQL, Swift, Dart, Objective-C
- **Functional:** Haskell, OCaml, Elixir, Erlang, Clojure
- **Data, Scripting & Config:** R, Julia, Bash/Shell, PowerShell, Lua, SQL, Protobuf, Thrift, Terraform, Starlark/Bazel, Dockerfile, Makefile, Markdown, XML, TOML/YAML/INI/env config, JSON, plain text

Unknown extensions are auto-detected and indexed as text.

---

## 🚀 Performance and speed

Release-readiness validation used a **Linux kernel** checkout with 93,502
indexed files and 4,419,660 chunks:

| Scenario | Metric | Result |
|------|------|-----:|
| Fresh lexical-first Linux kernel index | full rebuild | ~270 sec |
| Large-repo natural query | process-cold p95 | ~137 ms |
| Warm daemon identical-query replay | end-to-end p95 | ~79 ms |
| Warm daemon distinct queries | end-to-end p95 | ~116 ms |
| Portable Linux intent relevance | 13 labeled queries | 41.20 |
| Best retained dedicated-host daemon run | identical-query p95 | ~4.9 ms |
| Historical eager-vector Linux kernel index | full rebuild | ~27.3 min |
| Lexical-first scoped stress probe | 10,501 files | ~3 sec |
| Warm daemon correctness guard | daemon/local hits | 20 / 20 |

Latency depends on CPU, storage, repository shape, index state, and
virtualization. Public quality, latency, refresh, and resource evidence lives
under [`docs/benchmarks/`](docs/benchmarks/).

Indexing publishes BM25/literal search first. A load-aware background process
builds hash ANN vectors, then upgrades to the portable 256-dimensional
`static-retrieval-v1` model selected by the public embedding bake-off. Optional
profiles remain available through `IVYGREP_MODEL_PROFILE`: `potion-code`,
`general`, `code`, and `code-hq`. Model identity is stored with the index, so
incompatible vectors are rebuilt.

Resource knobs:

- `IVYGREP_NEURAL_THREADS`: desired transformer worker ceiling.
- `IVYGREP_NEURAL_MEMORY_MB`: smaller explicit memory budget for worker sizing.
- `IVYGREP_NEURAL_BATCH_SIZE`: local benchmark override for background batches.
- `IVYGREP_NEURAL_ACCELERATOR_HANDLES`: shared-model CUDA/Metal concurrency.
- `IVYGREP_NEURAL_FOREGROUND_ACCELERATOR=0`: force CPU query embedding.

CUDA builds read `nvidia-smi` free VRAM, total VRAM, and utilization before
choosing batch size. Linux memory accounting honors effective cgroup limits,
including containers.

Relevance evaluation separates foreground readiness from post-background hash
quality:

```bash
uv run scripts/eval_relevance.py
uv run scripts/eval_relevance.py --enhance-hash
uv run scripts/run_public_benchmark_matrix.py \
--profile public-core \
--datasets-root /tmp/ivygrep-public-datasets \
--work-root /tmp/ivygrep-public-results \
--output public-code-retrieval-results.json
```

The public matrix pins 20 CoIR task/language variants plus a compact
1,000-query, 48-language baseline. Reports include checksums, quality, variance,
latency, memory, and index size under [`docs/benchmarks/`](docs/benchmarks/).

---

## 🏗️ Architecture and git

Git behavior is part of the index design:
- **Worktree overlays:** Reuses one base search index. Per-worktree SQLite, lexical, and vector stores contain only divergent chunks and tombstones; lightweight Merkle metadata tracks filesystem state.
- **Branch-switch deltas:** Merkle reconciliation re-indexes *only* changed files upon branch switch instead of rebuilding the search index.
- **Content-based deduplication:** Byte-identical files are never re-indexed across branches.
- **`.gitignore` native:** Respects rules automatically at every level.

**Tech stack:** `tantivy` (BM25), `usearch` (ANN), `tree-sitter` (AST), SQLite
symbol/call graph storage,
`candle_embed` / `candle-core` (local neural embeddings), and `xxh3` hashes.

---

## 🔒 Security and privacy

ivygrep runs search and embedding inference locally. It never sends code,
queries, or index data to an external service.

- **Where data lives:** compressed source chunks live under `~/.local/share/ivygrep` (or `$XDG_DATA_HOME`/`$IVYGREP_HOME`). Unix uses an owner-only `0600` socket plus peer-uid verification. Windows uses loopback TCP with a per-daemon token beside the user-owned index. Keep custom `IVYGREP_HOME` paths private.
- **Model download:** neural mode downloads revision-pinned assets with `hf-hub` on first use and caches them under `$HF_HOME` or `~/.cache/huggingface`. Use `--hash` or a `--no-default-features` build when model assets must never be downloaded.
- **Inference backend:** release binaries run locally: Accelerate-backed CPU math on macOS, CPU on Linux/Windows. Source builds can opt into Metal (`--features accelerate,metal`) or CUDA (`--features cuda`). CUDA does not require cuDNN. Set `CUDA_COMPUTE_CAP` explicitly when auto-detection is wrong; `ig --status` reports the backend that last generated neural vectors.
- **Resource controls:** indexing refuses to start below 512 MiB available memory, background enhancement pauses below 1 GiB, and optional transformer workers share model weights plus an adaptive memory budget. These checks use native available-memory reporting on macOS and Windows and cgroup-aware reporting on Linux.
- **Secrets in your repo:** ivygrep indexes file *contents*, including config/dotfiles (e.g. `.env`) unless they're gitignored. Those contents are stored in the local index and can appear in search snippets. Keep secrets out of the workspace or in `.gitignore`.
- **MCP scope:** `ig_search` only searches the workspace at the supplied `path`.

---

## 🔧 CLI reference

```bash
# Core workflow
ig "your query" # search current workspace
ig "query" ~/other/project # search a different workspace
ig --add . # register & index a workspace
ig --rm . # unregister a workspace
ig --status # show workspace health & embedding status
ig --doctor # inspect index health for the current workspace
ig --doctor --deep # run full cross-store integrity scans
ig --doctor --fix # rebuild a broken or stale index

# Search modes
ig --interactive "query" # interactive TUI with file/snippet browsing
ig --literal "fn_name" # fast exact-match search (index-backed)
ig --lexical-only "query" # BM25/path/signature retrieval only
ig --hash "query" # force hash embeddings (skip neural)
ig --symbol calculate_tax # exact definitions
ig --refs calculate_tax # indexed references/calls
ig --callers calculate_tax # caller chunks

# Output control
ig -n 5 "query" # at most 5 ranked result files
ig -C 4 "query" # up to 4 lines before and after each match
ig -n 5 -C 8 "query" # 5 files with richer snippets
ig --type rust "query" # filter by language
ig --include "*.rs,*.go" "query" # include globs
ig --exclude "vendor/**" "query" # exclude globs
ig --json "query" # machine-readable JSON
ig --first-line-only "query" # compact grep-style output
ig --file-name-only "query" # file paths only

# Daemon and server
ig --daemon # start background watcher
ig --mcp # start MCP server (stdio)
```

`--limit` controls retrieval breadth. `--context` controls snippet size.
Neither is a relevance threshold.

| Control | What it changes | Ranking |
|---|---|---|
| `-n N`, `--limit N` | Searches a candidate pool sized for the request and returns at most `N` ranked files | The same relevance signals apply; a deeper pool can slightly change ranks |
| `--no-limit` | Uses maximum candidate budgets and returns every result that survives relevance filtering | Can change ranks and is slower |
| `-C N`, `--context N` | Shows up to `N` source lines before and after each focused match | Unchanged |
| `--first-line-only` | Reduces each result to one preview line after retrieval | Unchanged |
| `--file-name-only` | Returns paths only; without `-n`, the CLI also uses maximum candidate budgets | Unchanged with `-n`; without `-n`, the deeper pool can change ranks |

- Smaller limits truncate ranked files. Larger limits search deeper and can
slightly rerank top results.
- `--no-limit` uses maximum candidate budgets and can be much slower.
- `-C`, `--first-line-only`, and `--file-name-only -n N` change presentation
after retrieval.
- `--file-name-only` without `-n` also uses maximum candidate budgets.
- Agents should start with `-n 5` to `-n 10` and `-C 2`. Increase context for
more lines from the same file; increase limit for more candidate files.
- Scores order one query's results. They are not global confidence values.
- ivygrep does not expose a total token-budget parameter.

---

## 🧪 Development

```bash
./test.sh # fmt, ShellCheck, clippy, Rust and Python harness tests
./build.sh --locked # release binary, Cargo.lock unchanged
./build.sh --locked --features accelerate,metal # opt-in macOS Metal neural binary
./build.sh --locked --features cuda # opt-in Linux CUDA neural binary
./bench.sh # critical Criterion benchmark, no stale local baseline comparison
```
Tests cover unit behavior, CLI snapshots, concurrency, golden queries, public
retrieval metrics, symbols/callers, incremental CRUD, MCP, daemon recovery,
git/worktrees, Merkle properties, and benchmark guards. Criterion repeats short
operations inside stable timed samples.

### End-to-end procedures
```bash
./build.sh
./scripts/e2e_procedures.sh --binary ./target/release/ig
python3 scripts/check_daemon_equivalence.py \
--skip-build \
--binary ./target/release/ig \
--bench-home /tmp/ivygrep-daemon-equivalence

# Opt-in macOS Metal backend validation. Downloads local model artifacts once.
./build.sh --locked --features accelerate,metal
./scripts/e2e_neural_backend.sh --binary ./target/release/ig --model-profile general --expect-backend "Candle Metal"

# Opt-in Linux CUDA backend validation. Downloads local model artifacts once.
./build.sh --locked --features cuda
./scripts/e2e_neural_backend.sh --binary ./target/release/ig --model-profile general --expect-backend "Candle CUDA"
```
Smoke tests use throwaway projects and isolated `IVYGREP_HOME` directories. The
neural backend check embeds fixture text locally and verifies backend reporting.

### Stress testing
```bash
./scripts/bootstrap_stress_fixtures.sh
./test.sh --stress
```

## Roadmap

- **More Tree-sitter languages:** add SQL and other mature grammars.
- **Evidence-backed search program:** track the quality,
latency, footprint, and portability work in
[#128](https://github.com/bvolpato/ivygrep/issues/128).
- **Learned reranking:** evaluate compact local cross-encoders against the
bounded deterministic reranker without weakening offline portability.
- **Editor integrations:** VS Code and Neovim Telescope.
- **Background job resilience:** better queue diagnostics and resumable worker state.

## Contributing

Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

---


Built by @bvolpato · Released under the MIT License