mirror of
https://github.com/imjasonh/cnotes
synced 2026-07-17 22:33:31 +00:00
- Add missing hook handlers: Stop, SubagentStop, PreCompact
- Replace all string type casting with proper JSON unmarshaling
- Change ToolUseRequest.Parameters from map[string]interface{} to json.RawMessage
- Update helper methods to use json.Unmarshal directly to typed structs
- Replace speech notifications with simple logging notifications
- Update documentation to reflect all hook events and remove speech references
- Add comprehensive CLAUDE.md with architecture overview and development guidance
All hooks now use type-safe JSON handling without .(string) assertions.
Complete coverage of Claude Code events: PreToolUse, PostToolUse,
UserPromptSubmit, Notification, Stop, SubagentStop, PreCompact.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
189 lines
No EOL
4.7 KiB
Markdown
189 lines
No EOL
4.7 KiB
Markdown
# Claude Code Hooks
|
|
|
|
A Go binary that handles Claude Code hooks for validating and modifying tool usage. This tool makes it easy to write custom hooks as simple Go functions.
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
go build -o hooks
|
|
./hooks install
|
|
```
|
|
|
|
This will configure your `~/.claude/settings.json` to use this binary for all hook events.
|
|
|
|
## Usage
|
|
|
|
### Writing Custom Hooks
|
|
|
|
Hooks are simple Go functions that follow this signature:
|
|
|
|
```go
|
|
func MyHook(ctx context.Context, input hooks.HookInput) (hooks.HookOutput, error) {
|
|
// Your logic here
|
|
return hooks.HookOutput{Decision: "continue"}, nil
|
|
}
|
|
```
|
|
|
|
Register your hook in an init function:
|
|
|
|
```go
|
|
func init() {
|
|
// Register for specific tools
|
|
hooks.RegisterHook(hooks.EventPreToolUse, "Bash", ValidateBashCommand)
|
|
|
|
// Use regex patterns
|
|
hooks.RegisterHook(hooks.EventPreToolUse, "Write|Edit", PreventSensitiveEdits)
|
|
|
|
// Match all tools
|
|
hooks.RegisterHook(hooks.EventPostToolUse, "*", LogEverything)
|
|
}
|
|
```
|
|
|
|
### Example: Block Dangerous Commands
|
|
|
|
```go
|
|
func BlockRmRf(ctx context.Context, input hooks.HookInput) (hooks.HookOutput, error) {
|
|
bashInput, err := input.GetBashInput()
|
|
if err != nil {
|
|
return hooks.HookOutput{Decision: "approve"}, nil
|
|
}
|
|
|
|
if strings.Contains(bashInput.Command, "rm -rf /") {
|
|
return hooks.HookOutput{
|
|
Decision: "block",
|
|
Reason: "Cannot execute rm -rf on root directory",
|
|
}, nil
|
|
}
|
|
return hooks.HookOutput{Decision: "approve"}, nil
|
|
}
|
|
```
|
|
|
|
### Example: Add Context to Prompts
|
|
|
|
```go
|
|
func AddGitInfo(ctx context.Context, input hooks.HookInput) (hooks.HookOutput, error) {
|
|
branch := getCurrentGitBranch()
|
|
return hooks.HookOutput{
|
|
Decision: "continue",
|
|
AdditionalContext: fmt.Sprintf("Current git branch: %s", branch),
|
|
}, nil
|
|
}
|
|
```
|
|
|
|
### Example: Modify Tool Parameters
|
|
|
|
```go
|
|
func ForceNonInteractiveSudo(ctx context.Context, input hooks.HookInput) (hooks.HookOutput, error) {
|
|
bashInput, err := input.GetBashInput()
|
|
if err != nil {
|
|
return hooks.HookOutput{Decision: "approve"}, nil
|
|
}
|
|
|
|
if strings.Contains(bashInput.Command, "sudo") && !strings.Contains(bashInput.Command, "sudo -n") {
|
|
return hooks.HookOutput{
|
|
Decision: "approve",
|
|
ModifiedParameters: map[string]interface{}{
|
|
"command": strings.ReplaceAll(bashInput.Command, "sudo", "sudo -n"),
|
|
},
|
|
}, nil
|
|
}
|
|
return hooks.HookOutput{Decision: "approve"}, nil
|
|
}
|
|
```
|
|
|
|
## Built-in Hooks
|
|
|
|
This package includes comprehensive hook implementations for all Claude Code events:
|
|
|
|
### Pre Tool Use
|
|
- **Bash Command Validator**: Blocks dangerous commands using regex patterns
|
|
- **Sensitive File Protection**: Prevents editing `.env`, `.aws/credentials`, etc.
|
|
|
|
### Post Tool Use
|
|
- **Tool Usage Logger**: Logs all tool executions with structured logging
|
|
- **Go Imports**: Automatically runs `goimports -w` on modified Go files
|
|
|
|
### User Prompt Submit
|
|
- **Project Context**: Adds git branch and project type information
|
|
|
|
### Notification
|
|
- **System Notifications**: Logs notification events for debugging and monitoring
|
|
|
|
### Stop
|
|
- **Session Completion**: Logs when main Claude agent finishes responding
|
|
|
|
### SubagentStop
|
|
- **Subagent Completion**: Logs when Task tool subagents finish responding
|
|
|
|
### PreCompact
|
|
- **Context Compaction**: Handles before context window compaction (manual/auto)
|
|
|
|
## Testing Hooks
|
|
|
|
Test individual hooks by piping JSON:
|
|
|
|
```bash
|
|
echo '{
|
|
"event": "pre_tool_use",
|
|
"tool": "Bash",
|
|
"tool_use_request": {
|
|
"tool": "Bash",
|
|
"parameters": {
|
|
"command": "rm -rf /"
|
|
}
|
|
}
|
|
}' | ./hooks run
|
|
```
|
|
|
|
Enable debug logging:
|
|
|
|
```bash
|
|
./hooks run --debug
|
|
```
|
|
|
|
## Hook Events
|
|
|
|
- `pre_tool_use`: Before any tool execution
|
|
- `post_tool_use`: After successful tool execution
|
|
- `user_prompt_submit`: Before processing user prompts
|
|
- `stop`: When main agent finishes
|
|
- `subagent_stop`: When subagent finishes
|
|
- `notification`: For permission requests
|
|
- `pre_compact`: Before context compaction
|
|
|
|
## Configuration
|
|
|
|
Hooks are configured in `~/.claude/settings.json`:
|
|
|
|
```json
|
|
{
|
|
"hooks": [
|
|
{
|
|
"events": ["pre_tool_use", "post_tool_use"],
|
|
"matchers": [".*"],
|
|
"cmds": ["/path/to/hooks run"]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Security Warning
|
|
|
|
⚠️ **USE AT YOUR OWN RISK**: Hooks execute automatically when Claude Code runs tools. Ensure your hooks are thoroughly tested and secure.
|
|
|
|
## Development
|
|
|
|
To add new hooks:
|
|
|
|
1. Create a new file in `internal/handlers/`
|
|
2. Write your hook function
|
|
3. Register it in an `init()` function
|
|
4. Rebuild and reinstall: `go build && ./hooks install`
|
|
|
|
## Uninstalling
|
|
|
|
```bash
|
|
./hooks install --uninstall
|
|
```
|
|
|
|
This removes all hook configurations from your Claude settings. |