| Crates.io | vtcode-file-search |
| lib.rs | vtcode-file-search |
| version | 0.70.1 |
| created_at | 2026-01-02 04:03:51.136721+00 |
| updated_at | 2026-01-25 01:57:33.853991+00 |
| description | Fast, parallel fuzzy file search library for VT Code |
| homepage | |
| repository | https://github.com/vinhnx/vtcode |
| max_upload_size | |
| id | 2017906 |
| size | 53,507 |
Fast, parallel fuzzy file search library for VT Code.
vtcode-file-search is a dedicated file discovery and fuzzy matching crate that provides:
ignore crate (same library as ripgrep)nucleo-matcher for relevance scoringArc<AtomicBool>use std::num::NonZero;
use std::path::Path;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use vtcode_file_search::run;
fn main() -> anyhow::Result<()> {
let results = run(
"main", // Pattern
NonZero::new(100).unwrap(), // Limit
Path::new("."), // Search directory
vec![], // Exclusion patterns
NonZero::new(4).unwrap(), // Threads
Arc::new(AtomicBool::new(false)), // Cancellation flag
false, // compute_indices
true, // respect_gitignore
)?;
for m in results.matches {
println!("{}: {}", m.path, m.score);
}
Ok(())
}
# Search for files matching "main" pattern
vtcode-file-search "main"
# With options
vtcode-file-search --cwd /path/to/search "test" --limit 50 --threads 8
# JSON output
vtcode-file-search --json "pattern" /path
# Exclude patterns
vtcode-file-search "main" --exclude "target/**" --exclude "node_modules/**"
# Show help
vtcode-file-search --help
run()pub fn run(
pattern_text: &str,
limit: NonZero<usize>,
search_directory: &Path,
exclude: Vec<String>,
threads: NonZero<usize>,
cancel_flag: Arc<AtomicBool>,
compute_indices: bool,
respect_gitignore: bool,
) -> anyhow::Result<FileSearchResults>
Parameters:
pattern_text: Fuzzy search pattern (e.g., "main.rs", "test")limit: Maximum number of results to returnsearch_directory: Root directory to searchexclude: Glob patterns to exclude (e.g., ["target/**", "node_modules/**"])threads: Number of worker threadscancel_flag: Arc<AtomicBool> for early terminationcompute_indices: Whether to compute character indices for highlightingrespect_gitignore: Whether to respect .gitignore filesReturns:
pub struct FileSearchResults {
pub matches: Vec<FileMatch>,
pub total_match_count: usize,
}
pub struct FileMatch {
pub score: u32,
pub path: String,
pub indices: Option<Vec<u32>>,
}
file_name_from_path()Extract filename from a path:
use vtcode_file_search::file_name_from_path;
assert_eq!(file_name_from_path("src/main.rs"), "main.rs");
assert_eq!(file_name_from_path("/absolute/path/file.txt"), "file.txt");
use std::num::NonZero;
use std::path::Path;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use vtcode_file_search::run;
let results = run(
"src",
NonZero::new(100).unwrap(),
Path::new("."),
vec![],
NonZero::new(4).unwrap(),
Arc::new(AtomicBool::new(false)),
false,
true,
)?;
for m in results.matches {
println!("{} (score: {})", m.path, m.score);
}
let results = run(
"test",
NonZero::new(50).unwrap(),
Path::new("."),
vec![
"target/**".to_string(),
"node_modules/**".to_string(),
".git/**".to_string(),
],
NonZero::new(4).unwrap(),
Arc::new(AtomicBool::new(false)),
false,
true,
)?;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
let cancel_flag = Arc::new(AtomicBool::new(false));
let cancel_clone = cancel_flag.clone();
// Spawn a task that cancels after 100ms
tokio::spawn(async move {
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
cancel_clone.store(true, Ordering::Relaxed);
});
let results = run(
"pattern",
NonZero::new(100).unwrap(),
Path::new("."),
vec![],
NonZero::new(4).unwrap(),
cancel_flag,
false,
true,
)?;
On a modern machine (M4 Apple Silicon, 8 cores):
Parallel efficiency is ~90% with 8 threads.
Input Pattern
↓
[Parallel Directory Traversal]
├─ Worker 1: [Fuzzy Match] → [Per-Worker Results]
├─ Worker 2: [Fuzzy Match] → [Per-Worker Results]
└─ Worker N: [Fuzzy Match] → [Per-Worker Results]
↓
[Merge & Sort by Score]
↓
[Top-K Results]
Key Design:
BestMatchesList (no locking during traversal)nucleo-matcherignore crateArc<AtomicBool> cancellation flagignore – Parallel directory traversal (ripgrep's choice)nucleo-matcher – Fuzzy matching and scoring (Neovim's choice)tokio – Async runtimeserde / serde_json – Serializationclap – CLI argument parsing# Unit tests
cargo test -p vtcode-file-search
# Integration tests
cargo test -p vtcode-file-search --test integration_tests
# With output
cargo test -p vtcode-file-search -- --nocapture
# Specific test
cargo test -p vtcode-file-search test_multiple_matches
# Development build
cargo build -p vtcode-file-search
# Release build
cargo build -p vtcode-file-search --release
# Show help
./target/debug/vtcode-file-search --help
# Search in current directory
./target/debug/vtcode-file-search "pattern"
# Search in specific directory
./target/debug/vtcode-file-search --cwd /path/to/search "pattern"
# JSON output
./target/debug/vtcode-file-search --json "pattern"
# Exclude patterns
./target/debug/vtcode-file-search "pattern" --exclude "target/**" --exclude "node_modules/**"
# Limit results
./target/debug/vtcode-file-search "pattern" --limit 50
# Custom thread count
./target/debug/vtcode-file-search "pattern" --threads 8
This crate will be integrated into VT Code for:
This crate follows VT Code's standard conventions:
cargo test for testingcargo clippy for lintingcargo fmt for formattinganyhow::Result<T>unwrap() or expect() callsMIT