Claude Code Hooks Integrations
Tags: integrations third-party external-tools services
A comprehensive guide to integrating Claude Code hooks with external tools and services.
Version Control Integration
Git Hooks
Claude Code can work seamlessly with Git through hooks:
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "git add -A && git commit -m 'Claude Code: Auto-commit changes' || echo 'No changes'"
}
]
}
]
}
}GitHub Integration
GitHub CLI (gh)
# Create PR after changes
gh pr create --title "Claude improvements" --body "Automated by Claude Code"
# Check PR status
gh pr checks
# Auto-merge when ready
gh pr merge --auto --squashGitHub Actions
Claude Code has an official GitHub Action:
name: Claude Code Review
on:
pull_request:
types: [opened, synchronize]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: anthropics/claude-code-action@beta
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
direct_prompt: |
Review this PR for:
- Code quality issues
- Security vulnerabilities
- Performance concernsGitButler Integration
GitButler automatically creates isolated branches for each Claude session:
- Keeps changes organized
- Easy rollback of experiments
- Visual diff tracking
CI/CD Pipeline Integrations
Jenkins
pipeline {
agent any
stages {
stage('Claude Code Analysis') {
steps {
sh 'claude-code --prompt "Analyze code quality" --format json > analysis.json'
publishHTML([allowMissing: false, alwaysLinkToLastBuild: true, keepAll: true, reportDir: '.', reportFiles: 'analysis.json', reportName: 'Claude Analysis'])
}
}
}
}CircleCI
version: 2.1
jobs:
claude-review:
docker:
- image: anthropics/claude-code:latest
steps:
- checkout
- run:
name: Claude Code Review
command: |
claude-code --prompt "Review recent changes" --output review.md
- store_artifacts:
path: review.mdGitLab CI
claude-analysis:
image: anthropics/claude-code:latest
script:
- claude-code --prompt "Analyze merge request" --mr $CI_MERGE_REQUEST_IID
artifacts:
reports:
junit: claude-report.xmlMonitoring and Logging
Multi-Agent Observability System
Complete monitoring solution with SQLite backend and Vue frontend:
# Hook configuration for observability
{
"hooks": {
"PreToolUse": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "python .claude/hooks/log_event.py"
}
]
}
]
}
}Prometheus Integration
#!/usr/bin/env python3
from prometheus_client import Counter, Histogram, push_to_gateway
import json
import sys
# Metrics
tool_usage = Counter('claude_tool_usage', 'Tool usage count', ['tool_name'])
operation_duration = Histogram('claude_operation_duration', 'Operation duration')
data = json.load(sys.stdin)
tool_usage.labels(tool_name=data['tool_name']).inc()
# Push to Prometheus
push_to_gateway('localhost:9091', job='claude_hooks', registry=registry)ELK Stack Integration
#!/bin/bash
# Send logs to Elasticsearch
JSON_INPUT=$(cat)
curl -X POST "localhost:9200/claude-hooks/_doc" \
-H "Content-Type: application/json" \
-d "$JSON_INPUT"Notification Services
Slack Integration
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "curl -X POST -H 'Content-Type: application/json' -d '{\"text\":\"Claude: '\"$CLAUDE_NOTIFICATION\"'\"}' $SLACK_WEBHOOK_URL"
}
]
}
]
}
}Discord Integration
#!/usr/bin/env python3
import json
import sys
import requests
import os
webhook_url = os.environ['DISCORD_WEBHOOK_URL']
data = json.load(sys.stdin)
requests.post(webhook_url, json={
"content": f"Claude Code Event: {data['hook_event_name']}",
"embeds": [{
"title": "Tool Usage",
"fields": [
{"name": "Tool", "value": data.get('tool_name', 'N/A')},
{"name": "Files", "value": os.environ.get('CLAUDE_FILE_PATHS', 'N/A')}
]
}]
})Microsoft Teams
#!/bin/bash
TEAMS_WEBHOOK="https://outlook.office.com/webhook/..."
curl -H "Content-Type: application/json" -d '{
"@type": "MessageCard",
"@context": "https://schema.org/extensions",
"summary": "Claude Code Activity",
"sections": [{
"activityTitle": "Claude Code completed task",
"facts": [{
"name": "Tool",
"value": "'$CLAUDE_TOOL_NAME'"
}]
}]
}' "$TEAMS_WEBHOOK"Email (SendGrid)
#!/usr/bin/env python3
import sendgrid
from sendgrid.helpers.mail import Mail
import json
import sys
import os
sg = sendgrid.SendGridAPIClient(api_key=os.environ['SENDGRID_API_KEY'])
data = json.load(sys.stdin)
message = Mail(
from_email='claude@example.com',
to_emails='team@example.com',
subject='Claude Code Alert',
html_content=f'<strong>Event:</strong> {data["hook_event_name"]}<br><strong>Tool:</strong> {data.get("tool_name", "N/A")}'
)
sg.send(message)Development Tools
Docker Integration
#!/bin/bash
# Run hooks in containerized environment
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace \
-e CLAUDE_TOOL_NAME \
-e CLAUDE_FILE_PATHS \
my-hook-container:latestKubernetes Integration
apiVersion: v1
kind: ConfigMap
metadata:
name: claude-hooks
data:
settings.json: |
{
"hooks": {
"PostToolUse": [{
"matcher": ".*",
"hooks": [{
"type": "command",
"command": "kubectl annotate deployment myapp claude.ai/last-update=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}]
}]
}
}Terraform Integration
resource "null_resource" "claude_hook" {
triggers = {
always_run = timestamp()
}
provisioner "local-exec" {
command = "claude-code --prompt 'Review Terraform changes' --output tfplan-review.md"
}
}Model Context Protocol (MCP)
MCP Server Integration
MCP tools follow the pattern mcp__<server>__<tool>:
{
"hooks": {
"PreToolUse": [
{
"matcher": "mcp__github__.*",
"hooks": [
{
"type": "command",
"command": "echo 'GitHub MCP tool used: $CLAUDE_TOOL_NAME' >> mcp.log"
}
]
}
]
}
}Popular MCP Integrations
- Filesystem: File operations
- GitHub: Repository management
- Slack: Message posting
- Google Drive: Document access
- Figma: Design file access
IDE and Editor Integrations
VS Code / Cursor
Claude-Autopilot extension for automated task execution:
{
"claude-autopilot.hooks": {
"onTaskComplete": "npm test",
"onError": "git reset --hard"
}
}Neovim
claude-code.nvim plugin integration:
require('claude-code').setup({
hooks = {
post_edit = function(filepath)
vim.cmd('!prettier --write ' .. filepath)
end
}
})IntelliJ IDEA
<component name="ClaudeCodeHooks">
<option name="postToolUse">
<command>./gradlew spotlessApply</command>
</option>
</component>Web Services
Webhook.site
For testing webhook integrations:
WEBHOOK_URL="https://webhook.site/your-unique-url"
curl -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{\"event\": \"$CLAUDE_TOOL_NAME\", \"files\": \"$CLAUDE_FILE_PATHS\"}"IFTTT Integration
#!/usr/bin/env python3
import requests
import json
import sys
IFTTT_KEY = "your-key"
EVENT_NAME = "claude_code_event"
data = json.load(sys.stdin)
requests.post(
f"https://maker.ifttt.com/trigger/{EVENT_NAME}/with/key/{IFTTT_KEY}",
json={
"value1": data['tool_name'],
"value2": data.get('file_path', ''),
"value3": data['hook_event_name']
}
)Zapier Integration
#!/bin/bash
ZAPIER_WEBHOOK="https://hooks.zapier.com/hooks/catch/..."
curl -X POST "$ZAPIER_WEBHOOK" \
-H "Content-Type: application/json" \
-d "{
\"tool\": \"$CLAUDE_TOOL_NAME\",
\"files\": \"$CLAUDE_FILE_PATHS\",
\"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"
}"Security and Compliance
Vault Integration
#!/usr/bin/env python3
import hvac
import json
import sys
client = hvac.Client(url='http://localhost:8200')
client.token = 'your-vault-token'
# Store sensitive operations
data = json.load(sys.stdin)
if 'sensitive' in data.get('file_path', ''):
client.secrets.kv.v2.create_or_update_secret(
path='claude-audit',
secret={'operation': data, 'timestamp': datetime.now().isoformat()}
)SonarQube Integration
#!/bin/bash
# Run SonarQube analysis after code changes
if [[ "$CLAUDE_FILE_PATHS" =~ \.(js|ts|py|java)$ ]]; then
sonar-scanner \
-Dsonar.projectKey=myproject \
-Dsonar.sources=. \
-Dsonar.host.url=http://localhost:9000
fiPerformance Monitoring
New Relic Integration
import newrelic.agent
@newrelic.agent.function_trace()
def process_hook(data):
# Your hook logic
pass
newrelic.agent.record_custom_event('ClaudeHook', {
'tool_name': data['tool_name'],
'event_type': data['hook_event_name']
})Datadog Integration
from datadog import initialize, statsd
import json
import sys
initialize(statsd_host='localhost', statsd_port=8125)
data = json.load(sys.stdin)
statsd.increment('claude.hook.execution', tags=[f"tool:{data['tool_name']}"])
statsd.histogram('claude.hook.duration', duration, tags=[f"event:{data['hook_event_name']}"])Database Integrations
PostgreSQL Logging
#!/usr/bin/env python3
import psycopg2
import json
import sys
from datetime import datetime
conn = psycopg2.connect("dbname=claude_logs user=postgres")
cur = conn.cursor()
data = json.load(sys.stdin)
cur.execute("""
INSERT INTO hook_events (timestamp, event_type, tool_name, file_paths, data)
VALUES (%s, %s, %s, %s, %s)
""", (
datetime.now(),
data['hook_event_name'],
data.get('tool_name'),
os.environ.get('CLAUDE_FILE_PATHS'),
json.dumps(data)
))
conn.commit()Redis Caching
#!/usr/bin/env python3
import redis
import json
import sys
r = redis.Redis(host='localhost', port=6379, db=0)
data = json.load(sys.stdin)
# Cache file metadata
for file_path in os.environ.get('CLAUDE_FILE_PATHS', '').split():
r.setex(
f"claude:file:{file_path}",
300, # 5 minute TTL
json.dumps({
'last_tool': data['tool_name'],
'timestamp': time.time()
})
)Best Practices for Integrations
- Use Environment Variables for sensitive data
- Implement Retry Logic for network calls
- Add Timeout Handling to prevent hanging
- Log Integration Failures separately
- Version Your Integrations with your code
- Test Integrations Locally before deployment
- Monitor Integration Health with alerts
Community Tools
Claude Code Hook Collections
- rins_hooks: Cross-platform installer for common hooks
- claude-code-hooks-multi-agent-observability: Complete monitoring system
- TDD Guard: Enforces test-driven development practices
Hook Generators
- claude-hook-wizard: Interactive CLI for creating hooks
- hook-templates: Collection of hook templates
- claude-code-hook-validator: Validates hook configurations