On-device embedding Β· AST-aware chunking Β· Incremental indexing Β· MCP-native
Zebra indexes your codebase locally β parsing source files with tree-sitter, embedding each symbol and chunk with an on-device transformer model (via Candle), and storing everything in LanceDB β so AI agents can search code by meaning, not by string matching.
It runs entirely on your machine. No data leaves your computer. No API keys. No cloud dependency.
When an agent explores a codebase, it spawns sub-agents that scan files with grep, glob, and Read β consuming tokens on every tool call. Zebra gives those agents a pre-built semantic index β symbol relationships, call graphs, and code structure β so they query the index instantly instead of scanning files.
cargo install --git https://github.com/hicaru/zebra_tree_indexerOr build from source:
git clone https://github.com/hicaru/zebra_tree_indexer.git
cd zebra_tree_indexer
cargo build --release -p zebraragThe terminal UI walks you through model selection, downloads, daemon launch, and indexing:
zebrarag# Index a project
zebrarag index -r /path/to/your/project
# Search by meaning
zebrarag search -r /path/to/your/project "rate limiting middleware"
# Interactive search loop
zebrarag chat -r /path/to/your/projectRun as an MCP server so your agent can search your codebase semantically:
zebrarag --mcpAdd to Claude Code (~/.claude.json):
{
"mcpServers": {
"zebrarag": {
"command": "zebrarag",
"args": ["--mcp"]
}
}
}Or via CLI:
claude mcp add -s user zebrarag -- zebrarag --mcpAdd to Cursor (.cursor/mcp.json):
{
"mcpServers": {
"zebrarag": {
"command": "zebrarag",
"args": ["--mcp"]
}
}
}Add to opencode (~/.config/opencode/opencode.json):
"zebrarag": {
"type": "local",
"command": ["zebrarag", "--mcp"],
"enabled": true
}Add to Codex CLI (~/.codex/config.toml):
[mcp_servers.zebrarag]
command = "zebrarag"
args = ["--mcp"]Add to Pi (.pi/config.toml):
[mcp_servers.zebrarag]
command = "zebrarag"
args = ["--mcp"]Add to Gemini CLI, Hermes Agent, Antigravity IDE, or Kiro β same pattern: point the MCP server config to zebrarag --mcp.
Zebra is MCP-native β works with any MCP-compatible agent. The agent gets seven tools: searchQuery, searchPassage, searchDep, fileTree, projectList, doctor, and projectList.
| π Semantic Search | Search code by intent, not by string. "user session validation" finds the session validation logic, not files containing that literal string. |
| π Search by Example | Paste a code snippet or error message β find semantically similar implementations across the codebase. |
| π§ Symbol Lookup | Look up any symbol by name and get its definition with full call graph (callers & callees), doc summary, and source body β all in one call. |
| β‘ Incremental Indexing | Tracks file snapshots. Only re-indexes what changed. Ξ-only β no full rebuilds. |
| π 100% Local | No data leaves your machine. No API keys. No external services. LanceDB + Candle run on-device. |
| π³ AST-Aware Chunking | tree-sitter parses every source file. Chunks are semantic units (functions, structs, methods) β not arbitrary line splits. |
| π Auto-Detect Models | Downloads embedding models from HuggingFace automatically. No manual config. |
| π¦ Rust Native | Single binary. Zero-cost abstractions. Parallel chunking with rayon. Async daemon with tokio. |
| π MCP-Native | First-class MCP server via rmcp. Works with Claude Code, Cursor, Codex, opencode, Hermes Agent, Gemini, Antigravity, Kiro, Pi, and any MCP client. |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β AI Agent β
β β
β "How does request validation work in this codebase?" β
β calls zebrarag tools directly β no grep/find needed β
β β β
βββββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββ
β MCP (stdio)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β zebrarag (CLI / TUI / MCP) β
β β β
β Unix socket IPC β β
β βΌ β
β zrag-daemon β
β β
β tree-sitter Β· DSL chunking Β· embedding Β· ANN Β· rerank β
β AST parsing recursive (Candle) (usearch) (Turbo) β
β β β
β βΌ β
β LanceDB Store β
β chunks Β· embeddings Β· file-snapshots β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-
Extraction β tree-sitter parses source code into ASTs. Language-specific queries extract nodes (functions, classes, structs, methods) and edges (calls, imports).
-
Chunking β Recursive DSL chunker splits code along semantic boundaries. Each chunk is a named scope with its context chain β not arbitrary line splits.
-
Embedding β On-device transformer models (via Candle) encode each chunk into a dense vector. Models download automatically from HuggingFace.
-
Storage β Everything lands in a local LanceDB database with vector search, file snapshots, and project metadata.
-
Search β ANN search via usearch with optional exhaustive fallback, plus Turbo reranking for precision.
-
Auto-Sync β File watcher detects changes and incrementally re-indexes only the delta.
Zebra is a single Rust binary β build from source on any target that Rust supports.
| Platform | Architectures | Status |
|---|---|---|
| macOS | x64, arm64 (Apple Silicon) | β Full support |
| Linux | x64, arm64 | β Full support |
| Windows | x64 | β Full support |
| FreeBSD | x64 | β Supported |
| OpenBSD | x64 | β Supported |
Zebra exposes an MCP server β it works with any MCP-compatible agent. Tested and confirmed:
- Claude Code (Anthropic)
- Cursor
- Codex CLI (OpenAI)
- opencode
- Hermes Agent
- Gemini CLI (Google)
- Antigravity IDE
- Kiro
- Pi
Your agent gets seven tools: searchQuery (semantic symbol search), searchPassage (find similar code by example), searchDep (symbol lookup with call graph), fileTree (project structure), projectList (indexed projects), and doctor (diagnostics).
Each language gets a dedicated tree-sitter parser that extracts symbols and call edges:
| Language | Extensions | Symbol Extraction |
|---|---|---|
| Rust | .rs |
functions, structs, enums, traits, impls, methods, macros, modules, type aliases |
| TypeScript | .ts, .tsx |
functions, classes, methods, interfaces, type aliases, enums, JSX components |
| JavaScript | .js, .jsx, .mjs, .cjs |
functions, classes, methods, arrow functions, JSX components |
| Python | .py |
functions, classes, methods, async functions, decorators |
| Dart | .dart |
functions, classes, methods, constructors, getters/setters |
| Go | .go |
functions, methods, structs, interfaces, type aliases |
| Solidity | .sol |
contracts, functions, events, modifiers, structs, enums |
| OCaml | .ml, .mli, .scilla, .scillib, .scilexp |
functions (let/value), types, modules, classes, methods, module types; also parses Zilliqa Scilla smart contracts |
All models run locally via Candle β no API calls, no data leakage. Hardware auto-detection: Metal (macOS), CUDA (Linux/Windows), CPU fallback.
| Model | Params | Description |
|---|---|---|
all-MiniLM-L6-v2 |
22.7M | Lightweight baseline. High speed, minimal footprint. |
all-MiniLM-L12-v2 |
33.4M | Slightly deeper. Better accuracy than L6. |
bge-small-en-v1.5 |
33.4M | Gold standard for small models. Fast and accurate. |
bge-base-en-v1.5 |
109M | Excellent balance of speed and retrieval accuracy. |
bge-m3 |
567M | Heavyweight multi-lingual (100+ languages). GPU recommended. |
e5-small-v2 |
33.4M | Fast English-only. Requires query:/passage: prefixes. |
e5-base-v2 |
109M | Standard English-only E5. High accuracy. |
multilingual-e5-small |
118M | Lightweight multilingual. Good for mixed-language data. |
multilingual-e5-base |
278M | Heavy multilingual. Broad vocabulary, GPU recommended. |
gte-small |
33.4M | Solid alternative to bge-small. Robust on diverse text. |
gte-base |
109M | Competes with e5-base and bge-base. No prefixes required. |
gte-large |
335M | Top-tier retrieval for English. VRAM heavy. |
| Backend | Status | Notes |
|---|---|---|
| CUDA | β Supported | Linux & Windows. NVIDIA GPUs via Candle CUDA backend. |
| Metal | β Supported | macOS. Apple Silicon & AMD GPUs via Candle Metal backend. |
| CPU | β Supported | Always-available fallback. Works everywhere. |
| Vulkan | β Not yet | Planned. Candle has experimental Vulkan support. |
| RockX | β Not yet | AMD ROCm. Not currently integrated. |
| NPU | β Not yet | Neural Processing Units (Apple Neural Engine, Qualcomm, Intel NPU). Not supported. |
Hardware is auto-probed at daemon startup and the fastest available backend is selected automatically.
zebrarag # Launch the terminal UI
zebrarag daemon --model <id> # Start the background indexer daemon
zebrarag index -r <path> # Index a project
zebrarag index -r <path> --refresh # Force full re-index
zebrarag search -r <path> <query> # Semantic search
zebrarag chat -r <path> # Interactive search loop
zebrarag status [-r <path>] # Show indexed project status
zebrarag doctor [-r <path>] # Run diagnostics
zebrarag env # Show daemon environment info
zebrarag stop # Stop the daemon
zebrarag projects # List all indexed projects
zebrarag remove -r <path> # Remove a project from the index
zebrarag --mcp # Run as MCP server (stdio)
# DSL debugging tools
zebrarag dsl -r <path> <subcommand> # Dump DSL graph / dependency tree / project mapzebrarag search -r <path> <query> \
--limit 10 \ # Max results (default: 5)
--lang rust,ts \ # Filter by language
--glob "src/**/*.rs" \ # Filter by file pattern
--mode passage \ # Search by example (default: query)
--exhaustive # Skip ANN, scan all chunksWhen running as an MCP server, Zebra exposes these tools to agents:
| Tool | Purpose |
|---|---|
searchQuery |
Primary. Search the codebase by intent in plain language. Returns full source code with file paths and line ranges β no follow-up file reads needed. |
searchPassage |
Find similar code by example. Paste a snippet or error message to locate related implementations. |
searchDep |
Look up a symbol by exact name. Returns kind, location, doc summary, callers/callees (to depth), and full source body. |
fileTree |
List project files and directory structure. Use instead of find, ls -R, or glob. |
projectList |
List all indexed projects with root paths. Use when unsure which project to target. |
doctor |
Run diagnostics on the embedding engine and index. Use when search tools return errors. |
| Layer | Technology |
|---|---|
| Language | Rust (edition 2024) |
| Build | Cargo workspace (24 crates) |
| Parsing | tree-sitter (9 language grammars) |
| Embedding | Candle (HuggingFace transformers on-device) |
| Vector DB | LanceDB (columnar, zero-copy reads) |
| ANN Search | usearch (HNSW graph) |
| IPC | Unix domain sockets (tokio async) |
| MCP | rmcp (stdio transport) |
| TUI | ratatui + crossterm |
| CLI | clap (derive API) |
| Async Runtime | tokio (multi-threaded) |
| Parallelism | rayon (CPU chunking & embedding) |
"Daemon not running" β Start it with zebrarag daemon --model <id> or launch the TUI (zebrarag) which starts the daemon automatically.
"No indexed projects found" β Run zebrarag index -r /path/to/project first. Use zebrarag projects to see what's indexed.
Search returns no results β The project may use a language not yet supported. Check zebrarag status to see file counts. Try --exhaustive to bypass ANN.
Indexing is slow on first run β Expected. The initial backfill parses, chunks, and embeds every file. Subsequent runs are incremental and fast.
Model download fails β Check your internet connection. Models download from HuggingFace. Set HF_HUB_CACHE to control the cache location.
MIT
Built with π¦ Rust Β· Cargo Β· tree-sitter Β· Candle Β· LanceDB