#!/usr/bin/env python3 import json import sys import re try: input_data = json.load(sys.stdin) except json.JSONDecodeError as e: print(f"Error: Invalid JSON input: {e}", file=sys.stderr) sys.exit(1) tool_name = input_data.get("tool_name", "") tool_input = input_data.get("tool_input", {}) command = tool_input.get("command", "") # Only validate git checkout -b commands if tool_name != "Bash" or "git checkout -b" not in command: sys.exit(0) # Extract branch name match = re.search(r'git checkout -b\s+([^\s]+)', command) if not match: sys.exit(0) branch_name = match.group(1) # Allow main and develop branches if branch_name in ["main", "develop"]: sys.exit(0) # Validate Git Flow naming convention if not re.match(r'^(feature|release|hotfix)/', branch_name): reason = f"""❌ Invalid Git Flow branch name: {branch_name} Git Flow branches must follow these patterns: • feature/ • release/v.. • hotfix/ Examples: ✅ feature/user-authentication ✅ release/v1.2.0 ✅ hotfix/critical-security-fix Invalid: ❌ {branch_name} (missing Git Flow prefix) ❌ feat/something (use 'feature/' not 'feat/') ❌ fix/bug (use 'hotfix/' not 'fix/') 💡 Use Git Flow commands instead: /feature - Create feature branch /release - Create release branch /hotfix - Create hotfix branch""" output = { "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": reason } } print(json.dumps(output)) sys.exit(0) # Validate release version format if branch_name.startswith("release/"): if not re.match(r'^release/v\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$', branch_name): reason = f"""❌ Invalid release version: {branch_name} Release branches must follow semantic versioning: release/vMAJOR.MINOR.PATCH[-prerelease] Valid examples: ✅ release/v1.0.0 ✅ release/v2.1.3 ✅ release/v1.0.0-beta.1 Invalid: ❌ release/1.0.0 (missing 'v' prefix) ❌ release/v1.0 (incomplete version) ❌ {branch_name} 💡 Use: /release v1.2.0""" output = { "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": reason } } print(json.dumps(output)) sys.exit(0) # Allow the command sys.exit(0)