Skip to content

Commit 52b46c2

Browse files
committed
chore: add guardrails blocking author trailers in commits
Project policy (CLAUDE.md + CONVENTIONS.md) forbids co-author lines in commit messages. One slipped into f6a621b despite the rule. Two layers added: - scripts/git-hooks/commit-msg: client-side git hook that rejects any commit containing a co-author trailer. Activate: `make install-hooks`. Bypass: --no-verify (agent use only). - .claude/hooks/no-coauthor.sh: Claude Code PreToolUse hook (exit 2) that hard-blocks Bash tool calls issuing git commit with the forbidden trailer, covering AI agent sessions as a second line of defense. - GNUmakefile: new `install-hooks` target (configures core.hooksPath). - .claude/settings.json: no-coauthor hook registered alongside serena-first.
1 parent 0e622f5 commit 52b46c2

4 files changed

Lines changed: 65 additions & 1 deletion

File tree

.claude/hooks/no-coauthor.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env bash
2+
# PreToolUse hook: block git commit commands containing Co-Authored-By trailer.
3+
# Project policy (CLAUDE.md + CONVENTIONS.md) strictly forbids co-author lines.
4+
# This catches Claude Code sub-agents that include the trailer before --no-verify
5+
# is applied, providing a second layer of defense alongside the commit-msg git hook.
6+
#
7+
# Exit codes (Claude Code PreToolUse semantics):
8+
# 0 → allow
9+
# 2 → BLOCK (hard rejection, tool call not executed)
10+
set -euo pipefail
11+
12+
input=$(cat)
13+
tool=$(echo "$input" | jq -r '.tool_name // ""')
14+
15+
[[ "$tool" != "Bash" ]] && exit 0
16+
17+
cmd=$(echo "$input" | jq -r '.tool_input.command // ""')
18+
19+
# Only inspect git commit invocations
20+
if ! echo "$cmd" | grep -qE '(^|[[:space:]])git[[:space:]].*commit'; then
21+
exit 0
22+
fi
23+
24+
# Check for Co-Authored-By in the command string (covers -m "...", HEREDOC, etc.)
25+
if echo "$cmd" | grep -iE 'co-?authored-?by' > /dev/null 2>&1; then
26+
cat >&2 <<'EOF'
27+
[no-coauthor] BLOCKED: git commit contains a Co-Authored-By trailer.
28+
Project policy (CLAUDE.md + CONVENTIONS.md) strictly forbids co-author lines.
29+
Remove the trailer from the commit message and retry.
30+
EOF
31+
exit 2
32+
fi
33+
34+
exit 0

.claude/settings.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@
1010
"command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/serena-first.sh\""
1111
}
1212
]
13+
},
14+
{
15+
"matcher": "Bash",
16+
"hooks": [
17+
{
18+
"type": "command",
19+
"command": "bash \"$CLAUDE_PROJECT_DIR/.claude/hooks/no-coauthor.sh\""
20+
}
21+
]
1322
}
1423
]
1524
}

GNUmakefile

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ VERSION=dev
99
OS_ARCH=$(shell go env GOOS)_$(shell go env GOARCH)
1010
PLUGIN_DIR=~/.terraform.d/plugins/$(HOSTNAME)/$(NAMESPACE)/$(TYPE)/$(VERSION)/$(OS_ARCH)
1111

12-
.PHONY: build test testacc lint generate docs install dev-override clean default
12+
.PHONY: build test testacc lint generate docs install install-hooks dev-override clean default
1313

1414
default: build
1515

@@ -42,6 +42,11 @@ install: build
4242
mkdir -p $(PLUGIN_DIR)
4343
cp $(BINARY_NAME) $(PLUGIN_DIR)/terraform-provider-$(TYPE)
4444

45+
install-hooks:
46+
@git config core.hooksPath scripts/git-hooks
47+
@echo "Git hooks installed (core.hooksPath = scripts/git-hooks)"
48+
@echo "commit-msg hook will reject Co-Authored-By trailers."
49+
4550
dev-override:
4651
@echo 'Add this to ~/.terraformrc:'
4752
@echo ''

scripts/git-hooks/commit-msg

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env bash
2+
# commit-msg hook: reject Co-Authored-By trailers (project policy, CLAUDE.md + CONVENTIONS.md)
3+
# Install: make install-hooks (sets core.hooksPath to scripts/git-hooks)
4+
# Bypass: git commit --no-verify (discouraged, agent-only use case)
5+
set -euo pipefail
6+
7+
msg_file="$1"
8+
9+
if grep -iE '^[[:space:]]*co-?authored-?by[[:space:]]*:' "$msg_file" > /dev/null 2>&1; then
10+
echo "ERROR [commit-msg]: Co-Authored-By trailer detected." >&2
11+
echo "Project policy (CLAUDE.md + CONVENTIONS.md) forbids co-author lines." >&2
12+
echo "Remove the trailer and retry. Use --no-verify to bypass (discouraged)." >&2
13+
exit 1
14+
fi
15+
16+
exit 0

0 commit comments

Comments
 (0)