Skip to content

Hooks Guide ​

Learn how to customize and extend CodeBuddy Code's behavior by registering shell commands

Table of Contents ​

We recommend reading the Hook Reference Guide first to understand all events, input/output structures, and security requirements. This guide focuses on practical walkthroughs and common examples to help you quickly enable Hooks functionality in your CodeBuddy Code projects. Note: The Hooks feature is currently in Beta and is being actively refined. Please watch for updates in future releases.


CodeBuddy Code hooks are user-defined shell commands that execute at different stages of the CodeBuddy Code lifecycle. Hooks provide deterministic control over CodeBuddy Code's behavior, ensuring specific actions always occur rather than relying on the LLM to choose to execute them.

For reference documentation on hooks, see the Hook Reference Guide.

Example use cases for hooks include:

  • Notifications: Customize how CodeBuddy Code notifies you when waiting for your input or permission.
  • Auto-formatting: Run prettier on .ts files, gofmt on .go files, etc., after every file edit.
  • Logging: Track and record all executed commands for compliance or debugging purposes.
  • Feedback: Provide automatic feedback when CodeBuddy Code-generated code doesn't conform to your codebase standards.
  • Custom permissions: Block modifications to production files or sensitive directories.

By encoding these rules as hooks rather than prompt instructions, you transform suggestions into application-level code that executes as expected every time.

⚠️ Security Warning: You must consider security implications when adding hooks, as hooks run automatically during the agent loop using your current environment's credentials. For example, malicious hook code could leak your data. Always review hook implementations before registering them. For complete security best practices, see Security Considerations in the Hook Reference Guide.

Hook Events Overview ​

CodeBuddy Code provides multiple hook events that run at different stages of the workflow:

Event NameDescription
PreToolUseRuns before tool calls (can block them)
PostToolUseRuns after tool calls complete
UserPromptSubmitRuns after user submits a prompt, before CodeBuddy processes it
NotificationRuns when CodeBuddy Code sends a notification
StopRuns when CodeBuddy Code finishes responding
SubagentStopRuns when a sub-agent task completes
PreCompactRuns before CodeBuddy Code is about to run a compaction operation
SessionStartRuns when CodeBuddy Code starts a new session or resumes an existing one
SessionEndRuns when a CodeBuddy Code session ends

Each event receives different data and can control CodeBuddy's behavior in different ways.

Quick Start ​

In this quick start, you'll add a hook to log shell commands run by CodeBuddy Code.

Prerequisites ​

Install jq for processing JSON on the command line.

Step 1: Open hooks configuration ​

Run the /hooks slash command and select the PreToolUse hook event. PreToolUse hooks run before tool calls and can block them while providing feedback to CodeBuddy on how to do things differently.

Step 2: Add a matcher ​

Select + Add new matcher… to run your hook only on Bash tool calls. Enter Bash for the matcher.

You can use * to match all tools.

Step 3: Add the hook ​

Select + Add new hook… and enter this command:

bash
jq -r '"\(.tool_input.command) ~ \(.tool_input.description // "No description")"' >> ~/.codebuddy/bash-command.log

Step 4: Save configuration ​

For the storage location, select User settings since you're logging to the home directory. This way the hook will apply to all projects, not just the current one. Then press Esc until you return to the REPL. Your hook is now registered!

Step 5: Verify the hook ​

Run /hooks again or check ~/.codebuddy/settings.json to view your configuration:

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '\"\\(.tool_input.command) ~ \\(.tool_input.description // \"No description\")\"' >> ~/.codebuddy/bash-command.log"
          }
        ]
      }
    ]
  }
}

Step 6: Test the hook ​

Have CodeBuddy run a simple command like ls, then check your log file:

bash
cat ~/.codebuddy/bash-command.log

You should see an entry similar to:

ls ~ Lists files and directories

More Examples ​

Code Formatting Hook ​

Automatically format TypeScript files after editing:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | { read file_path; if echo \"$file_path\" | grep -q '\\.ts$'; then npx prettier --write \"$file_path\"; fi; }"
          }
        ]
      }
    ]
  }
}

Ensure the prettier dependency is available in your project.

Markdown Formatting Hook ​

Automatically fix missing language tags and formatting issues in markdown files:

json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CODEBUDDY_PROJECT_DIR\"/.codebuddy/hooks/markdown_formatter.py"
          }
        ]
      }
    ]
  }
}

Create a .codebuddy/hooks/markdown_formatter.py file with the following content:

python
#!/usr/bin/env python3
"""
Markdown formatter for CodeBuddy Code output.
Fixes missing language tags and spacing issues while preserving code content.
"""
import json
import sys
import re
import os

def detect_language(code):
    """Best-effort language detection from code content."""
    s = code.strip()

    # JSON detection
    if re.search(r'^\s*[{\[]', s):
        try:
            json.loads(s)
            return 'json'
        except:
            pass

    # Python detection
    if re.search(r'^\s*def\s+\w+\s*\(', s, re.M) or \
       re.search(r'^\s*(import|from)\s+\w+', s, re.M):
        return 'python'

    # JavaScript detection
    if re.search(r'\b(function\s+\w+\s*\(|const\s+\w+\s*=)', s) or \
       re.search(r'=>|console\.(log|error)', s):
        return 'javascript'

    # Bash detection
    if re.search(r'^#!.*\b(bash|sh)\b', s, re.M) or \
       re.search(r'\b(if|then|fi|for|in|do|done)\b', s):
        return 'bash'

    # SQL detection
    if re.search(r'\b(SELECT|INSERT|UPDATE|DELETE|CREATE)\s+', s, re.I):
        return 'sql'

    return 'text'

def format_markdown(content):
    """Format markdown content using language detection."""
    # Fix unmarked code blocks
    def add_lang_to_fence(match):
        indent, info, body, closing = match.groups()
        if not info.strip():
            lang = detect_language(body)
            return f"{indent}```{lang}\n{body}{closing}\n"
        return match.group(0)

    fence_pattern = r'(?ms)^([ \t]{0,3})```([^\n]*)\n(.*?)(\n\1```)\s*$'
    content = re.sub(fence_pattern, add_lang_to_fence, content)

    # Fix excessive blank lines (only outside code blocks)
    content = re.sub(r'\n{3,}', '\n\n', content)

    return content.rstrip() + '\n'

# Main execution
try:
    input_data = json.load(sys.stdin)
    file_path = input_data.get('tool_input', {}).get('file_path', '')

    if not file_path.endswith(('.md', '.mdx')):
        sys.exit(0)  # Not a markdown file

    if os.path.exists(file_path):
        with open(file_path, 'r', encoding='utf-8') as f:
            content = f.read()

        formatted = format_markdown(content)

        if formatted != content:
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(formatted)
            print(f"βœ“ Fixed markdown formatting in {file_path}")

except Exception as e:
    print(f"Error formatting markdown: {e}", file=sys.stderr)
    sys.exit(1)

Make the script executable:

bash
chmod +x .codebuddy/hooks/markdown_formatter.py

This hook will automatically:

  • Detect programming languages in unmarked code blocks
  • Add appropriate language tags for syntax highlighting
  • Fix excessive blank lines while preserving code content
  • Only process markdown files (.md, .mdx)

Custom Notification Hook ​

Get desktop notifications when CodeBuddy needs input:

json
{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "notify-send 'CodeBuddy Code' 'Awaiting your input'"
          }
        ]
      }
    ]
  }
}

Windows/macOS need to replace with notification commands for powershell or osascript.

File Protection Hook ​

Block edits to sensitive files:

json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "python3 -c \"import json, sys; data=json.load(sys.stdin); path=data.get('tool_input',{}).get('file_path',''); sys.exit(2 if any(p in path for p in ['.env', 'package-lock.json', '.git/']) else 0)\""
          }
        ]
      }
    ]
  }
}

Best Practices and Recommendations ​

  1. Validate incrementally: Start with logging hooks before gradually adding high-risk operations.
  2. Control timeouts: Default is 60 seconds; if your script has long-running tasks, ensure timely output or split processing.
  3. Use matcher filtering: Properly setting matcher can reduce unnecessary hook executions.
  4. Centralize script directory: Recommend creating a .codebuddy/hooks/ directory in the project root to centrally manage scripts and include them in version control.
  5. Prioritize security:
    • Avoid using unvalidated user input directly in hooks.
    • Use absolute paths for external commands to prevent PATH hijacking.
    • Combine with the /hooks panel's security confirmation mechanism to ensure all hooks are reviewed before running.
  6. Work with MCP tools: MCP tool names follow the pattern mcp__<server>__<tool> and can be batch-controlled in matcher using regex, e.g., mcp__github__.*.
  7. The panel is the authoritative entry point: Any external file modifications need to be confirmed in the panel before taking effect; be sure to complete this step.

Learn More ​

  • For reference documentation on hooks, see the Hook Reference Guide.
  • For comprehensive security best practices and safety guidelines, see Security Considerations in the Hook Reference Guide.
  • For troubleshooting steps and debugging techniques, see the Debugging section in the Hook Reference Guide.

Now you've mastered the core workflow for enabling hooks in CodeBuddy Code. For more details on event fields, decision control, and security considerations, check out the Hook Reference Guide. Happy building powerful and secure automated workflows!