Route Permission-Prompt Notifications to a Webhook
For an unattended or CI-run agent, a permission prompt that only shows up in a terminal no one is watching is the same as no prompt at all. This posts it to a configured webhook (a pager, a Slack channel) so a human actually sees it.
1. Save this as the hook script
#!/usr/bin/env python3
"""Notification hook — posts a permission_prompt notification to a
webhook. Wire with matcher "permission_prompt". Set WEBHOOK_URL in the
environment."""
import json, os, sys, urllib.request
data = json.load(sys.stdin)
webhook_url = os.environ.get("WEBHOOK_URL", "")
if not webhook_url:
sys.exit(0)
payload = json.dumps({"text": f"Permission prompt: {data.get('message', '')}"}).encode()
try:
req = urllib.request.Request(webhook_url, data=payload,
headers={"Content-Type": "application/json"})
urllib.request.urlopen(req, timeout=5)
except Exception as e:
print(f"NOTICE: failed to post to webhook: {e}", file=sys.stderr)
sys.exit(0)
Save to a path inside your project, e.g. .claude/hooks/route-permission-prompt-webhook.sh, then chmod +x it.
2. Wire it into .claude/settings.json
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [
{"type": "command", "command": "python3 .claude/hooks/route-permission-prompt-webhook.py"}
]
}
]
}
}
Before you use this
A hook runs with your local shell's permissions — review the script above before adding it, the same way you'd review any script you didn't write yourself. See our guide on hook security risks for the specific CVEs this category of feature has already produced.
Related hooks