Fast, hybrid (BM25 + semantic) local code search for AI agents and humans, written in pure Rust.
Veles runs entirely on CPU — no GPU, no transformer forward pass at query time. Queries return in tens of milliseconds against a persistent on-disk index, with tree-sitter-aware symbol lookups, pipe-friendly output formats, and built-in MCP / gRPC servers for integration with Claude, Cursor, or anything else that speaks JSON-RPC. Static embeddings come from the potion family via model2vec-rs.
Originally inspired by Semble — Veles started as a Rust port of the same hybrid retrieval recipe and has grown to add persistent + incremental indexing, tree-sitter symbols / defs / refs, six pipe-friendly output formats, glob/language filters, gRPC, and shell completions.
veles tui — live hybrid search, ~10ms per keystroke.
Interfaces
- CLI —
veles search "query" ./my-repo - MCP server — stdio JSON-RPC for AI agent integration (Claude, Cursor, etc.)
- gRPC — tonic-based service with
Index,Search,FindRelated,GetStatsRPCs
Features
- Persistent index under
<repo>/.veles/— searches reuse the cache and finish in tens of milliseconds. Incrementalupdatekeeps embeddings of unchanged files. - Hybrid search with Reciprocal Rank Fusion (RRF) blending BM25 and semantic scores
- Tree-sitter symbol commands —
symbols/defs/refsfor Rust, Python, JavaScript, TypeScript, Go - Identifier-aware tokenizer — splits camelCase, snake_case, and mixed-script names
- Query-type detection — symbol queries lean BM25, natural language leans semantic
- Definition boosting — promotes chunks that define the queried symbol
- Path penalties — demotes test files, compat dirs, re-export files
- File saturation — avoids stacking all results from one file
- Scope labels on every hit — search/related/refs results carry a tree-sitter-derived
defines `Foo`orin `bar`suffix so the result header alone tells you what each chunk is - Multilingual model option for Cyrillic, CJK, Arabic, etc.
- Pipe-friendly output —
pretty,compact,ripgrep,paths,json,jsonl - Filter flags —
--lang,--pathand--excludeglob patterns,--min-score - Prebuilt binaries for macOS (Intel/ARM), Linux x86_64/ARM64 (musl), Windows x86_64
Install
# Linux / macOS — prebuilt binary (one-liner) curl --proto '=https' --tlsv1.2 -LsSf \ https://github.com/julymetodiev/Veles/releases/latest/download/veles-cli-installer.sh | sh # Windows — PowerShell irm https://github.com/julymetodiev/Veles/releases/latest/download/veles-cli-installer.ps1 | iex # Homebrew (macOS / Linux) brew install julymetodiev/tap/veles-cli # From crates.io (compiles locally; no protoc / extra deps needed) cargo install veles-cli # Manual download gh release download --repo julymetodiev/Veles --pattern '*linux-gnu*' # or browse # https://github.com/julymetodiev/Veles/releases/latest # Verify (optional) veles --version # → veles 0.4.3
See INSTALL.md for SHA-256 verification and other install paths.
Quickstart
veles index . # one-off, builds .veles/ veles search "parse config file" # auto-loads the cache veles update . # refresh after edits
The first search downloads the embedding model from Hugging Face (~64 MB, cached at ~/.cache/huggingface/hub/).
Most-used commands
Search
veles search "rate limiting" # hybrid (default) veles search "rate limiting" -t 10 -f compact # 10 results, 1 line each veles search "rate limiting" -f rg # ripgrep-style path:line:content veles search "rate limiting" -f json | jq '.results' # structured for scripting veles search "rate limiting" -f paths | xargs $EDITOR # open every matching file
veles search "TokenStream" -m bm25 # exact identifier veles search "auth flow" -m semantic # fuzzy concept veles search "auth" -l rust,python # language filter veles search "X" -g 'src/**/*.rs' -x 'src/legacy/**' # glob include / exclude veles search "BM25" --min-score 0.4 # drop weak hits
Symbols (tree-sitter)
veles symbols crates/veles-core/src/persist.rs # outline a single file veles defs Manifest # every definition named "Manifest" veles defs save -k function -l rust # filter by kind + language veles refs save_index -t 30 # defs + BM25 references
Related code
veles find-related src/main.rs 42 # semantically similar chunks veles find-related src/main.rs 42 -l rust # restrict to one language veles find-related src/main.rs 42 -g 'crates/foo/**' # restrict to a subtree
Index lifecycle
veles index . # bootstrap veles index . --force # rebuild from scratch veles update . # incremental refresh veles status . # manifest + drift veles clean . # remove .veles/
Interactive TUI
veles tui # live hybrid search with preview pane veles tui ./my-repo # against another repo
Loads the persistent index once, then debounces queries so each keystroke
re-runs in tens of milliseconds. ↑↓ navigate, Tab cycles
hybrid/bm25/semantic, Ctrl-R finds related code, Ctrl-D / Ctrl-F
show tree-sitter definitions / references for the typed identifier,
Enter prints path:line to stdout ($EDITOR $(veles tui) works),
Ctrl-O opens in $EDITOR, ? shows the full keybinding overlay.
Servers
veles serve-mcp # MCP over stdio (default if no args) veles serve-grpc --addr "[::1]:50051" # gRPC
Shell integration
mkdir -p ~/.zfunc ~/.local/share/man/man1 veles completions zsh > ~/.zfunc/_veles veles man --out-dir ~/.local/share/man/man1
veles man --out-dir DIR writes one page per subcommand (veles.1,
veles-search.1, veles-defs.1, …) so man veles-search works the
same way as man git-commit.
Then once in ~/.zshrc:
fpath=(~/.zfunc $fpath) autoload -Uz compinit && compinit export MANPATH="$HOME/.local/share/man:$MANPATH"
Remote repos
veles search "BM25 inverted index" https://github.com/julymetodiev/VelesSee USAGE.md for the full reference, recipes (fzf, vim quickfix, jq), and troubleshooting.
MCP server
veles serve-mcp # explicit veles # equivalent — bare `veles` starts MCP when stdin is piped
Exposed tools:
| Tool | Use it for |
|---|---|
search |
Hybrid / BM25 / semantic query, with optional lang / path / exclude / min_score. |
defs |
Tree-sitter definitions for an exact symbol name (Rust, Python, JS, TS, Go). |
refs |
Definitions plus BM25 hits — "where is X defined and where is X used", in one call. |
find_related |
Semantically similar chunks for a (file_path, line) from an earlier search. |
list_symbols |
Every tree-sitter definition across the index, with kind / lang / path filters. |
symbols |
Outline of a single file — every definition it contains. |
scope_at |
Innermost tree-sitter symbol containing a given file:line. |
files |
Distinct file paths in the index, with lang / path / exclude filters. |
read |
Line range from an indexed file (capped at 500 lines, repo-relative paths only). |
stats |
File / chunk counts, model metadata, per-language chunk breakdown. |
status |
Non-mutating drift check vs. persisted manifest; distinguishes content edits from bare touch. |
update |
Incremental refresh of a local repo's .veles/ index after edits (BLAKE3-aware). |
search, find_related, and refs accept a format argument:
default(default) — scored, fenced code blocks tagged with the enclosing scope.paths— flat per-line list.search/find_relatedemitpath:start-end;refsemitspath:lineper word-boundary occurrence of the symbol.unique_paths— collapsed to onepathline per file. For agent shortlist workflows that just want "which files matter".
Build from source
cargo build --release
tonic-build ships a vendored protoc via protoc-bin-vendored, so no system-wide protobuf compiler is required.
Embedding in your own Rust project
The workspace publishes four crates on crates.io — pick the layer you need:
| Crate | Purpose |
|---|---|
veles-core |
Indexing, chunking, BM25, dense search, hybrid ranking, persistence. |
veles-grpc |
tonic-based gRPC service wrapping veles-core. |
veles-mcp |
MCP / JSON-RPC server (stdio) for AI-agent integration. |
veles-cli |
The veles binary. |
Full API docs are on docs.rs.
[dependencies] veles-core = "0.2"
use std::path::Path; use veles_core::{SearchMode, VelesIndex}; let index = VelesIndex::from_path(Path::new("."), None, None, false)?; let results = index.search("parse config", 5, SearchMode::Hybrid, None, None, None); for r in results { println!("{} [{:.3}]", r.chunk.location(), r.score); } # Ok::<(), anyhow::Error>(())
Architecture
Veles/
crates/
veles-core/ indexing, chunking, BM25, dense search, ranking, symbols
veles-grpc/ gRPC service (tonic + prost)
proto/
veles.proto gRPC schema
veles-mcp/ MCP server over stdio
veles-cli/ CLI binary
The persistent index lives under <repo>/.veles/:
.veles/
manifest.json # model, dim, per-file (size, mtime, chunk_count)
chunks.bin # bincode Vec<Chunk>
bm25.bin # bincode BM25 inverted index
dense.bin # bincode dense matrix
symbols.bin # bincode tree-sitter symbols
update reuses embeddings of files whose (size, mtime) fingerprint hasn't changed, so refreshing after a small edit is near-instant on large repos.
License
MIT

























