Push Claude Code notifications to your phone via ntfy.sh, and approve/reject tool calls with action buttons — no server required.
| Script | Hook | Purpose |
|---|---|---|
ntfy_notify.sh |
Notification |
Push alerts when Claude needs input or finishes a task |
ntfy_approve.sh |
PreToolUse |
Approve/reject tool calls from your phone |
- ntfy.sh app installed on your phone (Android/iOS)
curlandjqinstalled on your machine- A unique ntfy topic name (acts as your channel — pick something hard to guess)
Pick a unique topic name and update both scripts:
# In ntfy_notify.sh
NTFY_TOPIC="https://ntfy.sh/my-unique-topic-abc123"
# In ntfy_approve.sh
NTFY_TOPIC="https://ntfy.sh/my-unique-topic-abc123"
NTFY_RESPONSE_TOPIC="https://ntfy.sh/my-unique-topic-abc123-response"Subscribe to your topic in the ntfy mobile app to receive notifications.
Add to ~/.claude/settings.json:
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt|idle_prompt",
"hooks": [
{
"type": "command",
"command": "bash /path/to/ntfy_notify.sh"
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "bash /path/to/ntfy_approve.sh"
}
]
}
]
}
}# Test notifications
echo '{"notification_type":"idle_prompt","message":"Hello from test"}' | bash ntfy_notify.sh
# Test approval (tap Approve/Reject on your phone)
echo '{"tool_name":"Bash","tool_input":{"command":"ls -la"}}' | bash ntfy_approve.sh
echo "Exit code: $?" # 0 = approved, 2 = rejected/timeoutSends a notification when Claude is idle or needs permission. Features:
- Dynamic priority:
permission_prompt→ high (persistent on mobile), others → default - Dynamic emoji tags: lock for permissions, hourglass for idle
- Smart message: uses Claude's message if available, falls back to sensible defaults
- Cooldown: suppresses duplicate pings within 10 seconds (configurable)
- Project name prefix: optionally prepend
[project-name](setSHOW_PROJECT=true)
Sends a notification with Approve/Reject action buttons. When tapped:
- The button publishes a session-tagged response (
allow:<session_id>) to a response topic - The script polls that topic, filtering for its own session ID
- Claude proceeds or blocks based on the response
Claude Code (PreToolUse)
→ ntfy_approve.sh sends notification with action buttons
→ You tap Approve or Reject on your phone
→ Button publishes "allow:<session_id>" to response topic
→ Script filters by session ID, returns decision to Claude Code
- Multi-session safe: each approval is tagged with the session ID, so concurrent sessions won't cross-talk
- Timeout: auto-denies after 120 seconds (configurable)
- No server needed: uses ntfy topics for both directions
| Variable | Script | Default | Description |
|---|---|---|---|
NTFY_TOPIC |
both | — | Your ntfy topic URL |
NTFY_RESPONSE_TOPIC |
approve | — | Topic for receiving button responses |
COOLDOWN_SECS |
notify | 10 |
Minimum seconds between notifications |
SHOW_PROJECT |
notify | false |
Prefix messages with [project-name] |
TIMEOUT_SECS |
approve | 120 |
Seconds to wait before auto-deny |
POLL_INTERVAL |
approve | 2 |
Seconds between response polls |
ntfy.sh topics are public by default — anyone who knows your topic name can send/receive messages. Use a long, random topic name (e.g., claude-notify-a8f3x9k2m7). For production use, consider self-hosting ntfy or using access tokens.