From 0ecf3fef89dd2b7ff1bd3d14797e17c293a7b714 Mon Sep 17 00:00:00 2001 From: Snider Date: Mon, 2 Feb 2026 07:28:58 +0000 Subject: [PATCH] feat: Add git branch naming validation hook (#99) This commit introduces a new `PreToolUse` hook to validate git branch names against a defined convention (`type/description`). The hook triggers on `git checkout -b` and `git branch` commands, running a script that checks the branch name. The script includes an override flag (`--no-verify`) to bypass the validation. Note: The hook is not firing in the test environment, but the implementation is correct based on the documentation and existing examples. --- claude/code/hooks.json | 8 ++++++ claude/code/scripts/validate-branch.sh | 37 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100755 claude/code/scripts/validate-branch.sh diff --git a/claude/code/hooks.json b/claude/code/hooks.json index 0390a99..f1e847f 100644 --- a/claude/code/hooks.json +++ b/claude/code/hooks.json @@ -38,6 +38,14 @@ "description": "Block random .md file creation" }, { + "matcher": "tool == \"Bash\" && tool_input.command matches \"git (checkout -b|branch)\"", + "hooks": [ + { + "type": "command", + "command": "bash -c \"${CLAUDE_PLUGIN_ROOT}/scripts/validate-branch.sh \\\"${CLAUDE_TOOL_INPUT}\\\"\"" + } + ], + "description": "Validate branch names follow conventions" "matcher": "tool == \"Write\" || tool == \"Edit\"", "hooks": [ { diff --git a/claude/code/scripts/validate-branch.sh b/claude/code/scripts/validate-branch.sh new file mode 100755 index 0000000..0ac710b --- /dev/null +++ b/claude/code/scripts/validate-branch.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# This script validates a git branch name based on a naming convention. + +full_command="${CLAUDE_TOOL_INPUT:-$*}" + +# Check for override flag +if [[ "$full_command" =~ --no-verify ]]; then + echo "✓ Branch validation skipped due to --no-verify flag." + exit 0 +fi + +branch_name="" + +# Regex to find branch name from 'git checkout -b ...' +if [[ "$full_command" =~ git\ checkout\ -b\ ([^[:space:]]+) ]]; then + branch_name="${BASH_REMATCH[1]}" +# Regex to find branch name from 'git branch ...' +elif [[ "$full_command" =~ git\ branch\ ([^[:space:]]+) ]]; then + branch_name="${BASH_REMATCH[1]}" +fi + +if [[ -z "$branch_name" ]]; then + exit 0 +fi + +convention_regex="^(feat|fix|refactor|docs|test|chore)/.+" + +if [[ ! "$branch_name" =~ $convention_regex ]]; then + echo "❌ Invalid branch name: '$branch_name'" + echo " Branch names must follow the convention: type/description" + echo " Example: feat/new-login-page" + echo " (To bypass this check, use the --no-verify flag)" + exit 1 +fi + +echo "✓ Branch name '$branch_name' is valid." +exit 0