diff --git a/.claude/hooks/guard-main-branch.sh b/.claude/hooks/guard-main-branch.sh index c7eeea9475..7a3a8189a0 100755 --- a/.claude/hooks/guard-main-branch.sh +++ b/.claude/hooks/guard-main-branch.sh @@ -16,6 +16,23 @@ command="$(echo "$input" | jq -r '.tool_input.command // empty')" if [[ "$command" =~ ^git\ (push|reset|revert|checkout|merge|rebase|commit|add) ]]; then branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || true)" if [[ "$branch" == "main" ]]; then - echo "BLOCK: You are on the main branch. Create or switch to a feature branch first." + echo "BLOCK: You are on the main branch. Create or switch to a feature branch first." >&2 + exit 2 + fi +fi + +# Block force-push targeting main from any branch. +if [[ "$command" =~ ^git[[:space:]]+push([[:space:]]|$) ]]; then + has_force=false + if [[ "$command" =~ (--force([[:space:]]|=|$)|--force-with-lease|[[:space:]]-f([[:space:]]|$)) ]]; then + has_force=true + fi + # `+ref` refspec syntax is also a force push. + if [[ "$command" =~ [[:space:]]\+[A-Za-z] ]]; then + has_force=true + fi + if $has_force && [[ "$command" =~ (^|[[:space:]:])\+?main([[:space:]]|$) ]]; then + echo "BLOCK: Force-push to main is not allowed via Claude. Run it yourself if you really mean to." >&2 + exit 2 fi fi diff --git a/.claude/settings.json b/.claude/settings.json index 1ef3704831..24575147e4 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -72,7 +72,13 @@ "Bash(chown:*)", "Bash(truncate:*)", "Bash(shred:*)", - "Bash(unlink:*)" + "Bash(unlink:*)", + "mcp__claude_ai_Stripe", + "mcp__claude_ai_Gmail", + "mcp__claude_ai_Google_Calendar", + "mcp__claude_ai_Google_Drive", + "mcp__claude_ai_Slack", + "mcp__claude_ai_Linear" ] }, "enableAllProjectMcpServers": true,