The following is a copy-paste of a thing Claude Agent (Opus 4.8 @ Max) found when using the hook for rg on macOS Tahoe when bouncing around a codebase doing some analysis. It baked a workaround into agent memory, but this feels like it needs a fix here. I validated the sample tool use call as well.
Maybe I'm missing something here and this override is intentional, but CC doesn't seem to like it.
Summary
The Claude Code integration hook (rtk hook claude, installed as a PreToolUse hook) auto-rewrites every rg command to rtk grep …. rtk grep follows grep (BSD) semantics, not ripgrep semantics, so the most common ripgrep forms break:
rg PATTERN with no path → ripgrep searches the CWD recursively; BSD grep instead reads stdin → the command silently returns 0 matches, or hangs if no stdin is attached.
rg PATTERN DIR → ripgrep recurses into DIR by default; BSD grep errors grep: DIR: Is a directory unless -r is passed.
- ripgrep-only flags (
--type-list, -t/--type, --files, etc.) are rejected by grep.
rtk rg … (and rtk proxy rg …) already wrap genuine ripgrep 15.1.0 correctly, so the bug is isolated to the hook choosing rtk grep as the rewrite target instead of rtk rg.
Why this matters: the failure is silent and wrong, not a loud error. An agent (or user) runs rg "SomeSymbol", gets no output, and concludes the symbol doesn't exist — when it does. This produces confidently-incorrect conclusions during code search/analysis. (It also intermittently hangs automated runs that don't redirect stdin.)
Environment
rtk 0.42.3
ripgrep 15.1.0 at /usr/local/bin/rg (the genuine binary is fine)
- macOS (Darwin 25.x); system grep is BSD grep 2.6.0-FreeBSD
- Host: Claude Code, with
~/.claude/settings.json → hooks → "command": "rtk hook claude"
Root cause (verified)
The hook unconditionally rewrites rg to rtk grep. Captured directly by piping the hook's PreToolUse JSON:
$ echo '{"tool_name":"Bash","tool_input":{"command":"rg -l -i ActiveStatus"}}' | rtk hook claude
{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecisionReason":"RTK auto-rewrite","updatedInput":{"command":"rtk grep -l -i ActiveStatus"}}}
$ echo '{"tool_name":"Bash","tool_input":{"command":"rg --version"}}' | rtk hook claude
{"hookSpecificOutput":{...,"updatedInput":{"command":"rtk grep --version"}}}
rtk grep is BSD grep, not a ripgrep front-end:
$ rtk grep --version
grep (BSD grep, GNU compatible) 2.6.0-FreeBSD # not ripgrep
$ rtk grep --type-list
grep: unrecognized option `--type-list' # ripgrep-only flag rejected
$ rtk grep -l -i ActiveStatus </dev/null | wc -l
0 # path-less: 0 matches (ripgrep finds 126)
$ printf 'has ActiveStatus\n' | rtk grep -i activestatus
has ActiveStatus # proof it read STDIN (grep), not cwd (rg)
$ rtk grep -l -i ActiveStatus backend/src
grep: backend/src: Is a directory # no default recursion (rg would recurse)
$ rtk grep -rl -i ActiveStatus backend/src | wc -l
31 # only works once you add BSD grep's -r
The correct rewrite target already works:
$ rtk rg --version
ripgrep 15.1.0
$ rtk rg --type-list | head -1
ada: *.adb, *.ads
$ rtk proxy rg -l -i ActiveStatus | wc -l
126 # matches `git grep -l -i ActiveStatus` = 125 tracked + 1 untracked
Steps to reproduce
- Install the rtk Claude Code hook (
rtk hook claude as a PreToolUse hook).
- In any repo where a symbol exists, run a normal path-less ripgrep search, e.g.
rg -i "someSymbolThatExists".
- Observe zero matches (or, with no stdin attached, the command hangs waiting on stdin).
- Confirm the symbol does exist:
rtk rg -i "someSymbolThatExists" (or git grep) returns matches.
Reproduce the rewrite itself without Claude Code:
$ echo '{"tool_name":"Bash","tool_input":{"command":"rg foo"}}' | rtk hook claude
# → updatedInput.command == "rtk grep foo" (expected: "rtk rg foo")
Impact
- Silent false-empty results on
rg PATTERN (no path) — ripgrep's most common invocation. Highest-severity because there is no error to notice.
- Hangs on path-less
rg PATTERN when stdin isn't redirected (BSD grep blocks on stdin).
- Directory searches error (
rg DIR → Is a directory) instead of recursing.
- ripgrep-only flags (
-t/--type, --type-list, --files, --json, glob-only forms, etc.) error or change meaning. Net effect: rg output via the hook is untrustworthy, and behavior varies by flag set, which compounds the unpredictability.
Suggested fix
- Rewrite
rg … → rtk rg … (preferred) — rtk rg already wraps genuine ripgrep correctly — or leave rg un-rewritten entirely.
- If
rg must map to rtk grep, make rtk grep a faithful ripgrep front-end: default to recursive CWD search when no path is given, recurse into directories by default, accept ripgrep flags, and fail loudly rather than silently falling back to BSD grep / stdin.
- Add a regression test:
rg PATTERN (no path) routed through the hook must return the same result set as rtk rg PATTERN / git grep PATTERN, and rg --version through the hook must report ripgrep, not BSD grep.
Workarounds (until fixed)
- Use
rtk rg … or rtk proxy rg … explicitly.
- Use
git grep … (also lets you target a ref without checkout).
- Passing an explicit
-r + subdirectory to rg can work, but is unreliable across flag combinations — prefer the above.
The following is a copy-paste of a thing Claude Agent (Opus 4.8 @ Max) found when using the hook for
rgon macOS Tahoe when bouncing around a codebase doing some analysis. It baked a workaround into agent memory, but this feels like it needs a fix here. I validated the sample tool use call as well.Maybe I'm missing something here and this override is intentional, but CC doesn't seem to like it.
Summary
The Claude Code integration hook (
rtk hook claude, installed as aPreToolUsehook) auto-rewrites everyrgcommand tortk grep ….rtk grepfollows grep (BSD) semantics, not ripgrep semantics, so the most common ripgrep forms break:rg PATTERNwith no path → ripgrep searches the CWD recursively; BSD grep instead reads stdin → the command silently returns 0 matches, or hangs if no stdin is attached.rg PATTERN DIR→ ripgrep recurses intoDIRby default; BSD grep errorsgrep: DIR: Is a directoryunless-ris passed.--type-list,-t/--type,--files, etc.) are rejected by grep.rtk rg …(andrtk proxy rg …) already wrap genuine ripgrep 15.1.0 correctly, so the bug is isolated to the hook choosingrtk grepas the rewrite target instead ofrtk rg.Why this matters: the failure is silent and wrong, not a loud error. An agent (or user) runs
rg "SomeSymbol", gets no output, and concludes the symbol doesn't exist — when it does. This produces confidently-incorrect conclusions during code search/analysis. (It also intermittently hangs automated runs that don't redirect stdin.)Environment
rtk0.42.3ripgrep15.1.0 at/usr/local/bin/rg(the genuine binary is fine)~/.claude/settings.json→ hooks →"command": "rtk hook claude"Root cause (verified)
The hook unconditionally rewrites
rgtortk grep. Captured directly by piping the hook's PreToolUse JSON:rtk grepis BSD grep, not a ripgrep front-end:The correct rewrite target already works:
Steps to reproduce
rtk hook claudeas aPreToolUsehook).rg -i "someSymbolThatExists".rtk rg -i "someSymbolThatExists"(orgit grep) returns matches.Reproduce the rewrite itself without Claude Code:
Impact
rg PATTERN(no path) — ripgrep's most common invocation. Highest-severity because there is no error to notice.rg PATTERNwhen stdin isn't redirected (BSD grep blocks on stdin).rg DIR→Is a directory) instead of recursing.-t/--type,--type-list,--files,--json, glob-only forms, etc.) error or change meaning. Net effect:rgoutput via the hook is untrustworthy, and behavior varies by flag set, which compounds the unpredictability.Suggested fix
rg …→rtk rg …(preferred) —rtk rgalready wraps genuine ripgrep correctly — or leavergun-rewritten entirely.rgmust map tortk grep, makertk grepa faithful ripgrep front-end: default to recursive CWD search when no path is given, recurse into directories by default, accept ripgrep flags, and fail loudly rather than silently falling back to BSD grep / stdin.rg PATTERN(no path) routed through the hook must return the same result set asrtk rg PATTERN/git grep PATTERN, andrg --versionthrough the hook must reportripgrep, not BSD grep.Workarounds (until fixed)
rtk rg …orrtk proxy rg …explicitly.git grep …(also lets you target a ref without checkout).-r+ subdirectory torgcan work, but is unreliable across flag combinations — prefer the above.