find::grep — searching by content
grep searches file contents with ripgrep’s regex engine, across a
directory (walked in parallel) or a single file (searched in memory).
pub fn grep(options: GrepOptions) -> Result<GrepResult, String>
Options
pub struct GrepOptions {
pub pattern: String, // regex (ripgrep syntax)
pub path: String, // file or directory
pub glob: Option<String>, // filename glob filter, e.g. "*.ts"
pub r#type: Option<String>, // language type filter, e.g. "rust", "py"
pub ignore_case: Option<bool>,
pub multiline: Option<bool>,
pub hidden: Option<bool>, // default: true (SDK default — see find.md)
pub gitignore: Option<bool>, // default: true
pub cache: Option<bool>, // use the shared scan cache
pub max_count: Option<u32>, // global match cap
pub offset: Option<u32>, // skip the first N matches
pub context_before: Option<u32>,
pub context_after: Option<u32>,
pub context: Option<u32>, // legacy: sets both before and after
pub max_columns: Option<u32>, // truncate long lines
pub mode: Option<GrepOutputMode>, // Content | Count | FilesWithMatches
pub max_count_per_file: Option<u32>, // per-file cap (content mode)
pub timeout_ms: Option<u32>,
pub on_match: Option<Arc<GrepMatchCallback>>, // live streaming
}
// Example: Basic content search
let result = grep(GrepOptions {
pattern: "fn main".to_string(),
path: "/path/to/project".to_string(),
r#type: Some("rust".to_string()),
..Default::default()
}).unwrap();
// Example: Count mode with pagination
let result = grep(GrepOptions {
pattern: "TODO".to_string(),
path: "/path/to/project".to_string(),
mode: Some(GrepOutputMode::Count),
offset: Some(20), // skip first 20 matches
max_count: Some(20), // return next 20
..Default::default()
}).unwrap();
// Example: File search with glob filter
let result = grep(GrepOptions {
pattern: "import.*react".to_string(),
path: "/path/to/project".to_string(),
glob: Some("*.{ts,tsx}".to_string()),
ignore_case: Some(true),
..Default::default()
}).unwrap();
Output modes
| Mode | matches contains |
total_matches |
|---|---|---|
Content (default) |
matched lines with line_number, line, context, truncated |
total matched lines |
Count |
one row per matched file with match_count (line_number: 0, empty line) |
total matches across files |
FilesWithMatches |
one row per matched file (no line content) | number of matched files |
Limiting and pagination
max_countcaps the global number of emitted matches/files (count-mode applies it to matches, not files).limit_reachedreports whether the cap cut the search short.offsetskips the first N matches in walker order. Combined withmax_countit gives you paging:offset=20, max_count=20returns the next page.max_count_per_filecaps matches per file before the global budget is applied — it keeps one hot file from exhaustingmax_countbefore other files are reached.
Type and glob filters
globcompiles throughtry_compile_glob(recursive prefix applies:"*.rs"matches.rsfiles at any depth).r#typemaps well-known names to extension sets:"js"/"javascript"→js, jsx, mjs, cjs;"ts"/"typescript"→ts, tsx, mts, cts;"py"→py, pyi;"rs"→rs;"docker"/"dockerfile"→ thedockerfilefilename;"make"/"makefile"→ themakefilefilename; and so on. Any unknown value is treated as a custom extension (a leading.is stripped, case-insensitive).
Pattern tolerances
Two niceties for callers who pass literal text fragments instead of carefully-written regexes:
- Braces that aren’t valid repetition quantifiers are escaped — a pattern
like
${platform}would fail to compile ({pis not a quantifier); it is silently rewritten to$\{platform\}. Valid quantifiers (a{2,4}) and Unicode property escapes (\p{Greek},\x{41}) pass through unchanged. - After a group-syntax error, unescaped parentheses are escaped — a
trailing
(from a snippet likefetchAnthropicProvider(is treated as a literal, retrying withfetchAnthropicProvider\(.
The result
pub struct GrepResult {
pub matches: Vec<GrepMatch>, // path, line_number, line, context, truncated, match_count
pub total_matches: u32, // across all files
pub files_with_matches: u32,
pub files_searched: u32,
pub limit_reached: Option<bool>,
pub skipped_oversized: Option<u32>, // files > 4 MiB skipped
pub timed_out: bool, // partial results — search was cut short
}
Paths are absolute for single-file searches and relative to the
searched directory for directory searches. Files larger than 4 MiB are
skipped and counted in skipped_oversized rather than silently missing.
Errors
| Situation | What happens |
|---|---|
path missing |
Path not found: ... |
| Invalid regex | Regex error: ... (after tolerances are applied) |
| Regex engine fails mid-search | Search failed: ... |
| Timeout before the walk starts | Timeout (hard error) |
| Mid-walk timeout | Partial GrepResult with timed_out: true |
path is a special file (FIFO, socket) |
empty GrepResult (no error) |
Next: fs_cache — the shared scan cache, or task — cancellation.
Summary
grepsearches file contents with ripgrep’s regex engine across directories (parallel walk) or single files (in-memory search).- Output modes: Content (matched lines with context), Count (one row per matched file with match count), FilesWithMatches (one row per matched file, no content).
- Limiting and pagination:
max_countcaps global matches,offsetskips first N matches (combined gives paging),max_count_per_filecaps matches per file before global budget. - Type and glob filters:
globcompiles through glob_util (recursive prefix applies),r#typemaps well-known names to extension sets (js→js,jsx,mjs,cjs; py→py,pyi; etc.). - Pattern tolerances: invalid repetition quantifiers are escaped, trailing parentheses from snippets are treated as literals.
- Result:
GrepResultwith matches (path, line_number, line, context, truncated, match_count), total_matches, files_with_matches, files_searched, limit_reached, skipped_oversized, timed_out. - Errors: path missing, invalid regex, regex engine failure, timeout before walk starts (hard error), mid-walk timeout (partial result), special file (empty result, no error).