Search Tools — Grep and Glob
Fast targeted search across the repository. When to prefer Grep over Bash-ripgrep, when to delegate broader searches to an Explore agent.
What it is#
Grep and Glob are Claude Code’s specialised search tools. Both are fast, both return structured output, and both exist because reaching for Bash + ripgrep on every search is wasteful.
- Grep searches file contents using a regex pattern. It is a thin wrapper over ripgrep with sane defaults, smart filtering, and structured output that the model can parse without effort.
- Glob searches file paths using a glob pattern. It walks the project tree, honours
.gitignore, and returns matching paths.
These are the two questions a developer asks the filesystem most often: “where does this string live?” (Grep) and “where are the files that match this shape?” (Glob). Having them as first-class tools — rather than as Bash invocations — keeps the model fast and the output clean.
When to use it#
- Grep for any “find usages of X” or “find files matching this content pattern” query. Function definitions, import statements, error strings, config keys — any time you want to know where a token appears.
- Glob for “find files by name or shape”.
**/*.test.ts,src/**/migrations/*.sql,**/CLAUDE.md. - Bash + ripgrep for one-off cases Grep cannot express: complex multiline patterns, custom output formats, piping into another tool, or counting with
--count-matches. - Bash + find almost never. Glob is faster, ignores junk, and returns sorted output.
- An Explore sub-agent for broad, open-ended searches where you do not know which terms will work. An Explore agent can run many Greps and Globs in its own context window without bloating the main session.
The rule of thumb: if the search is one regex, use Grep. If it is one glob, use Glob. If it is “find me everything related to authentication and tell me how it fits together”, delegate to Explore.
How it works#
Grep#
Grep takes a regex pattern and optional filters. The minimum call is just a pattern, which searches all tracked files under the current working directory. Key options:
path— restrict to a directory or single file.glob— filter by filename glob (e.g."*.ts").type— filter by file type (e.g."ts","py","go"— ripgrep’s--typeshorthand).output_mode—"files_with_matches"(default, just paths),"content"(matching lines), or"count"(per-file counts).-n— include line numbers (whenoutput_mode: "content").-i— case-insensitive.-A,-B,-C— context lines around matches.multiline— let.cross newlines (for patterns that span lines).
The default output_mode of "files_with_matches" is deliberate: a list of paths is much smaller than a list of matches, and the model can follow up with a targeted Read on the interesting files.
Glob#
Glob takes a single pattern and returns paths sorted by modification time (most recent first). The pattern syntax is standard glob: *, **, ?, [abc]. There is no regex — for regex on filenames, use Bash + find.
Glob honours .gitignore, which means it does not return paths under node_modules, .next, dist, or anything else listed. This is the right default for source-code questions.
Why these beat raw ripgrep#
The model could call Bash("rg pattern src/") and it would work. But:
- The dedicated tool has narrower output, easier to parse.
- It does not trigger Bash approval prompts.
- It composes naturally with Read (which expects paths and offsets).
- It is faster to schedule — the harness routes it directly without a shell.
For most searches, Grep is the right reflex. Reach for Bash + ripgrep only when Grep cannot express what you want.
When to delegate to Explore#
A search that may produce dozens of false-positive paths, or one that requires triangulating across multiple greps, is a good fit for an Explore sub-agent. The Explore agent runs the searches in its own context, summarises the answer, and returns a concise report to the main session. This keeps the main context window clean — the main session sees the conclusion, not the hundred grep hits behind it.
Configuration#
There is no configuration specific to Grep or Glob — they are always available and have no permission gates. The only related configuration is project-level .gitignore (which Glob and Grep both honour) and the optional .ignore / .rgignore files that ripgrep respects in addition.
If your project has generated or vendored directories that are not in .gitignore but should be skipped during search (e.g. snapshot fixtures, an examples/ directory you do not want greps to traverse), add them to .rgignore:
# .rgignore at project rootsnapshots/vendor/examples/large-corpus/Both Grep and Glob will then skip those paths.
Examples#
Find every call site of a function#
{ "tool": "Grep", "pattern": "enqueueTask\\(", "type": "ts", "output_mode": "files_with_matches"}Returns a path list. Read the interesting files.
Find with context lines#
When you want to see the actual code around each match:
{ "tool": "Grep", "pattern": "TODO\\(security\\)", "output_mode": "content", "-n": true, "-C": 2}Returns matching lines with two lines of context above and below.
Find files by shape#
Every CLAUDE.md in the repo:
{ "tool": "Glob", "pattern": "**/CLAUDE.md"}All TypeScript test files in src/:
{ "tool": "Glob", "pattern": "src/**/*.test.ts"}Multiline pattern#
Find function definitions that span lines (signature on one line, opening brace on the next):
{ "tool": "Grep", "pattern": "function\\s+\\w+\\([^)]*\\)\\s*\\{", "multiline": true, "type": "ts", "output_mode": "content"}Count occurrences per file#
How many console.log calls per source file, descending:
{ "tool": "Grep", "pattern": "console\\.log", "type": "ts", "output_mode": "count"}The “no broad searches” rule#
For “find everything related to authentication”, do not run a single Grep with a vague pattern. Either:
- Run several targeted Greps (
signIn,signOut,requireAuth,JWT,session) in parallel. - Or delegate to an Explore sub-agent and let it run those Greps in its own context.
The main session should see the answer, not the search.
Gotchas#
- Regex escaping is for the pattern, not the input. A literal
.in a Grep pattern must be\\.or it matches any character. This is a frequent silent over-match. - Default
output_modereturns paths, not lines. If you want to see the matches, passoutput_mode: "content". New users routinely run a Grep, get a list of paths, and think the search found nothing useful. - Glob is mod-time-sorted, not alphabetical. Useful when “the file I just touched” is what you want; surprising if you assumed alphabetical. Pipe through
sortvia Bash if you need alphabetical. - Glob does not search inside files. It only matches paths. For “files that contain X” use Grep with
output_mode: "files_with_matches". .gitignoreis honoured by both. If a file you expected to find is not appearing, check whether it is gitignored.- Grep over the whole repo can be heavy. Restrict with
path,glob, ortypewhenever you can. AGrep "TODO"with no filter on a large repo returns megabytes of paths. - Backreferences and lookarounds may not work. Grep uses ripgrep’s regex engine (Rust regex by default). Lookarounds and backreferences require
--pcre2, which is not exposed through the tool. Use Bash +rg --pcre2for those. - Do not run
greprecursively throughBashas a reflex. It is slower, noisier in approval prompts, and the output is harder to consume. Grep first; Bash + ripgrep only when needed.
Grep vs Bash + ripgrep at a glance#
- Structured output, easy to consume
- No approval prompts
- Honours
.gitignoreby default - Covers the common 90% of searches
- Composes with Read
- Full ripgrep flag surface (PCRE2, json output, etc.)
- Right for piped pipelines (
rg … | sort -u | head) - Right for one-offs Grep cannot express
- More setup, more noise, slower to schedule
- Reach for it only when Grep falls short
Related features#
- File Tools — Read, Edit, Write
- The Bash Tool
- Sub-Agents
- The Conversation Loop
- Context Window and Token Budget
When the search is bigger than the tool — delegate to Explore
If you find yourself running five Greps to triangulate one answer, the right move is not a sixth Grep — it is an Explore sub-agent. The sub-agent runs in its own context window, can fire dozens of searches without bloating the main conversation, and returns a paragraph of conclusion. The main session walks away with a clear answer and a clean context. The break-even for delegation is around three or four searches: below that, just do it inline; above that, delegate.