grep_file Tool Guide

July 5, 2026 · View on GitHub

Note: grep_file is now an internal implementation detail. The canonical public tool is unified_search with action="grep". This guide documents the underlying search engine behavior.

Overview

The grep_file module powers VT Code's primary code search mechanism via the unified_search tool's grep action, backed by ripgrep for fast, efficient pattern matching across codebases. It provides comprehensive regex-based and literal string searching with support for file filtering, context lines, and language-specific searches.

Architecture

  • Backend: ripgrep (rg) — requires rg on PATH
  • Search Type: Regex-based (default) or literal string matching
  • File Filtering: Glob patterns, file type matching, size limits
  • Performance: Respects .gitignore and .ignore files by default for faster searches
  • Context: Optional surrounding lines for understanding matched code

Basic Usage

{
    "pattern": "TODO",
    "path": "src"
}
{
    "pattern": "^(pub )?fn \\w+\\(",
    "glob": "**/*.rs",
    "context_lines": 3
}
{
    "pattern": "^import\\s.*from",
    "glob": "**/*.ts",
    "case_sensitive": false
}

Parameter Reference

Core Parameters

ParameterTypeDefaultDescription
patternstring(required)Regex pattern or literal string to search for
pathstring"."Directory to search (relative path)
max_resultsinteger100Maximum results to return (1-1000)

Pattern Matching

ParameterTypeDefaultDescription
literalbooleanfalseTreat pattern as literal string (disable regex)
case_sensitivebooleanfalseForce case-sensitive matching. Default uses smart-case
word_boundariesbooleanfalseMatch only at word boundaries (\b in regex)
invert_matchbooleanfalseReturn lines that DON'T match the pattern
only_matchingbooleanfalseShow only matched parts, not full lines

File Filtering

ParameterTypeDefaultDescription
glob_patternstringnullGlob pattern to filter files (e.g., **/*.rs, src/**/*.ts)
type_patternstringnullFilter by file type (rust, python, typescript, javascript, java, go, etc.)
max_file_sizeintegernullSkip files larger than this (in bytes)
respect_ignore_filesbooleantrueRespect .gitignore and .ignore files
search_hiddenbooleanfalseSearch inside hidden directories (starting with .)
include_hiddenbooleanfalseInclude hidden files in results
search_binarybooleanfalseSearch binary files (usually false)

Output Formatting

ParameterTypeDefaultDescription
context_linesinteger0Lines of context before/after matches (0-20)
line_numberbooleantrueInclude line numbers in output
columnbooleanfalseInclude column numbers for exact match position
trimbooleanfalseTrim leading/trailing whitespace
response_formatstring"concise"Output format (concise or detailed)

Common Patterns

Finding Functions

Rust functions:

{
    "pattern": "^(pub )?async fn \\w+|^(pub )?fn \\w+",
    "glob": "**/*.rs"
}

TypeScript/JavaScript functions:

{
    "pattern": "^(export )?function \\w+|^const \\w+ = (async )?\\(",
    "glob": "**/*.ts"
}

Python functions:

{
    "pattern": "^def \\w+\\(",
    "type_pattern": "python"
}

Finding Error Handling

Rust panics and unwraps:

{
    "pattern": "panic!|unwrap\\(|expect\\(",
    "type_pattern": "rust",
    "context_lines": 2
}

Try-catch blocks:

{
    "pattern": "try\\s*{|catch\\s*\\(|throw ",
    "glob": "**/*.ts"
}

Finding Imports and Exports

TypeScript imports:

{
    "pattern": "^import\\s+.*from\\s+['\"]",
    "glob": "**/*.ts"
}

Python imports:

{
    "pattern": "^import |^from .* import ",
    "type_pattern": "python"
}

Finding TODOs and FIXMEs

All comment markers:

{
    "pattern": "(TODO|FIXME|HACK|BUG|XXX)[:\\s]",
    "context_lines": 1
}

Language-specific TODOs:

{
    "pattern": "// TODO|# TODO",
    "type_pattern": "rust",
    "context_lines": 1
}

Finding API Calls

HTTP verbs:

{
    "pattern": "\\.(get|post|put|delete|patch)\\(",
    "glob": "src/**/*.ts",
    "context_lines": 2
}

Database queries:

{
    "pattern": "SELECT|INSERT|UPDATE|DELETE",
    "glob": "**/*.sql",
    "case_sensitive": false
}

Finding Config References

Environment variables:

{
    "pattern": "process\\.env\\.|os\\.getenv\\(|getenv\\(",
    "glob": "**/*.js"
}

Config objects:

{
    "pattern": "config\\.",
    "case_sensitive": false,
    "context_lines": 1
}

Smart-Case Matching

By default, grep_file uses smart-case matching:

  • Lowercase pattern → Case-insensitive search

    • pattern: "todo" matches "TODO", "Todo", "todo"
  • Uppercase characters in pattern → Case-sensitive search

    • pattern: "TODO" matches "TODO" only
    • pattern: "myVar" matches "myVar" only

Force case sensitivity with case_sensitive: true:

{
    "pattern": "ERROR",
    "case_sensitive": true // Forces case-sensitive match
}

Performance Tips

  1. Use specific globs instead of searching all files:

    {
        "pattern": "fn deploy",
        "glob": "src/**/*.rs" // Much faster than searching entire directory
    }
    
  2. Use type_pattern for language filtering:

    {
        "pattern": "class MyClass",
        "type_pattern": "python" // Faster than glob: "**/*.py"
    }
    
  3. Respect ignore files by default (leave respect_ignore_files: true)

    • Skips node_modules, .git, build artifacts automatically
    • Set false only when you need to search ignored directories
  4. Limit context lines in large searches:

    {
        "pattern": ".*",
        "context_lines": 0 // No context for massive matches
    }
    
  5. Use literal matching when searching exact strings:

    {
        "pattern": "const.ERROR_MSG",
        "literal": true // Faster than regex for exact strings
    }
    

Advanced Examples

Refactoring Scenario: Update all imports

{
    "pattern": "^import.*from.*old-module",
    "glob": "src/**/*.ts",
    "context_lines": 0,
    "files_with_matches": true
}

Returns: List of all files importing the old module.

Finding unused exports

{
    "pattern": "^export.*const|^export.*function",
    "glob": "src/**/*.ts",
    "max_results": 500
}

Auditing security concerns

{
    "pattern": "eval\\(|exec\\(|innerHTML|dangerouslySetInnerHTML",
    "glob": "**/*.ts",
    "context_lines": 2
}

Finding configuration issues

{
    "pattern": "hardcoded.*password|api.*key.*=|token.*=",
    "case_sensitive": false,
    "context_lines": 1
}

Comparison with ast-grep

Featuregrep_file (ripgrep)ast-grep
SpeedVery fastFast
Pattern TypeRegex + literalAST queries
File FilteringGlob, type, sizeLimited
Language SupportAll languagesLimited
InstallationUsually pre-installedRequires binary
Learning CurveRegex knowledgeDomain language
Use CasesGeneral code search, patternsAST-specific queries

Migration: Replace AST grep queries with regex patterns targeting:

  • Function signatures: ^(pub )?fn name
  • Class definitions: ^class Name
  • Imports: ^import|^from
  • Comments: #|//|/*

Outline mode (action=outline)

unified_search also exposes action=outline, which wraps ast-grep outline (ast-grep >= 0.44.0) to produce a cheap, token-efficient symbol map of a file or directory without requiring a structural pattern. Use it for the "what's in this file/directory?" question before reading full source.

When to use which search action:

ActionQuestion it answers
grep"Which lines match this text/regex?"
outline"What symbols are defined in this file/directory?" (no pattern)
structural"Which nodes match this AST pattern?" (pattern/kind required)
{"action":"outline","path":"vtcode-core/src/tools/registry/builder.rs","lang":"rust","view":"digest"}
{"action":"outline","path":"vtcode-core/src/tools/registry","lang":"rust","type":"function","view":"names","items":"exports"}

Sub-fields: path (default .), lang, type (string or array of symbol types), match (name regex), items (auto | structure | exports | imports | all; default auto), pub_members (bool), follow (bool), view (digest | names | full; default digest).

  • digest (default): symbols grouped by kind per file, with flat member names. ~100-300 bytes for a typical file.
  • names: grouped names only, no members.
  • full: per-symbol records with the raw zero-based range, a derived 1-based inclusive lineRange ({start, end} — usable directly with unified_file read offset_lines/page_size_lines), signatures, astKind, and nested members (members also carry astKind/range/lineRange).

Directory results also include a top-level summary with total_symbols, by_kind (per-kind symbol counts summing to total_symbols), and all_symbols (flat symbol list capped at 200 entries). When the cap is hit, summary.truncated is true and summary.visible_symbols reports the visible count — narrow with type or match, or outline a specific file. Grep/structural-only params (glob_pattern, case_sensitive, literal, context_lines, files_with_matches, type_pattern, max_file_size) and format/max_results are not used by outline; a hints array in the result lists which were ignored.

outline and structural shell out to the same resolved ast-grep binary. On a missing binary, both actions auto-install ast-grep on first use by downloading the matching platform release from GitHub into ~/.vtcode/bin (with checksum verification and a 24h failure cooldown). Set VTCODE_AST_GREP_NO_INSTALL=1 to opt out of auto-install; the error then surfaces immediately with the manual install command (vtcode dependencies install ast-grep). Unlike structural, outline has no grep fallback (outline has no text equivalent).

Troubleshooting

No results found

  1. Check pattern syntax (regex special chars must be escaped)
  2. Verify path exists
  3. Check if files are in .gitignore (add respect_ignore_files: false)
  4. Use context_lines: 1 to debug with surrounding lines

Too many results

  1. Add glob_pattern or type_pattern to narrow scope
  2. Increase max_results limit (up to 1000)
  3. Use files_with_matches: true to get just filenames

Slow searches

  1. Add glob_pattern to narrow scope (e.g., **/*.rs)
  2. Use type_pattern instead of glob when possible
  3. Set max_file_size to skip large files
  4. Use respect_ignore_files: true (default) to skip node_modules, etc.

Return Format

{
    "success": true,
    "query": "TODO",
    "matches": [
        {
            "type": "match",
            "data": {
                "path": { "text": "src/main.rs" },
                "line_number": 42,
                "lines": { "text": "// TODO: refactor this function\n" }
            }
        }
    ]
}

Integration with Other Tools

Using grep_file with read_file

1. grep_file to locate patterns
2. read_file to examine full context
3. edit_file to make changes

Using grep_file with execute_code

# Find all matches
results = grep_file(pattern="TODO", path="src")
# Process results locally
todos = [m['data']['lines']['text'] for m in results['matches']]

See Also