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...