> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tokenfactory.nebius.com/llms.txt
> Use this file to discover all available pages before exploring further.

# grep - Search file contents in the image

Search file contents in the session image using server-side ripgrep, without
spawning a sandbox.

## Examples

```bash theme={null}
# Search the session cwd for a pattern
contree grep TODO

# Search a specific file or directory
contree grep "^PermitRootLogin" /etc/ssh/sshd_config

# Search the whole image (PATH omitted defaults to cwd; pass / for the root)
contree grep TODO /

# Restrict to a glob, limit match count, case-insensitive
contree grep --glob '*.py' --max-count 5 --case insensitive def /app

# 2 lines of context before and after each match, like grep -C 2
contree grep -C 2 ERROR /var/log/app.log

# asymmetric context, like grep -A/-B (--after/--before also work)
contree grep -B 1 -A 3 ERROR /var/log/app.log

# JSON output for scripting (one row per match)
contree -o json grep TODO /app
```

## Output

The default format prints classic `PATH:LINE:TEXT` lines, one per match –
the same shape as running `grep -rn` locally:

```
/etc/hosts:1:127.0.0.1 localhost
/etc/hosts:2:255.255.255.255 broadcasthost
```

With `-A`/`-B`/`-C`, context lines use `-` instead of `:` and a `--` line
separates output groups that aren’t directly adjacent – the same
convention GNU grep and ripgrep use:

```
/var/log/app.log-4-starting request
/var/log/app.log:5:ERROR: connection refused
/var/log/app.log-6-retrying
--
/var/log/app.log-40-starting request
/var/log/app.log:41:ERROR: timeout
/var/log/app.log-42-giving up
```

Structured formats (`-o json`, `-o csv`, `-o table`, …) instead get one
row per match/context line with the columns `path`, `line_number`,
`absolute_offset`, `line_bytes`, `line_text`, `type` (`match` or
`context`).

## Help output

<div className="contree-terminal" style={{"border":"1px solid rgba(255,255,255,0.15)","borderRadius":8,"overflow":"hidden","margin":"1rem 0"}}><div style={{"background":"#292929","height":24,"display":"flex","alignItems":"center","padding":"0 12px","position":"relative"}}><div style={{"display":"flex","alignItems":"center","flexShrink":0}}><span style={{"display":"inline-block","width":10,"height":10,"borderRadius":"50%","background":"#ff5f57","marginRight":6}} /><span style={{"display":"inline-block","width":10,"height":10,"borderRadius":"50%","background":"#febc2e","marginRight":6}} /><span style={{"display":"inline-block","width":10,"height":10,"borderRadius":"50%","background":"#28c840"}} /></div><div style={{"position":"absolute","left":0,"right":0,"textAlign":"center","fontFamily":"-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif","fontWeight":"bold","color":"#999"}}>\$ contree grep --help</div></div><pre style={{"margin":0,"borderRadius":0,"padding":"8px 10px","background":"#1e1e1e","overflowX":"auto"}}><code style={{"fontFamily":"JetBrains Mono, SF Mono, SFMono-Regular, Menlo, Monaco, Cascadia Mono, Segoe UI Mono, Roboto Mono, Oxygen Mono, Ubuntu Monospace, Source Code Pro, Fira Mono, Droid Sans Mono, Consolas, Courier New, monospace","color":"#c5c8c6","whiteSpace":"pre-wrap"}}><span style={{"color":"#61afef","fontWeight":"bold"}}>usage: </span><span style={{"color":"#c678dd","fontWeight":"bold"}}>contree grep</span><span style={{"color":"#c5c8c6"}}> \[</span><span style={{"color":"#98c379"}}>-h</span><span style={{"color":"#c5c8c6"}}>] \[</span><span style={{"color":"#56b6c2"}}>--glob </span><span style={{"color":"#e5c07b"}}>GLOB</span><span style={{"color":"#c5c8c6"}}>] \[</span><span style={{"color":"#56b6c2"}}>--max-count </span><span style={{"color":"#e5c07b"}}>MAX\_COUNT</span><span style={{"color":"#c5c8c6"}}>] \[</span><span style={{"color":"#56b6c2"}}>--max-total </span><span style={{"color":"#e5c07b"}}>MAX\_TOTAL</span><span style={{"color":"#c5c8c6"}}>]</span><br /><span style={{"color":"#c5c8c6"}}>                    \[</span><span style={{"color":"#56b6c2"}}>--case </span><span style={{"color":"#e5c07b"}}>\{sensitive,insensitive,smart}</span><span style={{"color":"#c5c8c6"}}>] \[</span><span style={{"color":"#98c379"}}>-B </span><span style={{"color":"#e5c07b"}}>NUM</span><span style={{"color":"#c5c8c6"}}>] \[</span><span style={{"color":"#98c379"}}>-A </span><span style={{"color":"#e5c07b"}}>NUM</span><span style={{"color":"#c5c8c6"}}>] \[</span><span style={{"color":"#98c379"}}>-C </span><span style={{"color":"#e5c07b"}}>NUM</span><span style={{"color":"#c5c8c6"}}>] \[</span><span style={{"color":"#56b6c2"}}>--raw</span><span style={{"color":"#c5c8c6"}}>]</span><br /><span style={{"color":"#c5c8c6"}}>                    </span><span style={{"color":"#98c379"}}>pattern</span><span style={{"color":"#c5c8c6"}}> </span><span style={{"color":"#98c379"}}>\[path ...]</span><br /><br /><span style={{"color":"#c5c8c6"}}>Search file contents in the session image.</span><br /><br /><span style={{"color":"#c5c8c6"}}>Uses the /inspect/ API (server-side ripgrep) to search file contents</span><br /><span style={{"color":"#c5c8c6"}}>without spawning an instance. Defaults to the session working directory</span><br /><span style={{"color":"#c5c8c6"}}>(set via \`cd\`) when PATH is omitted -- pass \`/\` explicitly to search the</span><br /><span style={{"color":"#c5c8c6"}}>whole image. PATH may be repeated to search multiple roots in one call.</span><br /><br /><span style={{"color":"#61afef","fontWeight":"bold"}}>positional arguments:</span><br /><span style={{"color":"#c5c8c6"}}>  </span><span style={{"color":"#98c379","fontWeight":"bold"}}>pattern</span><span style={{"color":"#c5c8c6"}}>               Regex pattern to search for (Rust regex syntax)</span><br /><span style={{"color":"#c5c8c6"}}>  </span><span style={{"color":"#98c379","fontWeight":"bold"}}>path</span><span style={{"color":"#c5c8c6"}}>                  File(s)/directory(ies) inside image (defaults to session cwd); may be</span><br /><span style={{"color":"#c5c8c6"}}>                        repeated to search multiple roots</span><br /><br /><span style={{"color":"#61afef","fontWeight":"bold"}}>options:</span><br /><span style={{"color":"#c5c8c6"}}>  </span><span style={{"color":"#98c379","fontWeight":"bold"}}>-h</span><span style={{"color":"#c5c8c6"}}>, </span><span style={{"color":"#56b6c2","fontWeight":"bold"}}>--help</span><span style={{"color":"#c5c8c6"}}>            show this help message and exit</span><br /><span style={{"color":"#c5c8c6"}}>  </span><span style={{"color":"#56b6c2","fontWeight":"bold"}}>--glob</span><span style={{"color":"#c5c8c6"}}> </span><span style={{"color":"#e5c07b","fontWeight":"bold"}}>GLOB</span><span style={{"color":"#c5c8c6"}}>           Restrict search to files matching this glob (e.g. '\*.py')</span><br /><span style={{"color":"#c5c8c6"}}>  </span><span style={{"color":"#56b6c2","fontWeight":"bold"}}>--max-count</span><span style={{"color":"#c5c8c6"}}> </span><span style={{"color":"#e5c07b","fontWeight":"bold"}}>MAX\_COUNT</span><br /><span style={{"color":"#c5c8c6"}}>                        Stop after this many matches per file</span><br /><span style={{"color":"#c5c8c6"}}>  </span><span style={{"color":"#56b6c2","fontWeight":"bold"}}>--max-total</span><span style={{"color":"#c5c8c6"}}> </span><span style={{"color":"#e5c07b","fontWeight":"bold"}}>MAX\_TOTAL</span><br /><span style={{"color":"#c5c8c6"}}>                        Stop after this many matches total (server default: 1000)</span><br /><span style={{"color":"#c5c8c6"}}>  </span><span style={{"color":"#56b6c2","fontWeight":"bold"}}>--case</span><span style={{"color":"#c5c8c6"}}> </span><span style={{"color":"#e5c07b","fontWeight":"bold"}}>\{sensitive,insensitive,smart}</span><br /><span style={{"color":"#c5c8c6"}}>                        Case sensitivity (default: sensitive)</span><br /><span style={{"color":"#c5c8c6"}}>  </span><span style={{"color":"#98c379","fontWeight":"bold"}}>-B</span><span style={{"color":"#c5c8c6"}}>, </span><span style={{"color":"#56b6c2","fontWeight":"bold"}}>--before-context</span><span style={{"color":"#c5c8c6"}}>, </span><span style={{"color":"#56b6c2","fontWeight":"bold"}}>--before</span><span style={{"color":"#c5c8c6"}}> </span><span style={{"color":"#e5c07b","fontWeight":"bold"}}>NUM</span><br /><span style={{"color":"#c5c8c6"}}>                        Show NUM lines of context before each match (max 50)</span><br /><span style={{"color":"#c5c8c6"}}>  </span><span style={{"color":"#98c379","fontWeight":"bold"}}>-A</span><span style={{"color":"#c5c8c6"}}>, </span><span style={{"color":"#56b6c2","fontWeight":"bold"}}>--after-context</span><span style={{"color":"#c5c8c6"}}>, </span><span style={{"color":"#56b6c2","fontWeight":"bold"}}>--after</span><span style={{"color":"#c5c8c6"}}> </span><span style={{"color":"#e5c07b","fontWeight":"bold"}}>NUM</span><br /><span style={{"color":"#c5c8c6"}}>                        Show NUM lines of context after each match (max 50)</span><br /><span style={{"color":"#c5c8c6"}}>  </span><span style={{"color":"#98c379","fontWeight":"bold"}}>-C</span><span style={{"color":"#c5c8c6"}}>, </span><span style={{"color":"#56b6c2","fontWeight":"bold"}}>--context</span><span style={{"color":"#c5c8c6"}}> </span><span style={{"color":"#e5c07b","fontWeight":"bold"}}>NUM</span><span style={{"color":"#c5c8c6"}}>     Show NUM lines of context before and after (overridden by -A/-B)</span><br /><span style={{"color":"#c5c8c6"}}>  </span><span style={{"color":"#56b6c2","fontWeight":"bold"}}>--raw</span><span style={{"color":"#c5c8c6"}}>                 Print raw JSON (preserves submatches/patterns/truncated)</span><br /><br /><span style={{"color":"#c5c8c6"}}>for coding agents:</span><br /><span style={{"color":"#c5c8c6"}}>  read-only command (inspect API, no instance spawn)</span><br /><span style={{"color":"#c5c8c6"}}>  defaults to session cwd when PATH is omitted; pass / to search whole image</span><br /><span style={{"color":"#c5c8c6"}}>  exit code 1 means zero matches (like POSIX grep), not an error</span><br /><span style={{"color":"#c5c8c6"}}>  exit code 2 means the search was truncated before finding anything --</span><br /><span style={{"color":"#c5c8c6"}}>  inconclusive, not confirmed zero matches</span><br /><span style={{"color":"#c5c8c6"}}>  default format prints classic PATH:LINE:TEXT; use -o json/csv/... for rows</span><br /><span style={{"color":"#c5c8c6"}}>  use --raw to preserve submatches/patterns/truncated as JSON</span><br /><span style={{"color":"#c5c8c6"}}>  -A/-B/--context add ripgrep-side context lines (server-computed, not local)</span><br /><br /><span style={{"color":"#c5c8c6"}}>agent note:</span><br /><span style={{"color":"#c5c8c6"}}>  Before using this command in an automated workflow, read:</span><br /><span style={{"color":"#c5c8c6"}}>    contree agent</span></code></pre></div>

## Behavior

`grep` searches file contents directly in the image filesystem – no sandbox
is started. Matching is powered by ripgrep with Rust regex syntax and
linear-time matching; symlinks are never followed, hidden files are searched,
and binary files (containing a NUL byte) are skipped.

When PATH is omitted, the search defaults to the session working directory
(set via `cd`), consistent with [ls - List files in the image](./ls) and [cat - Show file content from the image](./cat). Pass `/` explicitly
to search the whole image.

`-B`/`--before-context`/`--before`, `-A`/`--after-context`/`--after`, and
`-C`/`--context` request extra lines of context around each match (server
-side, up to 50 lines each way) – `-C` sets both directions unless
overridden by an explicit `-A`/`-B`. This mirrors GNU grep/ripgrep’s own
flags; `-C` is a deliberate one-off exception to this CLI’s usual
uniqueness rule for short flags (`-C` is `--cwd` everywhere else).

Nested match detail (`submatches`) is dropped from structured output; pass
`--raw` to get the full JSON response, including `submatches`, the searched
`patterns`, and the `truncated` flag – useful for `jq` pipelines.

The command exits with status 1 when no matches are found (like POSIX
`grep`), so it composes in shell conditionals:

```bash theme={null}
if contree grep ERROR /var/log/app.log > /dev/null; then
  echo "found errors"
fi
```

Exit status 2 is different from 1: it means the search was truncated
(`max_total`/the server deadline was hit) *before finding anything at all*,
which is inconclusive rather than a confirmed zero-match result. A truncated
search that still found at least one match exits 0/none as usual –
`truncated` only affects the exit code when combined with zero matches.

## See also

* [ls - List files in the image](./ls) – list files before searching
* [cat - Show file content from the image](./cat) – view a single file’s full contents
