Are you the author? Sign in to claim
Claude Code PreToolUse hooks that deny Bash commands with a native tool equivalent (find/grep chains, sed -i, cat/head/t
Tired of Claude not working because it is waiting for you to approve a simple bash command? claude-no-bash-detour is for you!
3 Claude Code PreToolUse hooks that deny specific Bash command
patterns in favour of native tools instead. Each hook is a standalone script; install one, some, or
all of them.
Telling Claude in a CLAUDE.md file "don't use find -exec, use Grep/Glob"
doesn't work with certainty. .md instructions are merely suggestions and have no enforcement
mechanism. The model will still reach for a familiar shell one-liner under
the right prompt. It also means every Bash call built out of one of these
patterns shows up as a permission prompt for the user to approve, when the
native tool call wouldn't have needed approval at all.
A PreToolUse hook enforces it at the harness level instead: the hook runs
before the Bash tool call reaches the user, denies it if it matches, and hands
Claude a reason it can act on so it retries with the right tool rather than
just getting stuck. Configured once in settings.json, it applies to every
session and every subagent, so you're not approving (or fixing) the same
pattern repeatedly across parallel agents.
deny-find-chains.sh — use Grep/GlobBlocks:
find . -name '*.log' -exec rm {} \;find . -name '*.ts' | grep -v node_modulesfind . -type f | xargs grep -l TODODoesn't touch: plain find with no -exec/piped grep, plain grep, or
"find"/"grep" appearing as substrings of another word or inside quoted
arguments (e.g. grep -rn "findUser" src, a path like my-find-exec-project/).
deny-sed-inplace.sh — use EditBlocks:
sed -i 's/foo/bar/' file.txtsed -i.bak 's/foo/bar/' file.txtsed -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
transform piped text (git diff | sed 's/^/ /').
deny-cat-head-tail.sh — use ReadBlocks:
cat notes.txthead -n 20 notes.txttail -c 100 notes.txtsudo cat /etc/hostsDoesn't touch: tail -f/--follow (streaming), cat file1 file2
(concatenating multiple files — Read handles one file at a time), anything
piped elsewhere (cat notes.txt | grep TODO, head -n 5 file | wc -l), and
anything redirected to a new file (cat notes.txt > copy.txt).
These are text-pattern heuristics on the raw Bash command string, not a
shell parser — deliberately simple. They won't catch every possible
obfuscation (e.g. combined short-option clusters like sed -ni where -i
isn't the first letter after the dash, or a quoted file path containing a
space in deny-cat-head-tail.sh's naive whitespace tokenizer), and
deny-find-chains.sh/deny-sed-inplace.sh can't distinguish a real
invocation from a command that merely mentions the pattern in a comment or
string — both get denied. If you need airtight enforcement, that's a
different, heavier tool.
git clone https://github.com/<you>/claude-no-bash-detour.git
cd claude-no-bash-detour
./install.sh # installs all hooks into ~/.claude/settings.json
./install.sh --project # installs all hooks into ./.claude/settings.json (this repo only)
./install.sh deny-sed-inplace # installs only the named hook(s)
Requires jq. The installer copies each hook script
into <config-dir>/hooks/ and adds a Bash-matched PreToolUse entry per
hook to settings.json, without touching any of your existing hooks or
permissions. It's idempotent — running it again only installs what's
missing. A timestamped backup of your prior settings.json is written
before the first change.
After installing, restart Claude Code (or open /hooks once) to pick up the
change.
For each hook you want removed: delete the PreToolUse entry whose
matcher is "Bash" and whose command points at that hook's script from
settings.json, and delete the script from ~/.claude/hooks/.
Each hook script reads the hook's stdin JSON, pulls out
tool_input.command, and checks it against the patterns described above. On
a match it prints a hookSpecificOutput JSON blob with
permissionDecision: "deny" and a permissionDecisionReason pointing Claude
at the right tool; otherwise it exits silently and the command proceeds as
normal.
MIT
Design enforcement with memory — keeps your UI consistent across a project
Create animation-rich HTML presentations using a coding agent's frontend skills
1000+ skills curated from Anthropic, Vercel, Stripe, and other engineering teams
Detects 37 AI writing patterns and rewrites text with human rhythm across 5 voice profiles