Hey there, it's your resident "old man" developer, 38 years old and tinkering with AI trading bots in my spare time.
One evening, as I was routinely checking my bot's logs, disaster struck. I wanted to search the entire repository for a specific log output, so I mindlessly typed this into my terminal:
grep -r "some_keyword" .
The next second, my PC's fans roared like a Formula 1 car, and my mouse cursor started lagging severely. I opened Task Manager, and sure enough, CPU usage was pegged at 100%. I genuinely thought my machine was on its last legs. The culprits? grep.exe and, consequently, Windows Defender's real-time scan, which went haywire.
Ultimately, I had to force-restart my PC. Who knew a simple grep could cause such a catastrophe? Today, I'm sharing the story of this "grep scream incident" and the mechanism I built to prevent it from ever happening again.
The Problem: .gitignore Is Just a Text File
Why did grep go rogue? The reason became clear quickly.
My repository contained several massive log files generated by the bot. These were temporarily placed there for testing, with the largest one clocking in at 23GB. Naturally, I had these files properly listed in .gitignore to exclude them from Git's tracking.
But here's where my huge misconception lay: the shell's grep command knows absolutely nothing about .gitignore. To grep, .gitignore is just ignore.txt—nothing more, nothing less.
grep -r recursively, and naively, reads all files under the current directory. So, it plunged headfirst into that 23GB log file. No wonder the CPU screamed.
This same issue can occur with find . | xargs grep "..." or PowerShell's Select-String -Path . -Pattern "..." -Recurse. Essentially, any command that recursively scans the file system is susceptible to this trap.
Especially when working with automated trading bots, gigabyte-sized logs and data files are a daily occurrence. It seems personal development environments are particularly prone to these kinds of accidents.
The Solution: "Being Careful" Isn't Enough, So I Automated It
Even if I vow to use rg (ripgrep) or ag—which respect .gitignore—I can already foresee myself accidentally typing grep out of habit. Humans forget, and humans make mistakes.
So, instead of relying on "being careful," I opted for an approach that would "physically prevent execution."
Specifically, I leveraged a "hook" mechanism that kicks off a specific script right before a command is executed in the terminal. If a dangerous grep command is about to run, the hook detects and blocks it.
I wrote this hook script in JavaScript. What it does is simple: it checks the command string using a regular expression.
// Check the command line about to be executed with a regular expression
// Roughly detect grep-like command call patterns
const GREP_CALL = /(?:^|[\s(])(?:[^\s|;&]*[\\/])?(r|e|f)?grep(?:\.exe)?(?:\s+(.*))?$/s;
// Detect short recursive flags like -r or -R
const SHORT_RECURSIVE_FLAG = /(?:^|\s)-(?!-)[A-Za-z]*[rR][A-Za-z]*(?=\s|$)/;
// findstr /s on Windows is equally dangerous, so detect it too
const FINDSTR_SUBDIRS = /\bfindstr(?:\.exe)?\b[^|;\n]*\s\/s\b/i;
function shouldBlock(toolName, command) {
// Only target Bash or PowerShell execution
if (toolName !== 'Bash' && toolName !== 'PowerShell') return false;
// findstr /s is an immediate block
if (FINDSTR_SUBDIRS.test(command)) return true;
// Split the command by pipes or semicolons and check if any segment
// includes a recursive grep call
return command.split(/\|\||&&|[|;\n]/).some(isRecursiveGrepSegment);
}
function isRecursiveGrepSegment(segment) {
const match = segment.match(GREP_CALL);
if (!match) return false;
const args = match[2] || '';
// Check for long flags like --recursive or --directories=recurse
const hasLongRecursiveFlag = /\s--(recursive|directories=recurse)\b/.test(args);
// Check for short flags like -r, -R
const hasShortRecursiveFlag = SHORT_RECURSIVE_FLAG.test(args);
return hasLongRecursiveFlag || hasShortRecursiveFlag;
}
With this script integrated into a hook, if I accidentally type grep -r ., the command will be blocked before execution with a message like: "Dangerous command! Please use rg instead." Peace of mind achieved.
The regular expression is a bit messy because I wanted to detect not just grep -r but also -R, --recursive, and grep commands connected via pipes. findstr /s causes equally nasty accidents, so I included it in the block list as well.
Summary and Lessons Learned
What I learned from this incident is, while obvious, crucial: you'll get burned if you don't properly understand what your tools are doing implicitly.
-
.gitignoreis Git's rulebook, not the shell's. - Mechanical prevention is more robust and reliable than relying on self-discipline.
- In personal development, especially with automation and bot development, huge files can be generated unintentionally. Safety measures in the development environment, though seemingly trivial, are incredibly important.
Just grep, but grep can be a beast. To keep my PC from screaming, I need to properly understand the characteristics of my tools. With this, I've made my development environment safer for those late-night coding sessions. 👍
I build and run small Python systems — trading bots, RAG APIs, scheduled automation — and write up whatever breaks along the way.
If a provider-agnostic RAG Q&A API is useful to you, mine is MIT-licensed on GitHub: rag-faq-api. It runs and passes its full test suite **with no API key* (offline stub LLM + hashing embedder), swaps to Claude / Gemini / OpenAI via one env var, and ships a retrieval-quality harness (Hit@k / MRR / Recall@k) with a chunking sweep.*
Top comments (1)
Rough experience, glad the hook caught it going forward. Worth knowing for next time:
git grep(built into every Git install, no extra tool needed) sidesteps this exact trap by default. It only searches tracked files, so anything covered by.gitignore— including that 23GB log — is automatically excluded, no config or hook required.git grep --untrackedextends that to untracked-but-not-ignored files if you want a broader search, still skipping ignored ones. The custom hook is still a nice safety net for anyone who might type plaingrep -rout of habit, but if the search always happens inside a repo,git grepsolves the root problem (grep not knowing what.gitignoremeans) rather than blocking the symptom.