#!/usr/bin/env bash # Pre-commit hook: keep .agents/skills/oci-deal-accelerator/SKILL.md # byte-aligned with the root SKILL.md (the source of truth that # CLAUDE.md / Claude Code reads). The Codex copy under .agents/ # follows the same content with an auto-generated banner — they MUST # stay in lock-step or Claude Code and Codex will give the user # different instructions. # # Behavior: # • If SKILL.md is staged but the .agents/ copy is not synced, # auto-run scripts/sync-skill.py and stage the result so the # commit ships both files together. # • If the script can't run (no python, etc.), abort with a clear # message rather than committing a desync silently. # # Install once per clone: make install-hooks (sets core.hooksPath) set -euo pipefail ROOT="$(git rev-parse --show-toplevel)" SOURCE="SKILL.md" TARGET=".agents/skills/oci-deal-accelerator/SKILL.md" SCRIPT="scripts/sync-skill.py" # Only act when SKILL.md is part of the staged change set. if ! git diff --cached --name-only | grep -qx "$SOURCE"; then exit 0 fi if [ ! -f "$ROOT/$SCRIPT" ]; then echo "pre-commit: $SCRIPT missing — cannot verify SKILL.md sync. Aborting." >&2 exit 1 fi PYTHON="$(command -v python3 || command -v python || true)" if [ -z "$PYTHON" ]; then echo "pre-commit: no python found in PATH — cannot run $SCRIPT. Aborting." >&2 exit 1 fi # Run the full sync, then stage the regenerated target so it travels # in the same commit. (Idempotent — if it was already in sync, the # file write is a no-op.) "$PYTHON" "$ROOT/$SCRIPT" >&2 git add "$ROOT/$TARGET" # Final check — if for any reason the result still drifts, fail loud. if ! "$PYTHON" "$ROOT/$SCRIPT" --check >/dev/null 2>&1; then echo "pre-commit: SKILL.md and $TARGET are still out of sync after auto-run." >&2 echo " Investigate scripts/sync-skill.py before committing." >&2 exit 1 fi exit 0