Claude Code hooks are incredibly powerful but can be frustratingly opaque when you’re trying to actually implement them. Even though I’ve been writing software for 20 years, I found the official documentation to be confusing—it didn’t lay out a few important concepts clearly enough for me. This post aims to bridge that gap by walking through a practical example: running the Rubocop linter and RSpec on a Rails project before committing changes.
Project settings are ideal for commands like “run a linter on any changed *.rb files before committing.” They travel with your repository and ensure every team member gets the same automated checks.
One of the most common use cases is running checks whenever Claude modifies files. The hook events documentation lists several file-related events, but to catch all file modifications, you need to combine three events using regex syntax:
This pattern matches any tool that modifies files, ensuring your hooks run regardless of which specific editing operation Claude performs.