#!/bin/sh # PreToolUse(Bash) — validate all agent manifests before `git commit` in ~/.claude. # # Trigger: Bash command contains "git commit" AND current directory is under ~/.claude. # On validation failure: print FAIL list to stderr, exit 1 → Claude Code blocks the commit. # # Stdin: JSON with tool_input.command # Silent fall-through if jq is absent; otherwise `set -eu` would abort and # Claude Code would refuse the tool call system-wide. command -v jq >/dev/null 2>&1 || exit 0 # --- RUNTIME CONTROLS (v0.14.2) --- _hook_name="$(basename "$0" .sh)" case "${KEI_DISABLED_HOOKS:-}" in *"$_hook_name"*|*all*) exit 0 ;; esac case "${KEI_HOOK_PROFILE:-full}" in off) exit 0 ;; minimal) case "$_hook_name" in no-github-push|genesis-leak-guard|no-hand-edit-agents|secrets-guard|assemble-validate|git-pre-commit-genesis) ;; *) exit 0 ;; esac ;; advisory-off) case "$_hook_name" in recurrence-suggest|citation-verify|error-spike-detector|milestone-commit-hook) exit 0 ;; esac ;; full|*) ;; esac # --- end runtime controls --- set -eu ASSEMBLER="$HOME/.claude/agents/_assembler/target/release/assemble" [ -x "$ASSEMBLER" ] || exit 0 CMD=$(jq -r '.tool_input.command // empty') # Only act on git commit inside ~/.claude case "$CMD" in *"git commit"*) ;; *) exit 0 ;; esac # Check cwd is under ~/.claude case "$PWD" in "$HOME/.claude"*) ;; *) exit 0 ;; esac OUTPUT=$("$ASSEMBLER" --validate 2>&1 || true) if echo "$OUTPUT" | grep -q '^FAIL'; then echo "[assemble-validate] agent manifest validation FAILED:" >&2 echo "$OUTPUT" | grep -E '^(FAIL|OK)' | grep '^FAIL' >&2 echo "" >&2 echo "Fix manifests in ~/.claude/agents/_manifests/ before committing." >&2 echo "Run: $ASSEMBLER --validate" >&2 exit 1 fi exit 0