Files
claude-plugin-hooklib/hooks/dispatch.sh
T

37 lines
1.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# hooklib dispatcher — routes one Claude Code hook event to every drop-in
# script under hooks/<event>.d/, in lexical order.
#
# Usage (from hooks.json): dispatch.sh <EventName>
#
# The event JSON is read once from stdin and replayed to each sub-hook on
# its own stdin. A sub-hook that wants to act prints a hook JSON response
# (e.g. a PreToolUse permissionDecision) to stdout and exits 0. The FIRST
# sub-hook to emit non-empty stdout wins: the dispatcher forwards that
# response verbatim and stops. If no sub-hook emits anything, the dispatcher
# stays silent and exits 0, which Claude Code treats as "no opinion / allow".
#
# Adding a hook is just dropping an executable script into the matching
# hooks/<event>.d/ directory — no wiring changes required.
set -euo pipefail
event="${1:?dispatch.sh needs an event name}"
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
dir="${here}/$(printf '%s' "$event" | tr '[:upper:]' '[:lower:]').d"
payload="$(cat)"
[ -d "$dir" ] || exit 0
for hook in "$dir"/*.sh; do
[ -e "$hook" ] || continue
out="$(printf '%s' "$payload" | bash "$hook" || true)"
if [ -n "$out" ]; then
printf '%s\n' "$out"
exit 0
fi
done
exit 0