Releases: martintrojer/vecgrep
Release list
v0.10.0
Highlights
- Added opt-in --hybrid search mode for lexical + semantic ranking
- TUI now shows when hybrid mode is active
- Server /status and /search output now include hybrid
- Benchmarks now compare vector, lexical, and hybrid retrieval modes
Fixed
- Split query-time hybrid behavior from persisted index capability
- Fixed reindex path normalization regression that could trigger stale-file removal and full reindexing on the next hybrid query
Notes
- Hybrid is most useful for short, grep-like queries with strong identifiers or phrases
- Retrieval quality still varies by corpus and embedder, so hybrid stays an explicit mode rather than the universal default
v0.9.3
New features:
- --skip-vcs flag to exclude VCS directories (.git, .hg, .jj) when using --hidden. Configurable via skip_vcs = true in
project/global config — ideal for dotfile repos where you want hidden files indexed but not VCS internals.
Improvements:
- --reindex now always rebuilds from the project root and rejects positional arguments (query or paths), making its behavior
unambiguous.
v0.9.2
Open files from the TUI
Press Enter on any result in interactive mode to open the file at the matched location. By default it uses your $PAGER, but you can customize it:
vecgrep -i "error handling" --open-cmd "nvim +{line} {file}"
vecgrep -i "error handling" --open-cmd "bat -n --highlight-line {line}:{end_line} {file}"
Placeholders: {file}, {line}, {end_line}. Set it once in your config:
# ~/.config/vecgrep/config.toml
open_cmd = "nvim +{line} {file}"Bug fix: --clear-cache preserves config
Previously --clear-cache deleted the entire .vecgrep/ directory, including your config.toml. It now only removes the index database, leaving your configuration intact.
v0.9.1
--no-scope flag
Search the entire project index from any subdirectory:
cd src && vecgrep --no-scope "startup" # returns results from all directories
Without --no-scope, vecgrep scopes results to your cwd (like ripgrep). Conflicts with explicit paths. Works with CLI,
TUI (-i), and --serve.
Scope visibility
- TUI status bar shows
| scope: src, docswhen path scopes are active /statusendpoint includes"root"and"scope"fields
Spinner improvements
- CLI spinner runs on its own thread — animates smoothly regardless of embedder speed (no more stalling with remote/Ollama
models) - Spinner pauses cleanly for threshold prompts via atomic flag
TUI streaming results
- Results stream in progressively during indexing (auto-refresh every 3s)
- "Searching..." only shows for user-typed queries, not background refreshes
- No more status bar flashing during indexing
Internal
- Replaced search state booleans with
SearchTriggerenum in TUI - Consolidated
Spinnercleanup intoDrop - Added
test_stats_rejects_queryandtest_no_scopeintegration tests
v0.9.0
Search scoping
Search results are now scoped to the paths you specify, like ripgrep:
vecgrep "startup" src/ # only returns results from src/
cd src && vecgrep "startup" # same — scoped to cwd
vecgrep "startup" . ../docs/ # results from both directories
Path scoping is a post-filter on the index — the full project stays indexed, but only matching paths appear in results.
/status endpoint
The --serve mode now exposes a /status endpoint for IDE plugin integration:
{"status":"ready","files":36,"chunks":936,"version":"0.9.0","root":"/path/to/project","scope":["src"]}
- status — "indexing" (with progress) or "ready"
- version — vecgrep version
- root — project root path
- scope — path scopes (omitted when searching the full project)
--query flag for xargs workflows
rg TODO -l | xargs vecgrep -i --query "error handling"
rg TODO -l | xargs vecgrep --serve --query "search"
When --query is set, all positional arguments become paths. Requires -i or --serve.
New config options
All configurable via CLI flags, project config (.vecgrep/config.toml), or global config (~/.config/vecgrep/config.toml):
- -t/--type and -T/--type-not — file type filters
- -g/--glob — glob pattern filters
- -p/--pretty — alias for --color=always
- --port — fixed port for --serve mode
- --skip-outside-root — ignore paths outside the project root instead of failing
Threshold change
Default similarity threshold lowered from 0.3 to 0.2. The previous default was too aggressive for small code-heavy repos
where even good matches score lower with the built-in MiniLM model.
--stats is standalone
--stats now rejects queries and conflicts with --interactive, --serve, --index-only, --type-list, and --show-root.
Indexing progress
- N/M file progress shown during indexing (CLI spinner, TUI status bar, serve)
- PipelineStatus simplified to Indexing/Ready with optional total
- Ready status shows total index size, not just the current pass
Fixes
- Scoped searches over-fetch from the index (top_k * 3) to compensate for post-filtering
- Fixed test_status_indexing_with_total_when_walker_done — was calling read-only snapshot() instead of on_send()
v0.8.0
Pipe-friendly TUI mode
vecgrep -i now works seamlessly with pipes and xargs:
rg TODO -l | xargs vecgrep -i
rg TODO -l | xargs vecgrep "error handling" -i
File arguments from xargs are correctly treated as search paths — type your query in the TUI search box. Previously this
failed with "Failed to initialize input reader" on macOS.
Explicit file caching
When you pass file paths directly (not directories), vecgrep now caches them persistently with an explicit flag:
vecgrep "auth bug" src/auth.rs src/session.rs # cached for fast re-search
vecgrep "auth bug" # directory search excludes them
- Explicit files persist across invocations — no re-embedding on the next search
- Re-indexed automatically when file content changes
- Only the explicit files you pass appear in results — files from prior invocations don't leak through
- Excluded from directory-only searches so they don't pollute unrelated results
- Consistent filtering across CLI, TUI, and --serve
- Works safely with gitignored or hidden files
Fixes
- Old indexes now auto-rebuild instead of crashing with "table files has no column named explicit"
- Removed dead -C / --context flag that was accepted but silently ignored
Internal
- Refactored into smaller modules (root.rs, invocation.rs, embedder/)
- Improved test coverage for batch splitting, token estimation, chunk coverage, explicit file filtering, and edge cases
- Simplified function signatures — fewer clippy too_many_arguments allows
v0.7.2
-
Default chunk size reduced from 512 to 256 tokens (overlap from 128 to 64) — aligned with the built-in model's 256-token
context window. Previously chunks were silently truncated by the model, wasting half the content. Existing indexes will
automatically rebuild on first run. -
Clear error messages when remote embedder is unreachable — previously a cryptic SQLite float[0] error. Now reports the
actual server error, e.g. Embeddings API returned HTTP 404: model "mxbai-embed-large" not found, try pulling it first.
(#10, thanks @krisajenkins)
Bug fixes
- TUI responsiveness — stale search results no longer skip rendering and input handling. Previously, queued stale results
could make Esc unresponsive. - Remote embedder error propagation — errors from embed_batch are now propagated when the embedding dimension is still
unknown, instead of silently producing zero vectors that cause downstream failures.
Internal
Code quality and simplification release — ~500 fewer lines of implementation code, 194 tests (up from 161).
- Revised Allium spec (553 → 200 lines)
- Unified 3-layer config merge into single resolve_config function
- Collapsed path admission, process_batch, CLI spinner, and drain functions
- Refactored with_transaction to pass &Connection into closure
- Bundled serve parameters into ServeConfig struct
- Removed dead code, trivial wrappers, double canonicalization
- 12 new tests covering identified gaps and extract_error_message
v0.7.1
0.7.1 is a patch release focused on CLI correctness, chunking fixes, and internal cleanup around invocation planning.
Highlights
- Fixed --reindex when run without a query.
- Fixed tokenizer padding inflating chunk token counts.
- Capped local chunk size to the model context window.
- Improved handling of indexing aborts and search/embed errors in streaming modes.
- Refactored CLI invocation planning, config precedence, and mode execution in main.rs.
- Added regression tests for invocation resolution.
- Added the vecgrep AI skill and related docs.
Contributors
- Thanks to @krisajenkins for the tokenizer padding fix in PR #7.
v0.7.0
This release tightens vecgrep’s CLI and indexing behavior, improves visibility into index health, and makes cache handling safer and more predictable.
Highlights
- CLI searches now wait for indexing to finish before returning results.
This fixes the old behavior where first-run/default CLI searches could return incomplete, unlabeled results. - CLI indexing progress output is much clearer.
First-run indexing now reports compact progress with walked files and indexed chunks, and quiet mode is covered properly. - --stats now reports index holes.
Failed remote embeddings that fall back to zero vectors are counted as Holes, so hidden index gaps are visible without enabling
debug logs. - Index write paths are now atomic.
Multi-step cache mutations are wrapped in transactions, which makes vecgrep more robust when interrupted mid-run. - Schema changes now rebuild the cache instead of attempting in-place migration.
.vecgrep/index.db is treated as disposable cache state, which simplifies correctness and reduces migration edge cases. - Path semantics are stricter and safer.
vecgrep now enforces one selected project root per invocation.
Paths outside that root fail by default, and --skip-outside-root lets you ignore them explicitly. - Explicit file-list runs no longer prune unrelated cached files.
This fixes cases like rg ... -l | xargs vecgrep ..., where partial path lists could previously cause unnecessary cache rebuilds
later. - Global config now follows XDG-style lookup consistently.
vecgrep respects $XDG_CONFIG_HOME and otherwise falls back to ~/.config/vecgrep/config.toml, matching the documented config path. - Added a flake.nix build environment.
Contributors
Thanks to everyone who contributed to this release:
v0.6.2
What's new
--ignore-file flag — Add custom ignore patterns using gitignore syntax, following ripgrep's --ignore-file convention. Can
be specified multiple times on the CLI or as an ignore_files array in .vecgrep/config.toml.
CLI
vecgrep --ignore-file .vecgrepignore "query" ./src
Config (.vecgrep/config.toml)
ignore_files = [".vecgrepignore"]
Supports full gitignore syntax including globs (*.log, build/) and negation patterns (!important.log).