rgfind

Search results that agents can inspect, explain, and safely continue from.

rg pattern exits 0 with matches still hidden — and every step downstream trusts it.

A plain rg pattern skips gitignored, hidden, and binary files, then exits 0 as if it had searched everything. A person notices the gap. A program acting unattended does not: it passes the thinned result to the next step, and the error compounds down the pipeline. rf (ripgrep + fd) is built for those programs. It recovers the hidden matches, names the filter that hid each one, and returns one typed envelope a caller can inspect, explain, and safely continue from.

Read the docs Quickstart View source

Recovery is the easiest property to see, so it makes the proof. Three files hold the term — one tracked, one hidden, one gitignored. Plain ripgrep finds one and exits 0. rf finds all three, names the filter that hid each, and hands back the rg command to confirm it. The recovery is the demo; the inspectable result is the product:

$ rf content timeout .
content 'timeout' in .: 3 file(s), 1 by default, 2 hidden by filters
  default      config.py
  hidden       .env.local
  vcs_ignore   cache/build.py
  ! IGNORE_VCS: 1 match(es) hidden by default; add -u (ignore .gitignore/.ignore rules)
  ! HIDDEN_SKIPPED: 1 match(es) hidden by default; add -uu (also search hidden/dotfiles)
  $ 'rg' '-u' '-e' 'timeout' '--' '.'
  $ 'rg' '-uu' '-e' 'timeout' '--' '.'

See which filter hid each match

Every recovered match names the filter that hid it — gitignore, hidden, binary, or case — and gives you a paste-ready rg command to confirm it.

Exit codes you can branch on

An empty result is exit 0 with data: [], never an error. Bad input is 1, a broken environment is 3, an internal fault is 6 — and only a paged-snapshot conflict (5) is ever worth a retry. "No matches" is never confused with "it failed."

One process, not a pipe

rf links ripgrep's and fd's own crates directly, so every match remembers which stage found it. A shell pipe throws that away.

One JSON envelope

Every verb returns the same JSON envelope. Read rf capabilities once and an agent knows every verb, flag, exit code, and warning code.

Four discovery sources, each miss traced

The find verb combines fd's name filters, ripgrep's binary skip, git history (with secrets scrubbed from the tree), and ast-grep structural matches. Each miss is traced to the one stage that hid it — something a shell pipe can't do.

How find works