Skip to content

Fix git commit blocking hook to use stderr and add comprehensive tests#167

Merged
nhorton merged 1 commit intomainfrom
claude/fix-bash-hook-fuYxr
Jan 26, 2026
Merged

Fix git commit blocking hook to use stderr and add comprehensive tests#167
nhorton merged 1 commit intomainfrom
claude/fix-bash-hook-fuYxr

Conversation

@nhorton
Copy link
Contributor

@nhorton nhorton commented Jan 26, 2026

Summary

Updated the block_bash_with_instructions.sh hook to correctly output blocking messages to stderr instead of stdout, and added comprehensive test coverage for the hook's behavior.

Key Changes

Hook Script Updates

  • Output format: Changed from JSON output to stdout to plain text output to stderr, aligning with Claude Code's hook contract for exit code 2 handling
  • Pattern matching: Improved the git commit regex pattern from git[[:space:]]+commit to ^[[:space:]]*git[[:space:]]+commit to:
    • Anchor matching to the start of the command (prevents false positives)
    • Allow optional leading whitespace
    • Prevent blocking commands that merely contain "git commit" as a substring

Test Suite

Added tests/shell_script_tests/test_block_bash_with_instructions.py with 323 lines of comprehensive test coverage:

  • Existence & permissions: Verify script exists and is executable
  • Git commit blocking: Test that git commit and variants are blocked with exit code 2
  • Allowed commands: Verify git operations (status, add, diff, log) and non-git commands pass through
  • Non-Bash tools: Confirm hook doesn't interfere with other tool types
  • Edge cases: Handle empty input, missing commands, invalid JSON, and substring matching
  • Output format: Validate correct use of stdout/stderr and exit codes

Implementation Details

  • The hook now correctly implements the PreToolUse hook contract: exit code 0 allows, exit code 2 blocks with stderr message
  • Pattern anchoring prevents false positives (e.g., echo 'git commit' is now allowed)
  • Tests use subprocess to simulate actual hook invocation with JSON input matching Claude Code's format
  • All tests verify both the exit code and message content for proper user guidance

https://claude.ai/code/session_017cJ4AjRrK9JHoP17StFk6J

@nhorton nhorton force-pushed the claude/fix-bash-hook-fuYxr branch 2 times, most recently from 09e4497 to 3d6faeb Compare January 26, 2026 22:56
The block_bash_with_instructions.sh hook had two issues:
1. It output error messages as JSON to stdout instead of plain text to stderr
2. The regex pattern matched 'git commit' anywhere in the command string

According to Claude Code hook documentation, PreToolUse hooks with exit code 2
should output their error message to stderr, not stdout with JSON.

Additionally, the regex pattern was too broad and would match 'git commit'
appearing in commit message bodies or argument strings. The pattern is now
anchored to match only at the start of the command.

Changes:
- Updated hook to write error message to stderr instead of JSON to stdout
- Anchored regex pattern with ^[[:space:]]* to match only command start
- Updated documentation comments to reflect correct output behavior
- Added comprehensive test suite with 18 tests covering:
  - Git commit blocking scenarios
  - Allowed command passthrough
  - Non-Bash tool handling
  - Edge cases (empty input, invalid JSON, 'git commit' in message body)
  - Output format compliance

https://claude.ai/code/session_017cJ4AjRrK9JHoP17StFk6J
@nhorton nhorton force-pushed the claude/fix-bash-hook-fuYxr branch from 3d6faeb to f42bb9a Compare January 26, 2026 23:03
@nhorton nhorton merged commit bce8175 into main Jan 26, 2026
4 checks passed
@nhorton nhorton deleted the claude/fix-bash-hook-fuYxr branch January 26, 2026 23:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants