Skip to content

PreCommit hook event in settings template is not a valid Claude Code event #1103

@Josulo72

Description

@Josulo72

Summary

The settings.local.json template installed by install.py registers four hooks under a PreCommit event key:

  • auto_test.py
  • security_scan.py
  • validate_claude_md_size.py
  • enforce_regression_test.py

Claude Code does NOT recognize PreCommit as a valid hook event. The entry is rejected on load, and because "Files with errors are skipped entirely, not just the invalid settings", the whole settings.local.json is dropped — so every other valid hook in the file also stops firing.

Version

  • autonomous-dev: 3.51.0
  • Claude Code: 2.1.144 (native installer on Ubuntu/WSL2)

Reproduction

  1. Fresh install via the documented one-liner: bash <(curl -sSL https://raw.githubusercontent.com/akaszubski/autonomous-dev/master/install.sh)
  2. Open Claude Code in the project directory.
  3. Observe the startup warning:
.claude/settings.local.json
└ hooks
  └ PreCommit: Unknown hook event "PreCommit" was ignored.
    Valid events: PreToolUse, PostToolUse, PostToolUseFailure,
    PostToolBatch, Notification, UserPromptSubmit, UserPromptExpansion,
    SessionStart, SessionEnd, Stop, StopFailure, SubagentStart,
    SubagentStop, PreCompact, PostCompact, PermissionRequest,
    PermissionDenied, Setup, TeammateIdle, TaskCreated, TaskCompleted,
    Elicitation, ElicitationResult, ConfigChange, WorktreeCreate,
    WorktreeRemove, InstructionsLoaded, CwdChanged, FileChanged

Expected behaviour

The four scripts under PreCommit should run before git commit operations, as their names and docs suggest.

Actual behaviour

They never fire. The hooks exist on disk but Claude Code does not dispatch them, because PreCommit is not in the supported event list.

Suggested fix

Claude Code has no native pre-commit lifecycle (git owns commits, not Claude). Two valid alternatives:

(A) PreToolUse with Bash matcher + script filter — intercept Bash invocations, check whether the command is git commit, and run the gates only then:

"PreToolUse": [{
  "matcher": "Bash",
  "hooks": [{
    "type": "command",
    "command": "python .claude/hooks/precommit_dispatcher.py"
  }]
}]

The dispatcher reads tool_input.command from stdin and exits non-zero when the command is a git commit that fails one of the four gates.

(B) Classic git hook in .git/hooks/pre-commit installed by install.py. This lives outside Claude Code entirely; git invokes it. Less elegant for multi-user repos but technically robust.

Impact

Users relying on the documented behaviour (auto_test.py blocks broken tests, security_scan.py blocks committed secrets, etc.) get zero enforcement today. Combined with the related matcher issue, the whole settings.local.json is dropped, so even unrelated hooks stop working.

Happy to submit a PR with the PreToolUse + Bash dispatcher approach if that direction is acceptable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions