#!/bin/bash # branch-guard installer for Claude Code # Usage: curl -fsSL https://raw.githubusercontent.com/Bande-a-Bonnot/Boucle-framework/main/tools/branch-guard/install.sh | bash set -euo pipefail HOOK_NAME="branch-guard" HOOK_URL="https://raw.githubusercontent.com/Bande-a-Bonnot/Boucle-framework/main/tools/branch-guard/hook.sh" HOOK_DIR="$HOME/.claude/$HOOK_NAME" HOOK_PATH="$HOOK_DIR/hook.sh" SETTINGS_FILE="$HOME/.claude/settings.json" echo "Installing $HOOK_NAME for Claude Code..." # Check python3 (needed for settings.json management) if ! command -v python3 >/dev/null 2>&1; then echo "Error: python3 not found. Install Python 3 and try again." >&2 exit 1 fi # Check jq (needed at runtime to parse Claude Code hook input) if ! command -v jq >/dev/null 2>&1; then echo "Error: jq not found. $HOOK_NAME requires jq at runtime." >&2 echo " Install: brew install jq (macOS) or apt install jq (Linux)" >&2 exit 1 fi # Create hook directory mkdir -p "$HOOK_DIR" # Download hook echo " Downloading hook..." if command -v curl &>/dev/null; then curl -fsSL "$HOOK_URL" -o "$HOOK_PATH" elif command -v wget &>/dev/null; then wget -q "$HOOK_URL" -O "$HOOK_PATH" else echo "Error: curl or wget required" >&2 exit 1 fi chmod +x "$HOOK_PATH" # Verify download is not empty if [ ! -s "$HOOK_PATH" ]; then echo "Error: downloaded file is empty. The URL may have changed." >&2 exit 1 fi # Handle JSONC comments in settings.json (prevents silent failures) if [ -f "$SETTINGS_FILE" ]; then if ! python3 -c "import json,sys; json.load(open(sys.argv[1]))" "$SETTINGS_FILE" 2>/dev/null; then python3 - "$SETTINGS_FILE" << 'JSONC_FIX' import json, sys, shutil path = sys.argv[1] with open(path) as f: raw = f.read() o, i, n, q = [], 0, len(raw), False while i < n: if q: if raw[i] == '\\' and i+1/dev/null || { echo " Warning: Could not auto-register. Add manually to $SETTINGS_FILE:" echo " hooks.PreToolUse: [{\"type\": \"command\", \"command\": \"$HOOK_PATH\"}]" } else mkdir -p "$(dirname "$SETTINGS_FILE")" cat > "$SETTINGS_FILE" <