Release · v2.26.2
Enforce meaningful branch names via a PreToolUse…
chore: enforce meaningful branch names via a PreToolUse hook
Details
Work kept landing on auto-generated `claude/*` placeholder branches because the only safeguard was prose in CLAUDE.md, which loses to the web/Cloud harness's explicit "develop on the designated `claude/...` branch" instruction. Make the rule deterministic instead of advisory. - Add `.claude/hooks/guard-branch-names.py`: a PreToolUse hook that denies `git push` and GitHub `create_pull_request` when the branch is a `claude/*` placeholder, with a message telling Claude to rename to a meaningful `type/short-description` branch first. Detection is segment-aware (catches loop-wrapped / chained / env-prefixed pushes, bare/HEAD pushes via the current branch, and the MCP PR head) while ignoring mere mentions inside echo/grep/comments. Branch deletions (`git push --delete`, `:branch`) stay allowed for cleanup. - Wire it into `.claude/settings.json` (matcher `Bash|mcp__github__create_pull_request`), preserving the existing Stop hook. - Strengthen the CLAUDE.md git-conventions section to explicitly resolve the conflict: the harness's designated-branch instruction governs where commits land, not the name — rename before the first push/PR. Verified: 24-case unit battery on the hook (placeholder push/PR denied, meaningful allowed, deletions allowed, echo/grep mentions not blocked); a live in-session push of a `claude/*` branch is blocked while a `feat/*` push passes; and 4 sandbox agents started on placeholder branches all shipped from meaningful names (fix/…, docs/…), renaming proactively. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Siw4HBDfxn2sBiDFBpNkPN
Files changed (3)
| .claude/hooks/guard-branch-names.py | +157 | −0 |
| .claude/settings.json | +13 | −0 |
| CLAUDE.md | +15 | −3 |