Created
June 12, 2026 18:26
-
-
Save v3rron/3da36803b2c45af10174fc3ee615c5c3 to your computer and use it in GitHub Desktop.
Claude Code PreToolUse hook: prompt for confirmation before dangerous bash commands (rm, git push/reset --hard/clean/rebase/merge/cherry-pick, brew, package publish)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # PreToolUse hook: forces a confirmation prompt for dangerous bash commands. | |
| # Returns permissionDecision: "ask" for dangerous commands, exits 0 (allow) otherwise. | |
| COMMAND=$(jq -r '.tool_input.command' < /dev/stdin) | |
| # Extract the first command in pipes/chains by stripping everything after shell | |
| # operators. Leading VAR=value assignments are stripped first so env-prefixed | |
| # commands (FOO=1 git push) can't dodge the patterns. | |
| BASE_CMD=$(echo "$COMMAND" | sed -E 's/^([A-Za-z_][A-Za-z0-9_]*=[^ ]* +)+//' | sed 's/[;&|].*//' | xargs) | |
| # Check each dangerous pattern | |
| case "$BASE_CMD" in | |
| rm\ *|rm) | |
| REASON="File deletion: rm" ;; | |
| rmdir\ *|rmdir) | |
| REASON="Directory deletion: rmdir" ;; | |
| git\ push*|git\ -C\ *push*) | |
| REASON="Git push" ;; | |
| git\ reset\ --hard*|git\ -C\ *reset\ --hard*) | |
| REASON="Git reset --hard" ;; | |
| git\ clean*|git\ -C\ *clean*) | |
| REASON="Git clean" ;; | |
| git\ rebase*|git\ -C\ *rebase*) | |
| REASON="Git rebase" ;; | |
| git\ merge*|git\ -C\ *merge*) | |
| REASON="Git merge" ;; | |
| git\ cherry-pick*|git\ -C\ *cherry-pick*) | |
| REASON="Git cherry-pick" ;; | |
| brew\ *) | |
| REASON="Homebrew command" ;; | |
| npm\ publish*|gem\ push*|yarn\ publish*) | |
| REASON="Package publish" ;; | |
| *) | |
| # Also check for dangerous commands embedded after && or || or ; or | | |
| if echo "$COMMAND" | grep -qE '(^|[;&|]\s*)([A-Za-z_][A-Za-z0-9_]*=[^ ]+ +)*(rm|rmdir)\s'; then | |
| REASON="Embedded file deletion detected" | |
| elif echo "$COMMAND" | grep -qE '(^|[;&|]\s*)([A-Za-z_][A-Za-z0-9_]*=[^ ]+ +)*git\s+(commit|push|reset\s+--hard|clean|rebase|merge|cherry-pick)'; then | |
| REASON="Embedded dangerous git command detected" | |
| else | |
| exit 0 | |
| fi | |
| ;; | |
| esac | |
| jq -n --arg reason "$REASON" '{ | |
| hookSpecificOutput: { | |
| hookEventName: "PreToolUse", | |
| permissionDecision: "ask", | |
| permissionDecisionReason: $reason | |
| } | |
| }' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment