Skip to main content
Each hook event fires at a specific point in the agent’s lifecycle. Use the matcher field (a regex) to filter which tool invocations trigger your hook.

PreToolUse

Fires before a tool executes. Use this to block, modify, or add context to tool calls. Stdin data:
FieldDescriptionExample
tool_nameName of the tool being calledexec, edit, mcp__github__create_issue
tool_inputArguments passed to the tool{ "command": "rm -rf /", "shell_id": "main" }
Example — Block destructive commands:
{
  "PreToolUse": [
    {
      "matcher": "exec",
      "hooks": [
        {
          "type": "command",
          "command": "python3 -c \"import sys, json; data = json.load(sys.stdin); cmd = data.get('tool_input', {}).get('command', ''); sys.exit(2 if 'rm -rf' in cmd else 0)\""
        }
      ]
    }
  ]
}
Example — Require confirmation for writes outside src/: Use a script that inspects the tool input and returns a decision:
{
  "PreToolUse": [
    {
      "matcher": "edit",
      "hooks": [
        {
          "type": "command",
          "command": "./scripts/check-edit-path.sh",
          "timeout": 5
        }
      ]
    }
  ]
}

PostToolUse

Fires after a tool finishes executing. Use this for logging, validation, or triggering follow-up actions. Stdin data:
FieldDescription
tool_nameName of the tool that ran
tool_inputArguments that were passed
tool_responseObject with success (boolean), output (string), and error (string or null)
Example — Log all shell commands:
{
  "PostToolUse": [
    {
      "matcher": "exec",
      "hooks": [
        {
          "type": "command",
          "command": "sh -c 'cat >> ~/.devin-command-log'"
        }
      ]
    }
  ]
}

PermissionRequest

Fires when the agent needs a permission decision. Use this to implement custom approval logic. Stdin data:
FieldDescription
tool_nameTool requesting permission
tool_inputArguments for the tool call
Example — Auto-approve git commands:
{
  "PermissionRequest": [
    {
      "matcher": "exec",
      "hooks": [
        {
          "type": "command",
          "command": "python3 -c \"import sys, json; data = json.load(sys.stdin); cmd = data.get('tool_input', {}).get('command', ''); print(json.dumps({'decision': 'approve'})) if cmd.startswith('git ') else sys.exit(0)\""
        }
      ]
    }
  ]
}

UserPromptSubmit

Fires when the user submits a message. Use this to add context or trigger workflows. Stdin data:
FieldDescription
promptThe user’s message text
Example — Add project context for deploy-related prompts:
{
  "UserPromptSubmit": [
    {
      "matcher": "",
      "hooks": [
        {
          "type": "command",
          "command": "./scripts/add-deploy-context.sh"
        }
      ]
    }
  ]
}

Stop

Fires when the agent decides to stop (finish its turn). Use this to add follow-up instructions or prevent premature stopping. Stdin data:
FieldDescription
stop_hook_activeWhether a stop hook is already active
Example — Remind agent to run tests:
{
  "Stop": [
    {
      "matcher": "",
      "hooks": [
        {
          "type": "command",
          "command": "echo '{\"decision\": \"block\", \"reason\": \"Please run the test suite before stopping.\"}'"
        }
      ]
    }
  ]
}
Be careful with stop hooks that block — they can cause the agent to loop if the condition isn’t eventually satisfied.

SessionStart

Fires when a new session begins. Use this for initialization, logging, or environment setup. Stdin data:
FieldDescription
sourceHow the session was started
Example — Run setup script:
{
  "SessionStart": [
    {
      "matcher": "",
      "hooks": [
        {
          "type": "command",
          "command": "./scripts/dev-setup.sh",
          "timeout": 10
        }
      ]
    }
  ]
}

SessionEnd

Fires when a session ends. Use this for cleanup or final logging. Stdin data:
FieldDescription
reasonWhy the session ended

Matching Multiple Events

A single hooks file can define hooks for multiple events:
{
  "PreToolUse": [
    {
      "matcher": "",
      "hooks": [
        { "type": "command", "command": "./scripts/audit.sh" }
      ]
    }
  ],
  "PostToolUse": [
    {
      "matcher": "",
      "hooks": [
        { "type": "command", "command": "./scripts/audit.sh" }
      ]
    }
  ]
}

Using the Matcher

The matcher field is a regex matched against the tool name:
MatcherMatches
"" (empty)All tools
"exec"The exec tool
"exec|edit"exec or edit
"mcp__.*"All MCP tools