Claude Code hooks that block find/sed/cat, redirect to native tools

habibicode1 pts0 comments

GitHub - HabibiCodeCH/claude-no-bash-detour: Claude Code PreToolUse hooks that deny Bash commands with a native tool equivalent (find/grep chains, sed -i, cat/head/tail) and redirect to Grep/Glob/Edit/Read · GitHub

/" data-turbo-transient="true" />

Skip to content

Search or jump to...

Search code, repositories, users, issues, pull requests...

-->

Search

Clear

Search syntax tips

Provide feedback

--><br>We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Cancel

Submit feedback

Saved searches

Use saved searches to filter your results more quickly

-->

Name

Query

To see all available qualifiers, see our documentation.

Cancel

Create saved search

Sign in

/;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up

Appearance settings

Resetting focus

You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.

Dismiss alert

{{ message }}

HabibiCodeCH

claude-no-bash-detour

Public

Notifications<br>You must be signed in to change notification settings

Fork

Star

main

BranchesTags

Go to file

CodeOpen more actions menu

Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit

History<br>1 Commit<br>1 Commit

hooks

hooks

.gitignore

.gitignore

LICENSE

LICENSE

README.md

README.md

install.sh

install.sh

View all files

Repository files navigation

claude-no-bash-detour

A set of Claude Code PreToolUse hooks that deny specific Bash command<br>patterns which duplicate a built-in Claude Code tool, and tell Claude to use<br>that tool instead. Each hook is a standalone script; install one, some, or<br>all of them.

Why

Telling Claude in a CLAUDE.md file "don't use find -exec, use Grep/Glob"<br>doesn't reliably stick — instructions are a suggestion, not an enforcement<br>mechanism, and a model will still reach for a familiar shell one-liner under<br>the right prompt. It also means every Bash call built out of one of these<br>patterns shows up as a permission prompt for the user to approve, when the<br>native tool call wouldn't have needed approval at all.

A PreToolUse hook enforces it at the harness level instead: the hook runs<br>before the Bash tool call reaches you, denies it if it matches, and hands<br>Claude a reason it can act on — so it retries with the right tool rather than<br>just getting stuck. Configured once in settings.json, it applies to every<br>session and every subagent, so you're not approving (or fixing) the same<br>pattern repeatedly across parallel agents.

Hooks included

deny-find-chains.sh — use Grep/Glob

Blocks:

find . -name '*.log' -exec rm {} \;

find . -name '*.ts' | grep -v node_modules

find . -type f | xargs grep -l TODO

Doesn't touch: plain find with no -exec/piped grep, plain grep, or<br>"find"/"grep" appearing as substrings of another word or inside quoted<br>arguments (e.g. grep -rn "findUser" src, a path like my-find-exec-project/).

deny-sed-inplace.sh — use Edit

Blocks:

sed -i 's/foo/bar/' file.txt

sed -i.bak 's/foo/bar/' file.txt

sed -i '' 's/foo/bar/' file.txt (BSD/macOS)

gsed -i ... / sed --in-place ...

Doesn't touch: sed without -i (printing to stdout), or sed used to<br>transform piped text (git diff | sed 's/^/ /').

deny-cat-head-tail.sh — use Read

Blocks:

cat notes.txt

head -n 20 notes.txt

tail -c 100 notes.txt

sudo cat /etc/hosts

Doesn't touch: tail -f/--follow (streaming), cat file1 file2<br>(concatenating multiple files — Read handles one file at a time), anything<br>piped elsewhere (cat notes.txt | grep TODO, head -n 5 file | wc -l), and<br>anything redirected to a new file (cat notes.txt > copy.txt).

Limitations

These are text-pattern heuristics on the raw Bash command string, not a<br>shell parser — deliberately simple. They won't catch every possible<br>obfuscation (e.g. combined short-option clusters like sed -ni where -i<br>isn't the first letter after the dash, or a quoted file path containing a<br>space in deny-cat-head-tail.sh's naive whitespace tokenizer), and<br>deny-find-chains.sh/deny-sed-inplace.sh can't distinguish a real<br>invocation from a command that merely mentions the pattern in a comment or<br>string — both get denied. If you need airtight enforcement, that's a<br>different, heavier tool.

Install

/claude-no-bash-detour.git<br>cd claude-no-bash-detour<br>./install.sh # installs all hooks into ~/.claude/settings.json<br>./install.sh --project # installs all hooks into ./.claude/settings.json (this repo only)<br>./install.sh deny-sed-inplace # installs only the named hook(s)">git clone https://github.com/you>/claude-no-bash-detour.git<br>cd claude-no-bash-detour<br>./install.sh # installs all hooks into ~/.claude/settings.json<br>./install.sh --project # installs all hooks into ./.claude/settings.json (this repo only)<br>./install.sh deny-sed-inplace # installs only the named hook(s)

Requires jq. The installer copies each hook script<br>into /hooks/ and adds a...

claude bash hooks find grep deny

Related Articles