Skip to content

Hook: find/grep rewrite breaks on native flags — workaround with smart translation #236

@Shankhara

Description

@Shankhara

Context

The recommended Claude Code hook blindly prefixes find and grep/rg commands with rtk, which breaks in many common cases (relates to #204, #229).

find — syntax mismatch

rtk find has a completely different syntax than GNU find:

  • GNU: find <path> <predicates> (e.g., find . -not -path '*/.git/*' -name '*.pdf')
  • RTK: rtk find <PATTERN> [PATH] [--max N] [-t f|d]

The hook rewrites find . -not -path ... | head -n 500rtk find . -not -path ... | head -n 500, which fails because:

  1. RTK's Clap parser doesn't know -not, -path, -type, -exec, etc.
  2. The argument order is reversed (pattern vs path)
  3. Piped commands like | head -n get their flags parsed by Clap (the -n error from find and grep commands fail (unexpected argument '-n' found) #204)

grep — Clap intercepts rg flags

rtk grep declares extra_args: Vec<String> with trailing_var_arg = true, but Clap still intercepts short flags like -i, -r, -n, -A etc. before reaching the trailing var arg. This means:

  • rtk grep -i "pattern" .error: unexpected argument '-i' found
  • rtk grep -rn "pattern" .error: unexpected argument '-n' found (grep: unexpecter argument #229)

The only way to pass rg flags is AFTER the positionals: rtk grep "pattern" path -- -i

Workaround: smart hook translation

We wrote a hook that properly translates instead of blindly prefixing:

find — syntax translation with safety guards

# Detect unsupported find features using case patterns
FIND_UNSUPPORTED=false
case "$MATCH_CMD" in
  *-exec*|*-delete*|*-print0*|*-newer*|*-mtime*|*-not*|*'!'*) FIND_UNSUPPORTED=true ;;
  *-maxdepth*|*-mindepth*|*-path*|*'|'*|*'&&'*) FIND_UNSUPPORTED=true ;;
esac

# Only translate simple: find <path> -name <pattern> [-type f|d]
# Complex cases pass through to native find
if [ "$FIND_UNSUPPORTED" = false ]; then
  # Translate: find . -name "*.pdf" -type f → rtk find *.pdf . -t f
  FIND_PATH=<extracted>
  FIND_PATTERN=<extracted>
  REWRITTEN="rtk find ${FIND_PATTERN} ${FIND_PATH}"
fi

grep — flag reorganization

# Parse args, separate RTK-known flags from rg-passthrough flags
# Strip -r/-R/-n/--recursive (redundant: rtk grep is recursive + line-numbered)
# Map --type → -t (RTK's Clap flag)
# Move unknown flags (like -i, -w, -A 3) after positionals with -- separator
# Result: grep -rn -i -A 3 "pattern" src/ → rtk grep "pattern" src/ -- -i -A 3

Suggestions for RTK

  1. find: Consider either adding external_subcommand / passthrough fallback (like PR feat: passthrough fallback when Clap parse fails + review fixes #200 suggests), or documenting that the hook should translate syntax rather than prefix
  2. grep: The trailing_var_arg on extra_args doesn't work as expected — Clap intercepts short flags before they reach extra_args. Consider using allow_hyphen_values = true on extra_args, or moving to a -- separator approach in the Clap definition
  3. Hook template: The default hook in the README should handle these edge cases — happy to contribute the full working hook if helpful

Environment

  • RTK: installed via Homebrew
  • OS: macOS (Darwin 24.6.0)
  • Claude Code hook (PreToolUse:Bash)

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2-importantDevrait être fixé bientôtbugSomething isn't workingeffort-medium1-2 jours, quelques fichiers

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions