1
0
Fork 0
mirror of https://github.com/imjasonh/cnotes synced 2026-07-08 17:16:00 +00:00
No description
Find a file
Jason Hall 9c661683cb
Add git notes functionality for conversation logging
- Implement PostToolUse hook to detect git commit commands
- Add git notes operations package with structured conversation data
- Add conversation context extraction from transcripts
- Include privacy controls and configuration options
- Support custom git notes references for organization

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 12:15:55 -04:00
.claude Complete hooks implementation with comprehensive features 2025-07-21 11:27:18 -04:00
cmd Scaffold all 7 hook events and eliminate type casting 2025-07-21 12:01:55 -04:00
internal Scaffold all 7 hook events and eliminate type casting 2025-07-21 12:01:55 -04:00
.gitignore Initial implementation of Claude Code hooks in Go 2025-07-21 11:27:08 -04:00
CLAUDE.md Scaffold all 7 hook events and eliminate type casting 2025-07-21 12:01:55 -04:00
go.mod Switch to terminal-notifier for visual notifications 2025-07-21 11:27:15 -04:00
go.sum Initial implementation of Claude Code hooks in Go 2025-07-21 11:27:08 -04:00
LICENSE Initial commit 2025-07-21 11:26:10 -04:00
main.go Initial implementation of Claude Code hooks in Go 2025-07-21 11:27:08 -04:00
README.md Scaffold all 7 hook events and eliminate type casting 2025-07-21 12:01:55 -04:00
test_commit_message.txt Add git notes functionality for conversation logging 2025-07-21 12:15:55 -04:00

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

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:

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:

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

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

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

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:

echo '{
  "event": "pre_tool_use",
  "tool": "Bash",
  "tool_use_request": {
    "tool": "Bash",
    "parameters": {
      "command": "rm -rf /"
    }
  }
}' | ./hooks run

Enable debug logging:

./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:

{
  "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

./hooks install --uninstall

This removes all hook configurations from your Claude settings.