🔧

Ripperdoc

Hooks

Automate workflows with custom hooks

Hooks let you execute custom scripts at various points in Ripperdoc's lifecycle.

Hook Events

EventDescription
PreToolUseBefore a tool executes
PostToolUseAfter a tool completes
PermissionRequestWhen permission is requested
UserPromptSubmitWhen user submits a message
NotificationFor status notifications
StopWhen the agent completes
SessionStartWhen a session begins
SessionEndWhen a session ends

Configuration Files

Hooks are configured in JSON files (loaded in order):

  1. ~/.ripperdoc/hooks.json - Global hooks
  2. .ripperdoc/hooks.json - Project hooks
  3. .ripperdoc/hooks.local.json - Local hooks (gitignored)

Hook Types

Command Hooks

Execute shell commands:

{
  "hooks": [
    {
      "event": "PostToolUse",
      "type": "command",
      "matcher": {
        "tool_name": "Bash"
      },
      "command": "echo 'Bash command completed' >> /tmp/ripperdoc.log"
    }
  ]
}

Prompt Hooks

Use an LLM to process the hook:

{
  "hooks": [
    {
      "event": "PreToolUse",
      "type": "prompt",
      "matcher": {
        "tool_name": "Edit"
      },
      "prompt": "Review this edit for security issues"
    }
  ]
}

Matchers

Control when hooks run:

{
  "matcher": {
    "tool_name": "Bash",
    "tool_name_regex": "^(Bash|Edit)$",
    "input_contains": "npm",
    "path_pattern": "*.py"
  }
}
MatcherDescription
tool_nameExact tool name
tool_name_regexRegex pattern for tool name
input_containsInput must contain string
path_patternGlob pattern for file paths

Hook Decisions

Hooks can return decisions to control execution:

{
  "decision": "allow",
  "message": "Approved by hook"
}
DecisionEffect
allowProceed with operation
denyBlock the operation
askPrompt user for confirmation
blockBlock and stop processing

Examples

Logging Tool Usage

{
  "hooks": [
    {
      "event": "PostToolUse",
      "type": "command",
      "command": "echo '[$(date)] Tool: $TOOL_NAME' >> ~/.ripperdoc/tool.log"
    }
  ]
}

Protect Sensitive Files

{
  "hooks": [
    {
      "event": "PreToolUse",
      "type": "command",
      "matcher": {
        "tool_name": "Edit",
        "path_pattern": "*.env*"
      },
      "command": "echo '{\"decision\": \"deny\", \"message\": \"Cannot edit .env files\"}'"
    }
  ]
}

Desktop Notifications

{
  "hooks": [
    {
      "event": "Notification",
      "type": "command",
      "command": "notify-send 'Ripperdoc' '$MESSAGE'"
    }
  ]
}

Auto-format on Edit

{
  "hooks": [
    {
      "event": "PostToolUse",
      "type": "command",
      "matcher": {
        "tool_name": "Edit",
        "path_pattern": "*.py"
      },
      "command": "black $FILE_PATH 2>/dev/null || true"
    }
  ]
}

Environment Variables

Hooks receive context via environment variables:

VariableDescription
TOOL_NAMEName of the tool
TOOL_INPUTJSON-encoded tool input
FILE_PATHFile path (for file operations)
MESSAGENotification message
SESSION_IDCurrent session ID

Managing Hooks

Use the /hooks command:

> /hooks list
> /hooks reload

Best Practices

  1. Test hooks carefully: Use logging to debug hook behavior
  2. Keep hooks fast: Slow hooks impact responsiveness
  3. Use local hooks for experiments: .ripperdoc/hooks.local.json is gitignored
  4. Handle errors gracefully: Hooks should not crash Ripperdoc