Productivity

Claude Code Stop Hook: Get a WhatsApp Message When It Finishes

Copy one shell script and one settings entry, and Claude Code sends a WhatsApp message to your own number each time it finishes a turn. The script and its request were tested against a local mock server.

Daniel Roth5 min read

Claude Code Stop Hook: Get a WhatsApp Message When It Finishes
On this page

Short answer: register a Stop hook in your Claude Code settings that runs a script, and have the script POST one text message to https://api.blueticks.co/v1/messages/<your chat id>. Claude Code then messages your phone every time it finishes a turn.

This page is the working example. For the setup through MCP, read Connect Claude Code to WhatsApp. For the wider picture (approvals, CI, what the connection needs while you are away), read Claude Code on WhatsApp.

What you need

  • A Blueticks account with your WhatsApp number connected, and a bt_live_ key from the Blueticks API page. Blueticks shows the key once.
  • jq and curl on your machine.
  • Your own WhatsApp chat id, for example 15551234567@c.us (your number, then @c.us).

Step 1: the script

Save this as ~/.claude/hooks/whatsapp-done.sh and run chmod +x on it.

Bash
#!/usr/bin/env bash
# Stop hook: send one WhatsApp message to your own number when Claude Code finishes a turn.
# Needs jq, curl and two environment variables:
#   BLUETICKS_API_KEY  your bt_live_ key
#   BLUETICKS_TO       your own chat id, for example 15551234567@c.us
KEY="${BLUETICKS_API_KEY:-}"
TO="${BLUETICKS_TO:-}"
[ -n "$KEY" ] && [ -n "$TO" ] || exit 0   # not configured: do nothing
body=$(jq '{
  type: "text",
  text: ("Claude Code finished in " + ((.cwd // "your project") | split("/") | last) + ": "
        + ((.last_assistant_message // "Finished.") | .[0:300]))
}') || exit 0
curl -sS --max-time 10 -X POST \
  "${BLUETICKS_API_URL:-https://api.blueticks.co}/v1/messages/${TO}" \
  -H "Authorization: Bearer ${KEY}" \
  -H "Content-Type: application/json" \
  -d "$body" > /dev/null || true
exit 0

What it does, line by line:

  • Claude Code passes the hook a JSON object on stdin. The script reads cwd (to name the project) and last_assistant_message (Claude's final text), per the Claude Code hooks reference. It keeps the first 300 characters.
  • The request is POST /v1/messages/{chatId} with a bearer key. Per the Blueticks OpenAPI spec, it sends immediately to the chat in the path, and the key needs the messages:write scope.
  • It exits 0 in every path: when either variable is unset it does nothing, and a failed or unreachable request is ignored. The script does not use set -u, which would make bash exit 1 on an unset variable. A failed send never interrupts Claude Code. The hooks reference says exit code 2 on a Stop hook keeps Claude working, which you do not want here.

Step 2: register the hook

Add this to ~/.claude/settings.json (all projects) or .claude/settings.json (one project):

JSON
{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "~/.claude/hooks/whatsapp-done.sh" }
        ]
      }
    ]
  }
}

Stop takes no matcher; the hooks reference says it always fires. Export your key and number where Claude Code can see them, for example in your shell profile:

Bash
export BLUETICKS_API_KEY="bt_live_your_key_here"
export BLUETICKS_TO="15551234567@c.us"

Treat the key like a password and keep it out of source control, per the authentication docs.

Step 3: check it

Start Claude Code, ask for something short, and wait for the turn to end. A WhatsApp message from your own number to your own number should arrive. If nothing arrives, run the script by hand with a sample payload:

Bash
echo '{"cwd":"/home/me/my-app","last_assistant_message":"Tests pass."}' | ~/.claude/hooks/whatsapp-done.sh

What was tested, and what was not

I ran this script against a local mock server that records requests. It sent POST /v1/messages/15551234567@c.us with Authorization: Bearer <key>, Content-Type: application/json, and a body of {"type":"text","text":"Claude Code finished in my-app: Tests pass."}. A quote and a newline in the message survived as valid JSON, an input longer than 300 characters was cut, and a missing field fell back to the default text. The script exited 0 when the server was unreachable, and exited 0 without sending anything when BLUETICKS_API_KEY or BLUETICKS_TO was unset or empty.

I did not send a live WhatsApp message for this page, so delivery to a real phone is not covered by that test.

Limits to know about

  • Plan limits. The hosted MCP page says the free plan allows 5 requests per 6 hours, shared with the API, and paid plans have no request limit. A hook that fires on every turn can use up the free allowance. See the hosted MCP page.
  • The connection must be up. On Pro the connection runs in the cloud; on Basic and Standard it runs in your browser, so WhatsApp Web has to stay open. See Claude Code on WhatsApp.
  • It sends part of Claude's last reply. The message includes up to 300 characters of last_assistant_message. Remove that part of the script if your replies can contain anything you do not want on your phone.
  • Your own number only. The example messages you. WhatsApp's rules apply to every message sent from your number, and consent is yours to collect if you ever point it at someone else.

Add an alert for when Claude is waiting on you

The hooks reference documents a Notification event with a permission_prompt matcher, which fires when Claude needs you to approve a tool use and the prompt has waited about six seconds. You can register a script under it with "matcher": "permission_prompt". I did not test this script under Notification, and I have not checked which fields that event passes on stdin, so adapt the message text before relying on it.

FAQ

Does a Stop hook fire when Claude is interrupted?

No. The hooks reference says a Stop hook does not run if the stoppage was caused by a user interrupt.

Can the hook also wait for my reply?

Sending is one request. Reading a reply and acting on it is a separate pattern; see human-in-the-loop WhatsApp approvals.

Where is the key shown?

The Blueticks API page, once, when you create it.

Try it on your own number. Create a key and paste the script above, or start free at blueticks.co/signup.

Share this article

The Dispatch, every week.

One sharp WhatsApp growth tactic in your inbox each week. Joined by 238,000+ founders, marketers and support leads.

Free forever. No spam, unsubscribe in one click.

Also on TikTok: @blueticksagents