Skip to main content

Example Hooks

Here are practical examples of hooks you can use in your projects. Each example includes the hook script and the corresponding configuration.
Block shell commands that could be destructive:Hook Script (/etc/augment/hooks/security-block-dangerous.sh):
#!/usr/bin/env bash

EVENT_DATA=$(cat)
COMMAND=$(echo "$EVENT_DATA" | jq -r '.tool_input.command // ""')

# Check for dangerous patterns
if echo "$COMMAND" | grep -qE "rm -rf|sudo|chmod 777"; then
  echo "Blocked dangerous command: $COMMAND" >&2
  exit 2
fi

exit 0
#!/usr/bin/env python3
import sys
import json
import re

event_data = json.load(sys.stdin)
command = event_data.get('tool_input', {}).get('command', '')

# Check for dangerous patterns
if re.search(r'rm -rf|sudo|chmod 777', command):
    print(f"Blocked dangerous command: {command}", file=sys.stderr)
    sys.exit(2)

sys.exit(0)
Configuration:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "launch-process",
        "hooks": [
          {
            "type": "command",
            "command": "/etc/augment/hooks/security-block-dangerous.sh",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}
Automatically format code files using language-specific formatters (Biome, Ruff, gofmt, rustfmt) before the agent edits them.Hook Script (/etc/augment/hooks/auto-format.sh):
#!/usr/bin/env bash

EVENT_DATA=$(cat)
TOOL_NAME=$(echo "$EVENT_DATA" | jq -r '.tool_name')

# Only run for file editing tools
[[ "$TOOL_NAME" != "str-replace-editor" ]] && exit 0

FILE_PATH=$(echo "$EVENT_DATA" | jq -r '.tool_input.path // ""')
[[ -z "$FILE_PATH" || ! -f "$FILE_PATH" ]] && exit 0

EXT="${FILE_PATH##*.}"

case "$EXT" in
  ts|tsx|js|jsx) command -v biome &>/dev/null && biome format --write "$FILE_PATH" ;;
  py) command -v ruff &>/dev/null && ruff format "$FILE_PATH" ;;
  go) command -v gofmt &>/dev/null && gofmt -w "$FILE_PATH" ;;
  rs) command -v rustfmt &>/dev/null && rustfmt "$FILE_PATH" ;;
esac

exit 0
#!/usr/bin/env python3
import sys, json, subprocess, shutil
from pathlib import Path

event_data = json.load(sys.stdin)
if event_data.get('tool_name') != 'str-replace-editor':
    sys.exit(0)

file_path = event_data.get('tool_input', {}).get('path', '')
if not file_path or not Path(file_path).exists():
    sys.exit(0)

ext = Path(file_path).suffix.lstrip('.')
formatters = {
    'ts': ['biome', 'format', '--write'],
    'tsx': ['biome', 'format', '--write'],
    'js': ['biome', 'format', '--write'],
    'py': ['ruff', 'format'],
    'go': ['gofmt', '-w'],
    'rs': ['rustfmt'],
}

if ext in formatters and shutil.which(formatters[ext][0]):
    subprocess.run(formatters[ext] + [file_path], timeout=30)

sys.exit(0)
Configuration:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "str-replace-editor",
        "hooks": [
          {
            "type": "command",
            "command": "/etc/augment/hooks/auto-format.sh",
            "timeout": 30000
          }
        ]
      }
    ]
  }
}
Supported Formatters:
LanguageFormatterCommand
TypeScript/JavaScriptBiomebiome format --write
PythonRuffruff format
Gogofmtgofmt -w
Rustrustfmtrustfmt
Monitor when the agent accesses sensitive files:Hook Script (/etc/augment/hooks/audit.sh):
#!/usr/bin/env bash
EVENT_DATA=$(cat)
FILE_PATH=$(echo "$EVENT_DATA" | jq -r '.tool_input.path // ""')

if echo "$FILE_PATH" | grep -qE "\.env|secrets|credentials"; then
  echo "[AUDIT] Sensitive file access: $FILE_PATH" >&2
fi

exit 0  # Audit only, don't block
Configuration:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "view|str-replace-editor",
        "hooks": [
          { "type": "command", "command": "/etc/augment/hooks/audit.sh" }
        ]
      }
    ]
  }
}
A simple hook to block sudo commands:Hook Script (/etc/augment/hooks/validate-tool.sh):
#!/usr/bin/env bash
EVENT_DATA=$(cat)
COMMAND=$(echo "$EVENT_DATA" | jq -r '.tool_input.command // ""')

if echo "$COMMAND" | grep -q "sudo"; then
  echo "Blocked: sudo not allowed" >&2
  exit 2  # Block execution
fi

exit 0
Configuration:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "launch-process",
        "hooks": [
          {
            "type": "command",
            "command": "/etc/augment/hooks/validate-tool.sh",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}
Inject development context when a session starts:Hook Script (/etc/augment/hooks/load-context.sh):
#!/usr/bin/env bash

# Load recent git commits
echo "Recent commits:"
git log --oneline -5

# Load current branch info
echo ""
echo "Current branch: $(git branch --show-current)"

# Load open issues (example)
echo ""
echo "Open issues:"
# curl -s https://api.example.com/issues | jq -r '.[] | "- \(.title)"'

exit 0
#!/usr/bin/env python3
import sys
import subprocess

# Load recent git commits
print("Recent commits:")
result = subprocess.run(['git', 'log', '--oneline', '-5'],
                       capture_output=True, text=True)
print(result.stdout)

# Load current branch info
print("")
print("Current branch:", end=" ")
result = subprocess.run(['git', 'branch', '--show-current'],
                       capture_output=True, text=True)
print(result.stdout.strip())

sys.exit(0)
Configuration:
{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "/etc/augment/hooks/load-context.sh",
            "timeout": 10000
          }
        ]
      }
    ]
  }
}
Run cleanup when a session ends:Hook Script (/etc/augment/hooks/cleanup.sh):
#!/usr/bin/env bash
echo "[$(date)] Session ended" >&2
exit 0
Configuration:
{
  "hooks": {
    "SessionEnd": [
      {
        "hooks": [
          { "type": "command", "command": "/etc/augment/hooks/cleanup.sh" }
        ]
      }
    ]
  }
}
Prevent agents from accessing production systems or sensitive data:Hook Script (/etc/augment/hooks/block-prod.sh):
#!/usr/bin/env bash
EVENT_DATA=$(cat)
TOOL_INPUT=$(echo "$EVENT_DATA" | jq -r '.tool_input | tostring')

if echo "$TOOL_INPUT" | grep -qE "prod-db|production\.database"; then
  echo "Access to production databases is not allowed" >&2
  exit 2
fi

exit 0
Configuration:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "/etc/augment/hooks/block-prod.sh",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}
Log all tool executions for compliance:Hook Script (/etc/augment/hooks/audit-log.sh):
#!/usr/bin/env bash
EVENT_DATA=$(cat)
TOOL=$(echo "$EVENT_DATA" | jq -r '.tool_name')
echo "[$(date -u +%FT%TZ)] Tool: $TOOL" >&2
exit 0
Configuration:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "/etc/augment/hooks/audit-log.sh",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}
Block excessive API calls to MCP servers:Hook Script (/etc/augment/hooks/rate-limit.sh):
#!/usr/bin/env bash
EVENT_DATA=$(cat)
SERVER=$(echo "$EVENT_DATA" | jq -r '.mcp_metadata.mcpExecutedToolServerName // ""')
RATE_FILE="/tmp/rate-$SERVER"
COUNT=$(cat "$RATE_FILE" 2>/dev/null || echo "0")

if [ "$COUNT" -gt 10 ]; then
  echo "Rate limit exceeded" >&2
  exit 2
fi

echo $((COUNT + 1)) > "$RATE_FILE"
exit 0
Configuration:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp:*",
        "hooks": [
          {
            "type": "command",
            "command": "/etc/augment/hooks/rate-limit.sh",
            "timeout": 5000
          }
        ],
        "metadata": {
          "includeMCPMetadata": true
        }
      }
    ]
  }
}
Block the agent from stopping until tests are modified:Hook Script (/etc/augment/hooks/require-tests.sh):
#!/usr/bin/env bash
EVENT_DATA=$(cat)

# Extract code changes
CODE_RESPONSE=$(echo "$EVENT_DATA" | jq -r '.conversation.agentCodeResponse // []')

# Check if any test files were modified
TEST_FILES=$(echo "$CODE_RESPONSE" | jq -r '.[] | select(.path | test("test|spec")) | .path')

if [[ -z "$TEST_FILES" ]]; then
  # No test files modified - block stop
  cat << EOF
{
  "hookSpecificOutput": {
    "hookEventName": "Stop",
    "decision": "block",
    "reason": "Please add or update tests before finishing"
  }
}
EOF
  exit 0
fi

exit 0
#!/usr/bin/env python3
import sys
import json
import re

event_data = json.load(sys.stdin)
conversation = event_data.get('conversation', {})
code_response = conversation.get('agentCodeResponse', [])

# Check if any test files were modified
test_files = [
    change['path'] for change in code_response
    if re.search(r'test|spec', change.get('path', ''))
]

if not test_files:
    output = {
        "hookSpecificOutput": {
            "hookEventName": "Stop",
            "decision": "block",
            "reason": "Please add or update tests before finishing"
        }
    }
    print(json.dumps(output))
    sys.exit(0)

sys.exit(0)
Configuration:
{
  "hooks": {
    "Stop": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "/etc/augment/hooks/require-tests.sh",
            "timeout": 5000
          }
        ],
        "metadata": {
          "includeConversationData": true
        }
      }
    ]
  }
}

Advanced Configuration Patterns

These patterns show how to combine multiple hooks effectively:
Execute multiple hooks in order for the same event:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "launch-process",
        "hooks": [
          {
            "type": "command",
            "command": "/etc/augment/hooks/log-command.sh",
            "timeout": 5000
          },
          {
            "type": "command",
            "command": "/etc/augment/hooks/security-check.sh",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}
If any hook returns exit code 2, execution is blocked and subsequent hooks are not run.
Use multiple matcher configurations for different tools:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp:*",
        "hooks": [
          {
            "type": "command",
            "command": "/etc/augment/hooks/log-mcp.sh",
            "timeout": 5000
          }
        ]
      },
      {
        "matcher": "launch-process",
        "hooks": [
          {
            "type": "command",
            "command": "/etc/augment/hooks/security-bash.sh",
            "timeout": 5000
          }
        ]
      },
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "/etc/augment/hooks/audit-all.sh",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}

See Also