#!/bin/bash
set +e
INPUT=""
if [ ! -t 0 ]; then
INPUT="$(cat 2>/dev/null)"
fi
[ -z "$INPUT" ] && exit 0
TOOL_NAME=""
COMMAND=""
if command -v jq >/dev/null 2>&1; then
TOOL_NAME="$(printf '%s' "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)"
COMMAND="$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)"
elif command -v python3 >/dev/null 2>&1; then
eval "$(printf '%s' "$INPUT" | python3 -c '
import json, shlex, sys
try:
data = json.load(sys.stdin)
except Exception:
data = {}
tool_name = data.get("tool_name") or ""
tool_input = data.get("tool_input") or {}
command = tool_input.get("command") or ""
print(f"TOOL_NAME={shlex.quote(tool_name)}")
print(f"COMMAND={shlex.quote(command)}")
' 2>/dev/null)"
fi
if [ "$TOOL_NAME" = "Edit" ] || [ "$TOOL_NAME" = "Write" ]; then
printf '%s' '{"hookSpecificOutput":{"hookEventName":"PermissionRequest","decision":{"behavior":"allow"}}}'
exit 0
fi
[ "$TOOL_NAME" != "Bash" ] && exit 0
[ -z "$COMMAND" ] && exit 0
CWD=""
if command -v jq >/dev/null 2>&1; then
CWD="$(printf '%s' "$INPUT" | jq -r '.cwd // empty' 2>/dev/null)"
elif command -v python3 >/dev/null 2>&1; then
CWD="$(printf '%s' "$INPUT" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("cwd",""))' 2>/dev/null)"
fi
is_pkg_manager_allowed() {
local allowlist_file="${CWD:-.}/.claude/config/allowed-pkg-managers.json"
[ ! -f "$allowlist_file" ] && return 1
local allowed="false"
if command -v jq >/dev/null 2>&1; then
allowed=$(jq -r '.allowed // false' "$allowlist_file" 2>/dev/null || echo "false")
elif command -v python3 >/dev/null 2>&1; then
allowed=$(python3 -c '
import json,sys
try:
with open(sys.argv[1]) as f: data=json.load(f)
print("true" if data.get("allowed") is True else "false")
except: print("false")
' "$allowlist_file" 2>/dev/null || echo "false")
fi
[ "$allowed" = "true" ]
}
is_safe() {
local cmd="$1"
if [[ "$cmd" == *$'\n'* || "$cmd" == *$'\r'* ]]; then
return 1
fi
echo "$cmd" | grep -Eq '[;&|<>`$]' && return 1
echo "$cmd" | grep -Eiq '^git[[:space:]]+(status|diff|log|branch|rev-parse|show|ls-files)([[:space:]]|$)' && return 0
if echo "$cmd" | grep -Eiq '^(npm|pnpm|yarn)[[:space:]]+(test|run[[:space:]]+(test|lint|typecheck|build|validate)|lint|typecheck|build)([[:space:]]|$)'; then
is_pkg_manager_allowed && return 0
return 1
fi
echo "$cmd" | grep -Eiq '^(pytest|python[[:space:]]+-m[[:space:]]+pytest)([[:space:]]|$)' && return 0
echo "$cmd" | grep -Eiq '^(go[[:space:]]+test|cargo[[:space:]]+test)([[:space:]]|$)' && return 0
return 1
}
if is_safe "$COMMAND"; then
printf '%s' "{\"hookSpecificOutput\":{\"hookEventName\":\"PermissionRequest\",\"decision\":{\"behavior\":\"allow\"}}}"
fi
exit 0