Skip to content
Productivity
Hook

Hooks

What agent-reachout runs automatically, and when. A hook is a command Claude Code fires at a fixed moment, without you asking for it.

From plugin
agent-reachout
542 hooks
Install
> /plugin marketplace add vibe-with-me-tools/agent-reachout
> /plugin install agent-reachout@agent-reachout

Ships with agent-reachout. Installing the plugin gets these hooks.

What fires, and when

Notification

  • Matches*${CLAUDE_PLUGIN_ROOT}/hooks/send-telegram.sh

PermissionRequest

  • Matches*${CLAUDE_PLUGIN_ROOT}/hooks/send-telegram.sh
Read hooks/hooks.json

Where it lives

  • hooks/send-telegram.shRunsGitHub
    Read the script
    #!/usr/bin/env bash
    set -euo pipefail
    
    if [ -z "${AGENT_REACHOUT_TELEGRAM_BOT_TOKEN:-}" ] || [ -z "${AGENT_REACHOUT_TELEGRAM_CHAT_ID:-}" ]; then
      echo "Missing AGENT_REACHOUT_TELEGRAM_BOT_TOKEN or AGENT_REACHOUT_TELEGRAM_CHAT_ID" >&2
      exit 0
    fi
    
    payload=$(cat)
    
    # Debounce Stop events β€” only send if a tool was used since last Stop
    # This prevents spammy "finished" messages after every conversational reply
    DEBOUNCE_FILE="/tmp/agent-reachout-last-stop"
    TOOL_FLAG="/tmp/agent-reachout-tool-used"
    event_name=$(echo "$payload" | python3 -c 'import json,sys; print(json.load(sys.stdin).get("hook_event_name",""))' 2>/dev/null || echo "")
    
    # Track when tools are used (Notification/PermissionRequest indicate active work)
    if [ "$event_name" = "Notification" ] || [ "$event_name" = "PermissionRequest" ]; then
      touch "$TOOL_FLAG"
    fi
    
    if [ "$event_name" = "Stop" ]; then
      # Only notify if tools were used since last Stop
      if [ ! -f "$TOOL_FLAG" ]; then
        exit 0
      fi
      rm -f "$TOOL_FLAG"
      # Also debounce rapid successive Stops (within 10s)
      now=$(date +%s)
      if [ -f "$DEBOUNCE_FILE" ]; then
        last_stop=$(cat "$DEBOUNCE_FILE" 2>/dev/null || echo 0)
        elapsed=$((now - last_stop))
        if [ "$elapsed" -lt 10 ]; then
          exit 0
        fi
      fi
      echo "$now" > "$DEBOUNCE_FILE"
    fi
    
    message=$(echo "$payload" | python3 -c '
    import json
    import sys
    from datetime import datetime
    
    payload = json.load(sys.stdin)
    event = payload.get("hook_event_name", "Unknown")
    
    if event == "Notification":
        notification_type = payload.get("notification_type", "")
        title = payload.get("title", "")
        message = payload.get("message", "")
        # Build a clean, informative notification
        lines = []
        if title:
            lines.append(f"πŸ”” {title}")
        elif notification_type:
            lines.append(f"πŸ”” Claude Code: {notification_type}")
        else:
            lines.append("πŸ”” Claude Code: Notification")
        if message:
            # Truncate long messages to keep Telegram tidy
            msg = message if len(message) <= 500 else message[:497] + "..."
            lines.append(msg)
        print("\n".join(lines))
    
    elif event == "PermissionRequest":
        tool_name = payload.get("tool_name", "unknown tool")
        tool_input = payload.get("tool_input", {})
        lines = [f"⚠️ Claude Code needs permission: {tool_name}"]
        if isinstance(tool_input, dict):
            for key in ("command", "file_path", "pattern", "url", "query", "message"):
                if key in tool_input:
                    detail = str(tool_input[key])
                    if len(detail) > 200:
                        detail = detail[:197] + "..."
                    lines.append(f"  {key}: {detail}")
                    break
        print("\n".join(lines))
    
    elif event == "Stop":
        reason = payload.get("stop_reason") or payload.get("reason") or ""
        ts = datetime.now().strftime("%H:%M")
        if reason:
            print(f"βœ… Claude Code finished at {ts}\nReason: {reason}")
        else:
            print(f"βœ… Claude Code finished at {ts}")
    
    else:
        print(f"Claude Code: {event}")
    ')
    
    curl -sS -X POST "https://api.telegram.org/bot${AGENT_REACHOUT_TELEGRAM_BOT_TOKEN}/sendMessage" \
      --data-urlencode "chat_id=${AGENT_REACHOUT_TELEGRAM_CHAT_ID}" \
      --data-urlencode "text=${message}" \
      > /dev/null
    

Read the script before you install anything that runs on your machine. This is the one part of a plugin that acts without being asked.

Ships withagent-reachout

Let your Claude Code message you on Telegram when it needs decisions or finishes work, even when you’re away from your desk. Claude Code β†’ Agent Reachout β†’ Telegram β†’ Human reply β†’ Agent continues

Get the whole plugin
Stats
54
Stars
10
Forks
Maintained
Maintenance
TypeScript
Language
MIT
License
5mo ago
Last commit
8mo ago
Created

Repo: vibe-with-me-tools/agent-reachout