विचय — blazing-fast terminal-native file finding for macOS in Rust.
Project site and release manifest: https://indrasvat.github.io/vicaya/
vicaya is a lightweight developer file finder inspired by "Everything" on Windows. It keeps filename, path, and metadata search instant through its daemon index, and adds scoped content search through local tools when you need to look inside files.
- Instant Search: Sub-20ms search latency over millions of files
- Trigram Index: Fast substring matching using trigram-based inverted index
- Live Updates: FSEvents-based file watcher keeps index up-to-date
- Repo-Aware Indexing: Honors
.gitignore,.ignore, and.git/info/excludeby default - Developer Ranking: Prefers exact/prefix/abbreviation matches and demotes noisy dependency/cache paths
- Smriti Frecency: Learns local usage from opens/copies/reveals/prints to promote the paths you repeatedly choose
- Scoped Content Search:
vicaya grepand theAntarvicayaTUI drishti userg, fall back togit grepin repos, and keep plaingrepexplicit - Composable Output: Table, plain, and JSON formats for shells,
fzf, scripts, and agents - Compact Index: Efficient string arena + trigram index persisted to disk
- CLI, Daemon & TUI: Command-line tools, always-on daemon, and terminal UI for instant results
Status: Core functionality complete; ongoing UX/perf improvements
Latest coverage report: Codecov dashboard.
- ✅ Rust workspace structure
- ✅ Core types and configuration
- ✅ File table and string arena
- ✅ Trigram index and query engine
- ✅ Parallel filesystem scanner
- ✅ Unix socket IPC daemon (single-instance)
- ✅ Live updates (FSEvents/notify) + index journal
- ✅ Startup + daily reconciliation (self-healing)
- ✅ CLI + TUI interfaces
- 🚧 Documentation + UX polish
- 🚧 Performance work (persistence/mmap, faster rebuilds)
- ⏳ macOS UI with global hotkey
- ⏳ Signed/notarized builds
- Rust 1.91+ (stable toolchain; see
rust-toolchain.toml) - macOS 10.15+ (Catalina or later)
# Clone the repository
git clone https://github.com/indrasvat/vicaya.git
cd vicaya
# Compile everything
make build # or `cargo build --workspace`
# Format, lint, and test
make check # runs fmt + clippy + tests
# Individual steps are also available: make fmt | make lint | make testtmpdir=$(mktemp -d)
cd "$tmpdir"
curl -fsSLO https://github.com/indrasvat/vicaya/releases/latest/download/vicaya-universal.tar.gz
curl -fsSLO https://github.com/indrasvat/vicaya/releases/latest/download/vicaya-universal.tar.gz.sha256
shasum -a 256 -c vicaya-universal.tar.gz.sha256
tar -xzf vicaya-universal.tar.gz
mkdir -p "$HOME/.cargo/bin"
install -m 0755 bin/vicaya bin/vicaya-daemon bin/vicaya-tui "$HOME/.cargo/bin/"
vicaya --version
vicaya-tui --versionFuture upgrades can be done in place:
vicaya upgrade --check
vicaya upgradevicaya update is an alias. vicaya --version prints immediately and, when a
fresh cached check knows about a newer release, adds an inline update notice
telling you to run vicaya upgrade or vicaya update. The check reads the
small static manifest at https://indrasvat.github.io/vicaya/version.json, so
normal users avoid GitHub REST API rate limits. Set VICAYA_NO_UPDATE_CHECK=1
to disable the background release check.
# Fast dev loop: build, start daemon, and launch the TUI
make dev # uses release binaries for realistic perf
# Build release binaries locally (no global install)
make build-release # binaries at ./target/release/
make tui-local # run local TUI binary directly
# Full install (CLI + daemon + TUI in ~/.cargo/bin)
make install
# Once installed, the one-shot demo target will start the daemon
# and open the TUI with the published binaries
make run# Build an index (first run)
vicaya rebuild
# Search for files
vicaya search "main.rs" --limit 10
vicaya search "query.rs" --scope ~/code/github.com/example-repo --limit 10
# Search file contents without touching the daemon
vicaya grep "fn main" --scope ~/code/github.com/example-repo --limit 20
vicaya grep "TODO" --scope . --engine git-grep --format json
vicaya grep "needle" --scope . --engine grep --allow-slow-fallback
# Check daemon/index status
vicaya status
# Inspect runtime memory/health (includes `vmmap -summary` on macOS)
vicaya metrics
vicaya metrics --format json
vicaya metrics --no-vmmap
# Live metrics stream (JSONL); `vmmap` is throttled by default
vicaya metrics watch --format jsonl --interval 1s --vmmap-every 30
# End-to-end IPC latency benchmark (percentiles + optional vmmap before/after)
vicaya metrics bench --queries /tmp/vicaya-bench-queries.txt --warmup 50 --runs 500 --limit 20 --vmmap-before-after
# Output formats
vicaya search "config" --format json
vicaya search "test" --format plain
# Inspect or reset local Smriti usage memory
vicaya smriti list --limit 20
vicaya smriti list config --scope ~/code/github.com/example-repo --format json
vicaya smriti forget ~/code/github.com/example-repo/Cargo.toml
vicaya smriti clear --yes
# Manage the daemon manually
vicaya daemon start
vicaya daemon status
vicaya daemon stop
# Upgrade installed release binaries
vicaya upgrade --check
vicaya upgradeNote: vicaya search auto-starts the daemon if needed. If an existing on-disk index is present,
the daemon performs a background reconciliation on startup to catch missed filesystem changes.
Run vicaya status to see whether reconciliation is in progress.
The TUI connects to the same daemon and gives you instant, fuzzy-as-you-type results.
Highlights:
- Split view:
phala(results) +purvadarshana(preview with syntax highlighting) Ctrl+Topens the searchabledrishtiswitcher (Patra = Files, Sthana = Directories, Smriti = usage memory, Antarvicaya = content)Enteron a directory pushesksetrascope;hpops scope (breadcrumbs in header)- Launch with
vicaya-tui .orvicaya-tui /some/dirto start withksetraalready applied Niyamafilters inprashna:type:file|dir,ext:rs,md,path:src/,mtime:<7d,size:>10mbCtrl+Kopens directksetrapath input;Ctrl+Popenskriya-suchi(action palette)Ctrl+Otogglespurvadarshana;Tab/Shift+Tabcycles focus (input/results/preview)- Preview: scroll with
j/k, arrows,PgUp/PgDn,Ctrl+U/Ctrl+D,g/G; search with/, jumpn/N, toggle line numbersCtrl+N, clearCtrl+L - Actions (in
phala):Enter/oopen in$EDITOR(or enter scope on dirs),ycopy path,pprint path and exit,rreveal in file manager - Smriti records accepted open/copy/reveal/print/scope actions locally and uses a bounded frecency boost for future matching searches
- Press
?for in-app help (when not focused onprashna)
Terminology note: the UI uses romanized Sanskrit labels (e.g. drishti, ksetra, prashna, phala, purvadarshana). See docs/vicaya-tui-plan.md for the glossary and longer-term roadmap.
# Dev mode (builds + starts daemon if needed)
make dev
# Assuming binaries are installed already
make daemon-start
vicaya-tui .
vicaya-tui
# Stop the daemon when done
make daemon-stopBy default, vicaya stores state under ~/Library/Application Support/vicaya:
config.toml(configuration)daemon.sock/daemon.pid(daemon IPC + lifecycle)index/index.bin/index/index.journal(snapshot + incremental updates)smriti.json(local usage memory for frecency ranking)
Use VICAYA_DIR=/path/to/dir to override the base directory (useful for tests and multi-instance setups).
respect_ignore_files = true is the default. It honors .gitignore, .ignore,
and .git/info/exclude during indexing; toggle it in config.toml only when you
want ignored build artifacts or generated files to appear in results. Because
this changes index membership, restart the daemon and run vicaya rebuild after
changing it.
[smriti] enabled = true is the default. Smriti never indexes file contents or
sends usage data anywhere; it only stores local path/action counters in
smriti.json. Corrupt Smriti state is moved aside as
smriti.json.corrupt.<timestamp> before Vicaya starts a fresh store. Set
VICAYA_NO_SMRITI=1 or disable [smriti] enabled when you want searches to
ignore usage memory entirely.
[content_search] enabled = true is the default. engine = "auto" prefers
rg, then git grep when the active scope is inside a git worktree. Plain
recursive grep is intentionally opt-in via --engine grep,
--allow-slow-fallback, or [content_search] allow_slow_fallback = true;
this keeps search-as-you-type responsive when rg is not installed. Existing
config files without a [content_search] table do not need migration; Vicaya
applies these defaults in memory after upgrade. Set VICAYA_NO_CONTENT_SEARCH=1
to disable the feature.
make help prints the full list, but the most common targets are below:
| Target | Description |
|---|---|
make build |
Compile the entire workspace (debug). |
make build-release |
Build release binaries to ./target/release/ without installing. |
make fmt / make lint / make test |
Run rustfmt, clippy (all targets/features), or the full test suite. |
make check |
Convenience combo: fmt → lint → test. |
make bench |
Execute the Criterion benchmarks. |
make install |
Install CLI, daemon, and TUI binaries into ~/.cargo/bin. |
make dev |
Build, spawn the daemon in the background, and launch the TUI (dev workflow). |
make tui-local |
Build release and run local TUI binary (no global install). |
make run |
Install release binaries, start the daemon, and open the TUI (simulates end-user setup). |
make daemon-start / make daemon-stop |
Manage the daemon using the installed CLI. |
make daemon-dev / make tui-dev |
Run daemon or TUI straight from source without installing. |
make clean |
Remove target/ artifacts. |
make ci |
Local CI parity: fmt + lint + test + build. |
vicaya is organized as a Rust workspace with multiple crates:
- vicaya-core: Configuration, logging, and error types
- vicaya-index: File table, string arena, and trigram index
- vicaya-scanner: Parallel filesystem scanner
- vicaya-watcher: FSEvents-based file watcher
- vicaya-daemon: Background service
- vicaya-cli: Command-line interface
- vicaya-tui: Terminal UI that streams live results from the daemon
See docs/vicaya.md for the complete implementation guide.
- Indexing: 200k+ files/sec on SSD
- Query Latency: p95 ≤ 20ms for 5M+ entries
- Memory: ≤ 500MB for 5M indexed paths
- Responsiveness: UI updates within 16ms
# Format code
make fmt
# Run linter
make lint
# Run all checks
make check
# Run benchmarks
make benchReleases are managed by Release Please:
- After CI succeeds on
main, the Release workflow opens or updates a release PR when conventional commits require a new version. That PR updatesCargo.toml,.release-please-manifest.json, andCHANGELOG.md. - Merge the release PR only after its CI and Codecov upload are green.
- After the release PR lands on
main, CI runs again. When that CI run succeeds, the Release workflow creates thev<semver>tag, builds the universal macOS tarball, uploads SHA256 sums, and publishes the GitHub Release. - Download and smoke-test the latest release with the commands in Install Latest Release.
Each artifact bundle contains the CLI (vicaya), daemon (vicaya-daemon), and TUI (vicaya-tui) binaries so you can exercise the full stack.
The self-updater consumes the same release artifacts. After the release assets
are uploaded, the Release workflow publishes the GitHub Pages site at
https://indrasvat.github.io/vicaya/ and writes
https://indrasvat.github.io/vicaya/version.json. vicaya upgrade reads that
static manifest first, downloads vicaya-universal.tar.gz and its SHA256 file,
verifies the checksum, stops the daemon if it is running, replaces vicaya,
vicaya-daemon, and vicaya-tui atomically in the current install directory,
then restarts the daemon unless --no-restart-daemon is passed. Use
--install-dir <dir> for non-standard installs and --force to reinstall the
latest version. If the Pages manifest is unavailable, the CLI can still fall
back to the GitHub Releases API.
For fully automated release PRs, configure a RELEASE_PLEASE_TOKEN repository secret backed by a fine-grained PAT or GitHub App token with contents and pull-request write access. The workflow can fall back to GITHUB_TOKEN, but GitHub suppresses CI triggers for pull requests created by GITHUB_TOKEN, so the dedicated token is the production-safe path.
CI artifacts are currently unsigned, so macOS adds a quarantine flag when you download them via a browser. If Finder refuses to launch them (or moves them to Trash), strip the flag manually before running:
xattr -dr com.apple.quarantine /Users/you/Downloads/vicaya-aarch64-apple-darwin-binariesNote: Replace /Users/you/Downloads/vicaya-aarch64-apple-darwin-binaries with the actual path where you downloaded the artifact.
After clearing the attribute you can run ./vicaya --version, ./vicaya-daemon --version, etc. This cannot be automated in CI because Gatekeeper attaches the flag on the downloader’s machine; the long-term fix is to codesign/notarize artifacts once a Developer ID certificate is available.
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Licensed under the Apache License, Version 2.0. See LICENSE for details.
विचय (vicaya) is a Sanskrit word meaning "inquiry" or "search" — perfectly capturing the essence of this tool