Ping

Claude Code Integration

Integrate Ping with Claude Code to get push notifications when Claude finishes tasks or needs approval for deploy commands.


Use Cases

  • Long-running tasks - Get notified when Claude finishes a big refactor
  • Background agents - Fire off a task and get pinged when it's done
  • Deploy approvals - Approve deployments from your phone before they run
  • Security alerts - Get notified when Claude runs potentially risky commands

Quick Setup

  1. Create a channel for Claude Code notifications in the Ping app
  2. Copy your webhook token
  3. Add to your project's .claude/settings.json:
JSON
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "export PING_WEBHOOK_TOKEN=YOUR_TOKEN && python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/deploy-approval.py\"",
            "timeout": 310
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/ping-notify.py\"",
            "timeout": 10
          }
        ]
      }
    ]
  }
}
  1. Copy the hook scripts to your .claude/hooks/ directory (available in the Ping repository)

Deploy Approval Flow

When enabled, the deploy approval hook:

  1. Detects deploy commands (git push, railway up, vercel deploy, etc.)
  2. Sends a notification to your phone with Approve/Reject buttons
  3. Waits up to 5 minutes for your response
  4. If approved: runs the command
  5. If rejected: blocks the command

This uses Ping's callback polling API - no external server or ngrok required.

Sending Interactive Notifications

To send approve/reject buttons (or any interactive control) from a hook, POST an actions array to the webhook endpoint. Buttons use a key (the identifier returned in the result); only url actions use value (the link to open). This is the most common point of confusion — see the full schema in Interactive Actions.

JSON
{
  "title": "Deploy to production?",
  "body": "git push origin main",
  "priority": "high",
  "actions": [
    {"type": "button", "label": "Approve", "key": "approve", "style": "primary"},
    {"type": "button", "label": "Reject", "key": "reject", "style": "destructive"}
  ]
}

Preview

Deploy to production?

just now
git push origin main

Reading the response — two ways. The polling flow (what deploy-approval.py uses, no server required) sends the payload above without a callback_url, takes the message_id from the /v1/send response, and polls GET /v1/callback/{token}/{message_id} until the tapped action comes back. Alternatively, add a callback_url pointing at your own HTTPS endpoint and Ping will POST the result there instead — don't point it at Ping's own /v1/callback route, which is the read-only polling endpoint, not a sink.

The deploy-approval.py hook above already builds the polling payload for you; reach for the raw schema only when you want custom controls (text input, selects, toggles).

Available Hooks

HookEventDescription
ping-notify.pyStopNotification when Claude finishes working
ping-notify.pySessionEndNotification when session terminates
ping-notify.pyNotificationAlert when Claude needs input
deploy-approval.pyPreToolUseSelf-contained deploy approval (polls Ping for response)

Minimal Completion Hook

For simple "Claude finished" notifications:

#!/usr/bin/env python3
import os
import sys
import json
import urllib.request

def send_notification():
    token = os.environ.get('PING_WEBHOOK_TOKEN')
    if not token:
        return

    payload = json.dumps({
        'title': 'Claude Finished',
        'body': 'Claude Code completed working on your task'
    }).encode()

    req = urllib.request.Request(
        f'https://ping-api-production.up.railway.app/v1/send/{token}',
        data=payload,
        headers={'Content-Type': 'application/json'}
    )

    try:
        urllib.request.urlopen(req, timeout=5)
    except Exception:
        pass

if __name__ == '__main__':
    send_notification()

For detailed documentation, see the Claude Code Hooks Guide in the Ping repository.