Short answer
Both, for different steps. Grep finds the line with nothing to build; the cost is the whole-file read that follows, which an index replaces with the file's signatures: 57,058 tokens against 1,649 on Hugging Face's trainer.py. For "who calls this", grep's matches are the ground truth our blast-radius benchmark scores against, and it returns every line that names the function, callers or not.
What grep is good at
Grep, ripgrep and the agent’s own search tool find a string anywhere, right away, with nothing to install or keep up to date. For “where is this error message” or “which files mention this flag” nothing beats it, and Pixel keeps it: pixel search-content takes the same regular expressions.
Where it stops
A match is a line, not an answer. To learn what the function around it does, what else the file defines or who calls it, the agent opens the whole file, and on a large file that read costs far more than the search that led to it. Grep also cannot tell a call from a comment, a string or another symbol with the same name: every line that spells the name comes back.
A code index answers those questions directly. pixel list-signatures gives a file’s definitions without its bodies, pixel who-calls and pixel impact give callers from a graph parsed with tree-sitter, and pixel find-symbol goes to a definition by name.
Use both
Keep grep for strings and a code index for structure. The agent prompt pixel install deploys says which pixel command replaces which search or read, and when the native tool is still the right one.
The figures
| Finds the matching line | Both; pixel search-content keeps grep's regex syntax |
|---|---|
| What the agent reads to know what trainer.py contains | 57,058 tok after grep, 1,649 tok through Pixel |
| Less read, 8 well-known files | 79.7 to 97.2% |
| Callers found, 29 blast-radius cases scored against grep | 0.86 recall |
Every figure above is on the benchmarks page, with its sample size and its method: Well-known files, Against GitNexus, On whole agent tasks.
Where Pixel does not win
Grep needs no index and runs on any file the moment it exists; Pixel builds one in .pixel/ first. On a single lookup the August runs found Pixel about 1.5 seconds slower. Pixel's graph misses callers grep sees: 0.86 of them overall, 0.56 on one Ruby repository. For a question in plain English, neither is the best tool: semble is.