Skip to content

code-examples

Production-ready hook implementations with all safety patterns.

From plugin
vexjoy-agent
413198 skills198 agents10 commands86 hooks
Install
$ npx -y skills add notque/vexjoy-agent --agent claude-code

How it fires

How this agent gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.

Context preview

The summary Claude sees to decide when to auto-load this agent.

Production-ready hook implementations with all safety patterns.

Agent definition

code-examples.md

Hook Development Code Examples

Production-ready hook implementations with all safety patterns.

Non-Blocking Hook Template

Complete template with comprehensive error handling and non-blocking execution.

#!/usr/bin/env python3
"""
Hook template with non-blocking execution patterns.
Always exits with code 0 to prevent blocking Claude Code.
"""
import json
import sys
import traceback
from pathlib import Path
from datetime import datetime

def debug_log(message):
    """Log debug information without blocking execution."""
    try:
        with open('/tmp/claude_hook_debug.log', 'a') as f:
            f.write(f"[{datetime.now().isoformat()}] {message}\n")
    except Exception:
        pass  # Never let logging block execution

def process_event(event_data):
    """
    Process the event and return result.

    Args:
        event_data: Parsed JSON from Claude Code event

    Returns:
        dict: Result to output (or None)
    """
    # Implement your hook logic here
    tool_name = event_data.get('tool', '')
    tool_output = event_data.get('output', '')

    debug_log(f"Processing {tool_name} event")

    # Example: Detect errors in tool output
    if 'error' in tool_output.lower():
        debug_log(f"Error detected in {tool_name}")
        return {'detected': True, 'tool': tool_name}

    return None

def main():
    """Main hook execution with comprehensive error handling."""
    try:
        # Parse input JSON from Claude Code
        input_data = json.loads(sys.stdin.read())

        # Process the event (implement specific logic here)
        result = process_event(input_data)

        # Output result if needed
        if result:
            print(json.dumps(result))

    except json.JSONDecodeError as e:
        debug_log(f"JSON parsing error: {e}")
    except Exception as e:
        debug_log(f"Unexpected error: {e}\\n{traceback.format_exc()}")
    finally:
        # CRITICAL: Always exit 0 to prevent blocking Claude Code
        sys.exit(0)

if __name__ == "__main__":
    main()

---

Error Detection and Classification Hook

Complete PostToolUse hook with error pattern detection and learning database integration.

#!/usr/bin/env python3
"""
Smart error detector with pattern matching and solution injection.
Detects errors, classifies them, queries learning database for solutions,
and injects high-confidence solutions into Claude Code context.
"""
import json
import sys
import hashlib
from pathlib import Path
from datetime import datetime

LEARNING_DB = Path.home() / '.claude' / 'learnings' / 'error_patterns.json'
DEBUG_LOG = Path('/tmp/claude_hook_debug.log')

def debug_log(message):
    """Non-blocking debug logging."""
    try:
        with DEBUG_LOG.open('a') as f:
            f.write(f"[{datetime.now().isoformat()}] {message}\\n")
    except Exception:
        pass

def classify_error(tool_name, error_output):
    """
    Classify error type from tool output.

    Args:
        tool_name: Name of the tool that errored
        error_output: Error message from tool

    Returns:
        str: Error classification (missing_file, permissions, etc.)
    """
    output_lower = error_output.lower()

    # Classification rules
    if 'no such file' in output_lower or 'filenotfound' in output_lower:
        return 'missing_file'
    elif 'permission denied' in output_lower:
        return 'permissions'
    elif 'multiple matches' in output_lower and tool_name == 'Edit':
        return 'multiple_matches'
    elif 'syntaxerror' in output_lower:
        return 'syntax_error'
    elif 'typeerror' in output_lower:
        return 'type_error'
    else:
        return 'unknown'

def generate_signature(tool_name, error_type, error_message):
    """
    Generate unique signature for error pattern.

    Args:
        tool_name: Tool that produced error
        error_type: Classification of error
        error_message: Error message (first 200 chars)

    Returns:
        str: MD5 signature for pattern matching
    """
    # Use first 200 chars to avoid signature pollution from dynamic data
    message_snippet = error_message[:200]
    signature_input = f"{tool_name}:{error_type}:{message_snippet}"
    return hashlib.md5(signature_input.encode()).hexdigest()

def query_learning_db(signature):
    """
    Query learning database for known pattern.

    Args:
        signature: Error signature to lookup

    Returns:
        dict: Pattern data if found and high confidence (>0.7), else None
    """
    try:
        if not LEARNING_DB.exists():
            return None

        with LEARNING_DB.open('r') as f:
            data = json.load(f)

        patterns = data.get('patterns', [])
        for pattern in patterns:
            if pattern.get('signature') == signature:
                confidence = pattern.get('confidence', 0.0)
                if confidence > 0.7:  # High confidence threshold
                    return pattern

    except Exception as e:
        debug_log(f"Learning DB query error: {e}")

    return None

def inject_solution(solution_data, event_name: str) -> None:
    """
    Inject solution into Claude Code context via stdout.

    Args:
        solution_data: Solution dict with description and command
        event_name: Hook event name (e.g. "PostToolUse")
    """
    try:
        from hook_utils import context_output
        text = (
            f"[auto-fix] action={solution_data.get('command', '')}\n"
            f"description={solution_data.get('description', '')}\n"
            f"confidence={solution_data.get('confidence', 0.0)}"
        )
        context_output(event_name, text).print_and_exit()
    except Exception as e:
        debug_log(f"Context injection error: {e}")

def main():
    """Main error detection logic."""
    try:
        # Parse event JSON
        event = json.loads(sys.stdin.read())

        # Extract tool info
        tool_name = event.get('tool', '')
        tool_output = event.get('output', '')
        is_error = event.g
Read more
Ships withvexjoy-agent

Essays and writing behind this toolkit live at vexjoy.com. AI agents skip steps. "Looks correct" replaces running tests. "Trivial change" replaces verification.

Get the whole plugin, auto-invoked