Skip to content

docs(claude): warn that rg's -r is --replace, not a bundled short flag#322

Merged
laurigates merged 1 commit into
mainfrom
docs/rg-replace-flag-footgun
Jul 14, 2026
Merged

docs(claude): warn that rg's -r is --replace, not a bundled short flag#322
laurigates merged 1 commit into
mainfrom
docs/rg-replace-flag-footgun

Conversation

@laurigates

Copy link
Copy Markdown
Owner

What

Adds a section to ~/.claude/rules/tool-use-patterns.md on a silent, confident failure mode: rg -r is --replace and takes an argument, so bundling it into a short-flag cluster makes ripgrep rewrite every match in its own output.

# Wrong — reads as "recursive + line numbers"; actually means --replace=n
rg -rn "yolo" .
./conf/cli_clients/gemini.json:    "--n"      ← the file says "--yolo"

# Right
rg -n "yolo" .
./conf/cli_clients/gemini.json:    "--yolo"

Why

No error, no warning, and the output is well-formed — it simply does not match the file on disk. That makes it worse than a crash: the fabricated lines read as ground truth.

Observed 2026-07 while auditing a clink CLI config in pal-mcp-server. The doctored output built a false picture of the file that was nearly acted on, and was caught only because the rewritten line contradicted an earlier direct Read of the same file.

The root cause is imported muscle memory from grep -r. ripgrep is recursive by default, so there is no -r to add — the habit produces a flag that means something else entirely.

The durable fix

The rule ends by pointing at the structural answer rather than just "be careful": prefer the Grep tool over rg in Bash. It has no --replace surface, so this class of error cannot occur at all.

Also adds the diagnostic heuristic: if an rg result contradicts something you read directly, suspect the flags before you suspect the file.

🤖 Generated with Claude Code

https://claude.ai/code/session_019wryFZuz4HEs1oqY9EJfGo

`rg -rn "yolo"` does not mean "recursive + line numbers". `-r` takes an
argument, so the cluster silently consumes `n` as a replacement string and rg
rewrites every match in its output. The result is fabricated lines that look
exactly like real file contents:

    rg -rn "yolo" .
    ./conf/cli_clients/gemini.json:    "--n"     ← the file actually says "--yolo"

No error, no warning, well-formed output — it just doesn't match the file on
disk. Observed 2026-07 while auditing a clink config: the doctored line built a
false picture of the file that was nearly acted on, and was caught only because
it contradicted an earlier direct Read of the same file.

The trap is the muscle memory of `grep -r`. rg is recursive by default, so there
is no `-r` to add — and the Grep tool has no --replace surface at all, which is
the durable way to avoid the class.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019wryFZuz4HEs1oqY9EJfGo
@laurigates laurigates self-assigned this Jul 14, 2026
@github-actions github-actions Bot added documentation Improvements or additions to documentation claude size/s labels Jul 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Broken Links Detected

Summary

Status Count
🔍 Total 170
✅ Successful 159
⏳ Timeouts 1
🔀 Redirected 0
👻 Excluded 9
❓ Unknown 0
🚫 Errors 1

Errors per input

Errors in exact_dot_claude/docs/prds/daily-catchup.PRD.md

Errors in docs/adrs/0013-nixos-declarative-system-configuration.md


Please fix the broken links before merging.

@laurigates
laurigates merged commit 290930c into main Jul 14, 2026
7 of 8 checks passed
@laurigates
laurigates deleted the docs/rg-replace-flag-footgun branch July 14, 2026 11:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude documentation Improvements or additions to documentation size/s

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant