tencent cloud

Tencent Cloud CodeBuddy

Release Notes and Announcements
Release Notes
Product Introduction
Overview
Product Strengths
Billing
Billing Overview
Price details
Billable Items
Refund/Invoice/Bill Description
Getting Started
Installation and Login
Open or Create a Project
User Guide
Overview
Code Completion
Inline Chat
CodeBuddy Built-in Slash Commands
Context
Rules
Checkpoint
History
Memory
Config MCP
Integration
Preview
Deployment
Smart Commit
Advanced Features
FAQ
Security and Privacy Guide
CodeBuddy Policy
Privacy Policy
Data Privacy And Security Agreement
Contact Us

Hook User Guide-Hook

PDF
Modo Foco
Tamanho da Fonte
Última atualização: 2026-03-02 15:47:14

Table of Contents

Overview
Features
FAQ
Appendix

Overview

The Hook feature allows you to insert custom scripts at critical points during AI Agent execution, enabling fine-grained control over Agent behavior. The Hook mechanism is fully compatible with the Claude Code Hooks specification, providing a powerful and flexible extension method.

Features

Multiple Event Support: Supports 7 key events (SessionStart, SessionEnd, PreToolUse, PostToolUse, UserPromptSubmit, Stop, PreCompact)
Tool Interception: Validate, modify, or block before and after tool execution
Context Injection: Dynamically inject additional context at different session stages
Parallel Execution: Multiple Hooks execute automatically in parallel for improved performance
Automatic Deduplication: Identical commands are automatically deduplicated to avoid repeated execution
Flexible Configuration: Supports regex matching, timeout control, project-level/user-level configuration
Session Tracking: Intelligently detects session changes to avoid duplicate SessionStart triggers
Safe and Reliable: Complete error handling and timeout mechanisms

Supported Hook Events

1. SessionStart - Session Startup

Trigger Timing: When a session starts (triggers only once per new session)
Trigger Logic:
The system determines if it's a new session by comparing conversationId
Multiple requests within the same session will not trigger repeatedly
Switching to a new session or clearing a session will trigger again
Use Cases:
Initialize project environment
Inject project-specific context
Set session-level configurations
Load project specifications and documentation
Matcher Field: source
startup - Initial startup (currently only this value is supported)
Input Data (stdin JSON)
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.txt",
"cwd": "/project/path",
"hook_event_name": "SessionStart",
"source": "startup"
}
Output Data (stdout JSON):
{
"continue": true,
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "Project uses TypeScript + React, prefer functional components"
}
}
Example Configuration:
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "/path/to/session_start.py",
"timeout": 30
}
]
}
]
}
}

2. SessionEnd - Session End

Trigger Timing: When a session terminates
Use Cases:
Clean up temporary resources
Save session state
Generate session reports
Matcher Field: reason
other - Session end (currently only this value is supported, including scenarios like switching sessions, deleting sessions, clearing sessions, etc.)
Input Data:
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.txt",
"cwd": "/project/path",
"hook_event_name": "SessionEnd",
"reason": "other"
}
Output Data:
{
"continue": true,
"systemMessage": "Session cleaned up, temporary files deleted"
}

3. PreToolUse - Before Tool Execution

Trigger Timing: Before any tool executes
Use Cases:
Validate tool parameters
Modify tool input
Block dangerous operations
Permission checks
Record audit logs
Matcher Field: tool_name
Examples: execute_command, write_to_file, read_file
Supports regex: write_to_file|replace_in_file
Match all: * or empty string
Input Data:
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.txt",
"cwd": "/project/path",
"hook_event_name": "PreToolUse",
"tool_name": "execute_command",
"tool_input": {
"command": "npm install",
"requires_approval": false
}
}
Output Data - Allow Execution:
{
"continue": true,
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow"
}
}
Output Data - Modify Parameters:
{
"continue": true,
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"permissionDecisionReason": "Added --legacy-peer-deps parameter",
"modifiedInput": {
"command": "npm install --legacy-peer-deps",
"requires_approval": false
}
}
}
Output Data - Block Execution:
{
"continue": false,
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Dangerous command detected: rm -rf /"
}
}
Output Data - Request User Confirmation:
{
"continue": true,
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "ask",
"permissionDecisionReason": "Detected git push --force, do you want to continue?"
}
}

4. PostToolUse - After Tool Execution

Trigger Timing: After a tool completes execution
Use Cases:
Record tool execution logs
Post-process tool output
Trigger follow-up actions
Send notifications
Matcher Field: tool_name
Input Data:
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.txt",
"cwd": "/project/path",
"hook_event_name": "PostToolUse",
"tool_name": "execute_command",
"tool_input": {
"command": "npm test"
},
"tool_response": {
"exitCode": 0,
"stdout": "All tests passed",
"stderr": ""
}
}
Output Data:
{
"continue": true,
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "Tests passed, you can continue development"
}
}

5. UserPromptSubmit - User Input Submission

Trigger Timing: When user submits a message
Use Cases:
Pre-process user input
Add contextual information
Detect specific keywords
Input validation
Matcher: Not used (triggers for all submissions)
Input Data:
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.txt",
"cwd": "/project/path",
"hook_event_name": "UserPromptSubmit",
"prompt": "Help me implement a login feature"
}
Output Data:
{
"continue": true,
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "Tip: The project has integrated JWT authentication library, recommend using it"
}
}
Block Input:
{
"continue": false,
"stopReason": "Input contains sensitive information, blocked"
}

6. Stop - Agent Stops Responding

Trigger Timing: When Agent completes its response
Use Cases:
Provide feedback to Agent
Record execution status
Trigger follow-up tasks
Matcher: Not used
Input Data:
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.txt",
"cwd": "/project/path",
"hook_event_name": "Stop",
"stop_hook_active": false
}
Output Data - Provide Feedback (exit code 2):
{
"continue": false,
"stopReason": "Please verify if the code passed unit tests"
}

7. PreCompact - Before Context Compaction

Trigger Timing: When context is about to be compacted
Use Cases:
Save important information
Provide compaction guidance
Backup complete context
Matcher Field: trigger
manual - User manually triggers /summarize
auto - Automatic compaction
Input Data:
{
"session_id": "abc123",
"transcript_path": "/path/to/transcript.txt",
"cwd": "/project/path",
"hook_event_name": "PreCompact",
"trigger": "auto",
"custom_instructions": "Preserve all API design discussions"
}
Output Data (exit code 0):
{
"continue": true,
"hookSpecificOutput": {
"hookEventName": "PreCompact",
"additionalContext": "Important: Preserve database table structure design"
}
}
Note:
When exit code is 0, stdout content will be added as additional compaction guidance

Hook Script Specifications

Input Format

Hook scripts receive JSON-formatted input data via stdin.
Common Fields:
{
"session_id": "Session ID",
"transcript_path": "Path to conversation transcript file",
"cwd": "Current working directory",
"hook_event_name": "Event name"
}
Event-Specific Fields:
SessionStart: source
SessionEnd: reason
PreToolUse/PostToolUse: tool_name, tool_input, tool_response
UserPromptSubmit: prompt
PreCompact: trigger, custom_instructions
Stop: stop_hook_active

Output Format

Hook scripts return JSON-formatted output via stdout.
Basic Structure:
{
"continue": true,
"suppressOutput": false,
"systemMessage": "Optional system message",
"stopReason": "Reason for blocking (when continue=false)",
"hookSpecificOutput": {
"hookEventName": "Event name",
"permissionDecision": "allow|deny|ask",
"permissionDecisionReason": "Decision reason",
"modifiedInput": {},
"additionalContext": "Additional context"
}
}
Field Descriptions:
continue: Whether to allow the operation to continue (false means block)
suppressOutput: Whether to hide stdout output
systemMessage: System message displayed to the user
stopReason: Reason for blocking
hookSpecificOutput: Event-specific output data

Exit Code Specifications

Exit Code
Meaning
Behavior
0
Success
Allow operation to continue, stdout may be processed
1
Non-blocking error
Display stderr as warning, allow to continue
2
Blocking error
Block operation, stderr passed to Agent/model
Other
Non-blocking error
Same as exit code 1
Special Rules:
PreToolUse: Exit code 2 blocks tool execution
Stop: Exit code 2 indicates feedback, stderr is injected into the next message
PreCompact: When exit code is 0, stdout serves as additional compaction guidance

Environment Variables

Hook scripts have access to the following environment variables during execution:

CLAUDE_PROJECT_DIR: Project root directory (Claude Code compatible)
CODEBUDDY_PROJECT_DIR: Project root directory (CodeBuddy specific)

Configuration Guide

Configuration File Locations

Priority (high to low):

1. Project-level: <workspace>/.codebuddy/settings.json
2. User-level: ~/.codebuddy/settings.json

Project-level configuration overrides user-level configuration.


Configuration File Structure

{
"hooks": {
"PreToolUse": [
{
"matcher": "execute_command",
"hooks": [
{
"type": "command",
"command": "/absolute/path/to/script.py",
"timeout": 10
}
]
},
{
"matcher": "write_to_file|replace_in_file",
"hooks": [
{
"type": "command",
"command": "/path/to/backup_script.sh",
"timeout": 20
}
]
}
],
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "/path/to/init.py",
"timeout": 30
}
]
}
]
}
}

Configuration Field Descriptions

matcher (Matcher)

Regular expression used to match specific conditions.
Syntax:
Empty string "" or "*": Match all
Single value: "execute_command"
Multiple values: "write_to_file|replace_in_file"
Regular expression: "read.*|search.*"
Match Targets for Different Events:
PreToolUse/PostToolUse: Matches tool_name
SessionStart: Matches source
SessionEnd: Matches reason
PreCompact: Matches trigger
UserPromptSubmit/Stop: Matcher not used

command (Command Path)

Path to the Hook script.
Requirements:
Absolute paths are recommended
Supports environment variables: "$CODEBUDDY_PROJECT_DIR/.codebuddy/hooks/script.py"
Can include interpreter: "python3 /path/to/script.py"
Ensure the script has execution permissions

timeout (Timeout)

Hook execution timeout, unit: seconds.
Default value: 60 seconds
Recommended settings: Adjust based on script complexity
Simple validation: 5-10 seconds
File operations: 15-30 seconds
Network requests: 30-60 seconds

Complete Examples

Example 1: Command Security Validation

Scenario: Block dangerous rm -rf commands
Hook Script (validate_command.py):
#!/usr/bin/env python3
import json
import sys

DANGEROUS_COMMANDS = ['rm -rf /', 'dd if=/dev/zero', 'mkfs']

def main():
input_data = json.loads(sys.stdin.read())

if input_data.get('tool_name') != 'execute_command':
print(json.dumps({"continue": True}))
return 0

command = input_data.get('tool_input', {}).get('command', '')

for dangerous in DANGEROUS_COMMANDS:
if dangerous in command:
output = {
"continue": False,
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": f"Dangerous command detected: {dangerous}"
}
}
print(json.dumps(output, ensure_ascii=False))
return 0

print(json.dumps({"continue": True}))
return 0

if __name__ == "__main__":
sys.exit(main())
Configuration:
{
"hooks": {
"PreToolUse": [
{
"matcher": "execute_command",
"hooks": [
{
"type": "command",
"command": "/path/to/validate_command.py",
"timeout": 10
}
]
}
]
}
}

Example 2: Smart Command Parameter Modification

Scenario: Automatically add --legacy-peer-deps parameter to npm install

Hook Script (modify_npm.py):
#!/usr/bin/env python3
import json
import sys
import re

def main():
input_data = json.loads(sys.stdin.read())

if input_data.get('tool_name') != 'execute_command':
print(json.dumps({"continue": True}))
return 0

tool_input = input_data.get('tool_input', {})
command = tool_input.get('command', '')

# Check if it's npm install
if re.match(r'^npm\\s+(i|install)\\b', command.strip()):
# If --legacy-peer-deps is not present, add it
if '--legacy-peer-deps' not in command:
modified_command = command.strip() + ' --legacy-peer-deps'

output = {
"continue": True,
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"permissionDecisionReason": "Automatically added --legacy-peer-deps parameter",
"modifiedInput": {
"command": modified_command,
"requires_approval": tool_input.get('requires_approval', False)
}
}
}
print(json.dumps(output, ensure_ascii=False))
return 0

print(json.dumps({"continue": True}))
return 0

if __name__ == "__main__":
sys.exit(main())

Example 3: Automatic File Backup Before Modification

Scenario: Automatically create backups before modifying files

Hook Script (backup_files.py):
#!/usr/bin/env python3
import json
import sys
import os
import shutil
from datetime import datetime

def main():
input_data = json.loads(sys.stdin.read())
tool_name = input_data.get('tool_name', '')

# Only process file write tools
if tool_name not in ['write_to_file', 'replace_in_file']:
print(json.dumps({"continue": True}))
return 0

tool_input = input_data.get('tool_input', {})
file_path = tool_input.get('filePath')

if not file_path or not os.path.exists(file_path):
print(json.dumps({"continue": True}))
return 0

# Create backup directory
project_dir = os.environ.get('CODEBUDDY_PROJECT_DIR', '')
backup_dir = os.path.join(project_dir, '.codebuddy', 'backups')
os.makedirs(backup_dir, exist_ok=True)

# Generate backup filename
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
backup_name = f"{os.path.basename(file_path)}.{timestamp}.bak"
backup_path = os.path.join(backup_dir, backup_name)

# Create backup
shutil.copy2(file_path, backup_path)

output = {
"continue": True,
"systemMessage": f"Backed up to: {backup_path}"
}
print(json.dumps(output, ensure_ascii=False))
return 0

if __name__ == "__main__":
sys.exit(main())
Configuration:
{
"hooks": {
"PreToolUse": [
{
"matcher": "write_to_file|replace_in_file",
"hooks": [
{
"type": "command",
"command": "/path/to/backup_files.py",
"timeout": 15
}
]
}
]
}
}

Example 4: Inject Project Context at Session Startup

Scenario: Automatically inject project configuration information when a session starts

Hook Script (session_start.py):
#!/usr/bin/env python3
import json
import sys
import os

def main():
input_data = json.loads(sys.stdin.read())
project_dir = os.environ.get('CODEBUDDY_PROJECT_DIR', '')

# Read project configuration
config_file = os.path.join(project_dir, '.codebuddy', 'project.json')
project_info = ""

if os.path.exists(config_file):
with open(config_file, 'r') as f:
config = json.load(f)
project_info = f"""
Project Name: {config.get('name', 'Unknown')}
Tech Stack: {', '.join(config.get('tech_stack', []))}
Coding Standard: {config.get('coding_standard', 'Standard')}
"""

output = {
"continue": True,
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": f"""
Session started!
Project Directory: {project_dir}
Startup Source: {input_data.get('source', 'unknown')}
{project_info}
"""
}
}

print(json.dumps(output, ensure_ascii=False))
return 0

if __name__ == "__main__":
sys.exit(main())

Example 5: Save Important Information Before Context Compaction

Scenario: Save complete conversation history before automatic compaction

Hook Script (save_context.py):
#!/usr/bin/env python3
import json
import sys
import os
import shutil
from datetime import datetime

def main():
input_data = json.loads(sys.stdin.read())

# Only process automatic compaction
if input_data.get('trigger') != 'auto':
print(json.dumps({"continue": True}))
return 0

project_dir = os.environ.get('CODEBUDDY_PROJECT_DIR', '')
transcript_path = input_data.get('transcript_path', '')

if not transcript_path or not os.path.exists(transcript_path):
print(json.dumps({"continue": True}))
return 0

# Create save directory
save_dir = os.path.join(project_dir, '.codebuddy', 'context_history')
os.makedirs(save_dir, exist_ok=True)

# Save conversation history
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
save_path = os.path.join(save_dir, f'transcript_{timestamp}.txt')
shutil.copy2(transcript_path, save_path)

output = {
"continue": True,
"systemMessage": f"Context saved to: {save_path}"
}
print(json.dumps(output, ensure_ascii=False))
return 0

if __name__ == "__main__":
sys.exit(main())

Configuration:

{
"hooks": {
"PreCompact": [
{
"matcher": "auto",
"hooks": [
{
"type": "command",
"command": "/path/to/save_context.py",
"timeout": 20
}
]
}
]
}
}

Practical Guide

Quick Start - Configure Your First Hook in 5 Minutes

Step 1: Create Configuration File
mkdir -p ~/.codebuddy
cat > ~/.codebuddy/settings.json << 'EOF'
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "/usr/bin/env python3 -c \\"import json,sys; print(json.dumps({'continue': True, 'hookSpecificOutput': {'hookEventName': 'SessionStart', 'additionalContext': 'Hook configured successfully!'}}))\\"",
"timeout": 5
}
]
}
]
}
}
EOF
Step 2: Restart Agent
Start a new session. If you see "Hook configured successfully!" the configuration is working.
Step 3: Create Your First Real Hook
# Create Hook script directory
mkdir -p ~/.codebuddy/hooks

# Create test script
cat > ~/.codebuddy/hooks/my_first_hook.py << 'EOF'
#!/usr/bin/env python3
import json
import sys

def main():
input_data = json.loads(sys.stdin.read())

output = {
"continue": True,
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": f"Welcome to Agent-Craft! Current project: {input_data.get('cwd', 'unknown')}"
}
}

print(json.dumps(output, ensure_ascii=False))
return 0

if __name__ == "__main__":
sys.exit(main())
EOF

# Add execution permission
chmod +x ~/.codebuddy/hooks/my_first_hook.py
Step 4: Update Configuration File
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "/Users/YOUR_USERNAME/.codebuddy/hooks/my_first_hook.py",
"timeout": 10
}
]
}
]
}
}

Advanced Debugging Tips

Tip 1: Use Log Files for Debugging
import sys

def debug_log(message):
"""Write to debug log without affecting stdout"""
with open('/tmp/hook_debug.log', 'a') as f:
f.write(f"{message}\\n")

# Use in Hook script
debug_log(f"Received input: {json.dumps(input_data)}")
Tip 2: Validate JSON Output Format
# Test if script output JSON is valid
echo '{"hook_event_name":"SessionStart"}' | python3 your_hook.py | jq .
Tip 3: Monitor Hook Execution
# Watch Hook logs in real-time
tail -f ~/.codebuddy/logs/agent-craft.log | grep -i hook
Tip 4: Use Environment Variables to Pass Information
import os

# Get project directory in Hook
project_dir = os.environ.get('CODEBUDDY_PROJECT_DIR', '')
claude_dir = os.environ.get('CLAUDE_PROJECT_DIR', '') # Claude Code compatible

Common Hook Patterns

Pattern 1: Whitelist Validation
ALLOWED_COMMANDS = [
'npm install',
'npm test',
'git status',
'git diff'
]

def is_allowed(command):
return any(command.startswith(allowed) for allowed in ALLOWED_COMMANDS)
Pattern 2: Parameter Enhancement
def enhance_command(command):
"""Automatically add common parameters"""
enhancements = {
'npm install': ' --legacy-peer-deps',
'git push': ' --dry-run', # Safe mode
}

for prefix, suffix in enhancements.items():
if command.startswith(prefix) and suffix not in command:
return command + suffix

return command
Pattern 3: Conditional Routing
def should_block(input_data):
"""Determine whether to block based on multiple conditions"""
tool_name = input_data.get('tool_name')
tool_input = input_data.get('tool_input', {})

# Rule 1: Block deletion of important files
if tool_name == 'delete_files':
file_path = tool_input.get('target_file', '')
if any(important in file_path for important in ['.git', 'package.json']):
return True, "Cannot delete important files"

# Rule 2: Block dangerous commands
if tool_name == 'execute_command':
command = tool_input.get('command', '')
if 'rm -rf /' in command or 'dd if=' in command:
return True, "Dangerous command detected"

return False, None

Recommended Project Templates

Node.js Project Hook Configuration
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "node ~/.codebuddy/hooks/nodejs-init.js",
"timeout": 15
}
]
}
],
"PreToolUse": [
{
"matcher": "execute_command",
"hooks": [
{
"type": "command",
"command": "python3 ~/.codebuddy/hooks/npm-safety-check.py",
"timeout": 5
}
]
}
]
}
}
Python Project Hook Configuration
{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "python3 ~/.codebuddy/hooks/python-env-check.py",
"timeout": 10
}
]
}
],
"PostToolUse": [
{
"matcher": "write_to_file|replace_in_file",
"hooks": [
{
"type": "command",
"command": "python3 ~/.codebuddy/hooks/python-lint.py",
"timeout": 20
}
]
}
]
}
}

Best Practices

1. Script Development

Use Absolute Paths: Place Hook scripts in a fixed directory, reference using absolute paths
Error Handling: Ensure scripts have complete exception handling to avoid blocking the main flow
Fast Execution: Hooks should complete quickly, avoid time-consuming operations
Idempotency: Hooks may be called multiple times, ensure consistent results across multiple executions
Logging: Use sys.stderr for debug output, don't pollute stdout

2. Security

Input Validation: Always validate input data integrity
Whitelist Over Blacklist: Use whitelist mechanisms for permission control
Avoid Code Injection: Never directly execute user input
Least Privilege: Hook scripts should run with minimum necessary permissions

3. Performance Optimization

Set Reasonable Timeouts: Adjust timeout based on script complexity
Design for Parallelism: Avoid dependencies between Hooks, fully utilize parallel execution
Cache Results: Consider caching results for repeated calculations

4. Debugging Tips

Manually Test Hook Scripts:
echo '{"hook_event_name":"PreToolUse","tool_name":"execute_command","tool_input":{"command":"npm install"}}' | \\
python3 /path/to/your_hook.py
Debug Output:
# Output debug information in Hook script
import sys

sys.stderr.write(f"[DEBUG] Processing command: {command}\\n")
sys.stderr.flush()

5. Configuration Management

Project-Specific Hooks: Place in <workspace>/.codebuddy/, version control with project
Personal Hooks: Place in ~/.codebuddy/, reuse across projects

Performance Optimization Tips

1. Reduce Hook Execution Time

Use Fast Languages: Shell scripts typically start faster than Python
Avoid Repeated Work: Cache computation results
Async Processing: Use background tasks for non-critical operations
Early Exit: Determine early if processing is needed
Example
# Bad practice: Load large file every time
def main():
with open('huge_config.json', 'r') as f:
config = json.load(f) # Read every time
# ... processing logic

# Good practice: Cache configuration
CONFIG_CACHE = None

def get_config():
global CONFIG_CACHE
if CONFIG_CACHE is None:
with open('huge_config.json', 'r') as f:
CONFIG_CACHE = json.load(f)
return CONFIG_CACHE

2. Optimize Matcher Configuration

{
"hooks": {
"PreToolUse": [
{
"matcher": "execute_command",
"hooks": [
{
"type": "command",
"command": "/path/to/fast_check.sh",
"timeout": 3
}
]
},
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "/path/to/general_check.py",
"timeout": 10
}
]
}
]
}
}

3. Parallel Execution Considerations

Multiple Hooks execute in parallel, don't rely on execution order
Avoid file write conflicts between Hooks
Use file locks or atomic operations for shared resources
import fcntl

def safe_append_log(message):
"""Thread-safe log writing"""
with open('/tmp/hook.log', 'a') as f:
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
f.write(message + '\\n')
fcntl.flock(f.fileno(), fcntl.LOCK_UN)

Security Best Practices

1. Input Validation

Never trust input data:
def validate_input(input_data):
"""Validate input data integrity"""
required_fields = ['hook_event_name', 'session_id']

for field in required_fields:
if field not in input_data:
raise ValueError(f"Missing required field: {field}")

# Validate field types
if not isinstance(input_data.get('tool_input'), dict):
raise ValueError("tool_input must be a dictionary")

return True

2. Command Injection Protection

Never directly execute user input:
# Dangerous: Direct execution
os.system(f"echo {user_input}")

# Safe: Use parameterized approach
import subprocess
subprocess.run(['echo', user_input], check=True)

3. Path Traversal Protection

import os

def safe_file_access(file_path, project_dir):
"""Ensure file path is within project directory"""
abs_path = os.path.abspath(file_path)
abs_project = os.path.abspath(project_dir)

if not abs_path.startswith(abs_project):
raise ValueError("Path traversal detected")

return abs_path

4. Privilege Minimization

# Hook scripts should run with minimum privileges
# Avoid using sudo or root permissions

# Check privileges
if os.geteuid() == 0:
print("Warning: Running as root is not recommended", file=sys.stderr)

Advanced Usage

Conditional Execution

Decide whether to process based on conditions in the Hook script:
def main():
input_data = json.loads(sys.stdin.read())

# Only process under specific conditions
if not should_process(input_data):
print(json.dumps({"continue": True}))
return 0

# Execute processing logic
...


Multi-Rule Combination

Implement multiple rules in a single Hook script:

def main():
input_data = json.loads(sys.stdin.read())

# Apply multiple rules
for rule in RULES:
if rule.matches(input_data):
return rule.apply(input_data)

# Default behavior
print(json.dumps({"continue": True}))
return 0

External Service Integration

Hooks can call external APIs or services:
import requests

def check_with_external_service(command):
response = requests.post('https://api.example.com/validate',
json={'command': command},
timeout=5)
return response.json()

FAQ

Q1: Hook is not being executed?

Checklist:
1. Configuration file path is correct (settings.json in .codebuddy directory)
2. hooks field is configured correctly, JSON format is valid
3. matcher regex can match the target
4. Hook script has execution permission (chmod +x script.py)
5. Script path is correct (absolute paths recommended)
6. Script has correct shebang on first line (#!/usr/bin/env python3)

Q2: Hook execution timeout?

Solutions:
Increase timeout configuration value
Optimize Hook script performance
Check for infinite loops or blocking operations

Q3: How to debug Hook scripts?

Debugging Steps:
1. Use echo to manually pass test data
2. Use sys.stderr for debug output in the script
3. Verify JSON format is correct

Q4: Execution order of multiple Hooks?

Answer:
Hooks execute in parallel, execution order is not guaranteed
If sequential execution is needed, merge logic into a single Hook script
Identical commands are automatically deduplicated

Q5: Modified parameters not taking effect?

Check Points:
Ensure modifiedInput field is returned
Ensure permissionDecision is allow
Check if field names match tool parameters
Verify JSON format is correct
Ensure continue is true

Q6: SessionStart Hook triggers on every request?

Cause: SessionStart should only trigger once per new session
Solutions:
System tracks sessions via conversationId
Multiple requests within the same session will not trigger repeatedly
If issues persist, check if session ID changes in logs

Appendix

A. Complete HookInput Interface Definition

interface HookInput {
// Common fields
session_id?: string; // Session ID
transcript_path?: string; // Conversation transcript path
cwd?: string; // Current working directory
hook_event_name: string; // Hook event name

// SessionStart specific (currently only 'startup' is supported)
source?: 'startup';

// UserPromptSubmit specific
prompt?: string; // User input content

// PreToolUse/PostToolUse specific
tool_name?: string; // Tool name
tool_input?: Record<string, any>; // Tool input parameters
tool_response?: any; // Tool response (PostToolUse only)

// Stop specific
stop_hook_active?: boolean; // Whether Stop Hook is activated

// PreCompact specific
trigger?: 'manual' | 'auto'; // Trigger method
custom_instructions?: string; // Custom compaction instructions
}

B. Complete HookOutput Interface Definition

interface HookOutput {
// Basic control
continue?: boolean; // Whether to continue execution (default true)
stopReason?: string; // Stop reason
suppressOutput?: boolean; // Whether to hide output
systemMessage?: string; // System message

// Hook-specific output
hookSpecificOutput?: {
hookEventName: string; // Hook event name

// PreToolUse specific
permissionDecision?: 'allow' | 'deny' | 'ask';
permissionDecisionReason?: string;
modifiedInput?: Record<string, any>;

// SessionStart/UserPromptSubmit/PostToolUse specific
additionalContext?: string; // Additional context
};
}

C. Environment Variables List

Environment Variable
Description
Example Value
CODEBUDDY_PROJECT_DIR
Project root directory
/path/to/project
CLAUDE_PROJECT_DIR
Project root directory (Claude Code compatible)
/path/to/project

D. Exit Code Details

Exit Code
Meaning
stdout
stderr
Behavior
0
Success
Processed as result
Ignored
Continue execution, may inject context
1
Warning
Ignored
Displayed as warning
Continue execution
2
Block/Feedback
Ignored
Passed to Agent
PreToolUse: Block execution<br>Stop: Provide feedback
Other
Error
Ignored
Displayed as warning
Continue execution

E. Common Tool Names List

File Operation Tools:
read_file - Read file
write_to_file - Write to file
replace_in_file - Replace file content
delete_files - Delete files
list_files - List files
search_file - Search files
Code Operation Tools:
search_content - Search content
read_lints - Read Lint errors
Execution Tools:
execute_command - Execute command
preview_url - Preview URL
Other Tools:
task - Create subtask
web_search - Web search
web_fetch - Fetch web content
ask_followup_question - Ask user

Summary

The Hook feature provides powerful extension capabilities, allowing you to insert custom logic at critical points of the AI Agent. By using Hooks properly, you can:

Enhance Security: Validate and block dangerous operations
Automate Workflows: Intelligently modify parameters, automatically backup files
Monitor and Audit: Record tool execution logs
Customize Behavior: Inject project-specific context

Start using the Hook feature to make your AI Agent smarter, safer, and more aligned with your project needs!

Happy Hooking!

Ajuda e Suporte

Esta página foi útil?

comentários