Claude Hooks
View SourceClaude provides a modern atom-based hook system that integrates with Claude Code to ensure your Elixir code is production-ready. The hooks use sensible defaults and can be configured with simple atom shortcuts.
📋 Quick Reference: See the Hooks Cheatsheet for a concise reference of configuration options and patterns.
Documentation
For complete documentation on Claude Code's hook system:
- Official Hooks Reference - Complete API reference
- Hooks Guide - Getting started with examples
For a quick reference of all hook configurations, see the Hook Configuration Cheatsheet.
What Claude Installs
When you run mix igniter.install claude
, it automatically sets up default hooks:
%{
hooks: %{
stop: [:compile, :format],
subagent_stop: [:compile, :format],
post_tool_use: [:compile, :format],
# These only run on git commit commands
pre_tool_use: [:compile, :format, :unused_deps]
}
}
This provides:
- Format checking - Alerts when Elixir files need formatting
- Compilation checking - Catches errors and warnings immediately
- Pre-commit validation - Ensures clean code before commits
Available Hook Atoms
Claude provides these atom shortcuts that expand to full hook configurations:
Available Hooks
:compile
- Runsmix compile --warnings-as-errors
withhalt_pipeline?: true
(stops on failure)- For
stop
/subagent_stop
: Usesblocking?: false
to prevent infinite loops
- For
:format
- Runsmix format --check-formatted
(checks only, doesn't auto-format)- For
stop
/subagent_stop
: Usesblocking?: false
to prevent infinite loops
- For
:unused_deps
- Runsmix deps.unlock --check-unused
(pre_tool_use on git commits only)
Hook Events
Different hook events run at different times:
pre_tool_use
- Before tool execution (can block tools)post_tool_use
- After tool execution completes successfullyuser_prompt_submit
- Before processing user prompts (can add context or block)notification
- When Claude needs permission or input is idlestop
- When Claude Code finishes responding (main agent)subagent_stop
- When a sub-agent finishes respondingpre_compact
- Before context compaction (manual or automatic)session_start
- When Claude Code starts or resumes a session
⚠️ Stop Hook Loop Prevention
Stop and subagent_stop hooks use blocking?: false
by default to prevent infinite loops:
- When a stop hook fails with
blocking?: true
, it sends error feedback to Claude - Claude tries to fix the issue and finishes responding again
- This triggers the stop hook again, creating an infinite loop
The default blocking?: false
setting keeps you informed about issues without causing Claude to get stuck. If you need blocking behavior, explicitly set blocking?: true
but be aware of the loop risk.
Advanced Configuration
You can mix atom shortcuts with explicit configurations:
%{
hooks: %{
# Standard hooks
post_tool_use: [:compile, :format],
# Custom hook with options
stop: [
:format,
{"custom_task", halt_pipeline?: true},
{"cmd echo 'Done'", blocking?: false}
],
# Conditional execution
pre_tool_use: [
{"test", when: "Bash", command: ~r/^git push/}
],
# Control output verbosity (rarely needed)
subagent_stop: [
{:compile, output: :full}, # WARNING: Can cause context overflow
:format # Default :none - recommended
]
}
}
Hook Options
:when
- Tool/event matcher (atoms, strings, or lists):command
- Additional command pattern for Bash (string or regex):halt_pipeline?
- Stop subsequent hooks on failure (default: false):blocking?
- Treat non-zero exit as blocking error (default: true):env
- Environment variables as a map:output
- Control output verbosity (default::none
):none
- Only show pipeline summary on failures (prevents context overflow) [Recommended]:full
- Show complete hook output plus pipeline summary (use sparingly - can cause context issues)
Hook Event Reporting (Experimental)
Claude supports sending hook events to external systems for monitoring and integration.
Webhook Reporter
Note: This feature is experimental and the API may change in future releases.
Send hook events to HTTP endpoints:
%{
reporters: [
{:webhook,
url: "https://example.com/webhook",
headers: %{"Authorization" => "Bearer token"},
timeout: 5000,
retry_count: 3
}
]
}
The webhook reporter sends the raw Claude Code hook event data as JSON, including:
- Event type and timestamp
- Tool information (for tool-related events)
- Session and project context
How It Works
- Configuration: Define hooks in
.claude.exs
using atoms, strings, or tuples with options - Installation:
mix claude.install
creates.claude/settings.json
with a dispatcher command - Execution: Claude Code runs
mix claude.hooks.run <event>
passing JSON via stdin - Expansion: The dispatcher reads
.claude.exs
and expands atoms to full commands - Running: Commands execute as Mix tasks (default) or shell commands (with "cmd " prefix)
- Communication: Hooks return exit codes only (0 = success, non-zero = failure, no JSON output)
- Reporting: Events are dispatched to configured reporters for external integration
Request a New Hook
Have an idea for a new standardized hook that would be useful for Elixir development? We'd love to hear from you!
Popular requests might be added as default hooks in future releases!
Troubleshooting
Hooks not running?
- Check
.claude/settings.json
exists and contains hook configuration - Verify
.claude.exs
has the correct hook definitions - Run
mix claude.install
to regenerate hook configuration - Use Claude Code's
/hooks
command to verify hooks are registered
Compilation/format errors not showing?
- Ensure hooks are defined for the right events (
post_tool_use
,stop
, etc.) - Check that the
:compile
and:format
atoms are included - Verify Mix is available in your PATH
Need help?
Learn More
For more details on hook events, configuration, and advanced usage, see the official documentation.