Skip to content

Instantly share code, notes, and snippets.

@kazuph
Created February 24, 2026 04:26
Show Gist options
  • Select an option

  • Save kazuph/8ad00d159ed86db62c4f80668cb40a27 to your computer and use it in GitHub Desktop.

Select an option

Save kazuph/8ad00d159ed86db62c4f80668cb40a27 to your computer and use it in GitHub Desktop.
Claude Code Hooks → Discord通知(SessionStart 2回発火バグ対策込み)

Claude Code Hooks → Discord通知

Claude Codeの動作状況をDiscord Webhookで通知する設定。

概要

  • SessionStart: セッション開始時に通知
  • Stop: 応答完了時に、最後の応答内容をDiscordに送信

ハマりポイント・ノウハウ

1. Stop hookで使えるフィールド

transcript_summary は存在しない。使えるのは以下:

フィールド 説明
last_assistant_message 最後の応答テキスト
stop_hook_active true の場合は hook 起因の停止(無限ループ防止に必須)
session_id セッションID
transcript_path トランスクリプトのパス

2. SessionStart が2回発火するバグ

Claude Code (2025年2月時点) では、SessionStart hookが約0.3秒差で2回発火する。 PIDも異なるため、2つの別プロセスとして実行される。

対策: ロックファイルで5秒以内の重複実行を防止する。

3. Termux環境では /tmp/ が使えない

Termux (Android) では /tmp/ への書き込みが Permission denied になる。 代わりに /data/data/com.termux/files/usr/tmp/ を使うこと。

設定ファイル

~/.claude/settings.json

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/discord-start.sh"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/discord-stop.sh"
          }
        ]
      }
    ]
  }
}

~/.claude/hooks/discord-start.sh

#!/bin/bash
WEBHOOK_URL="YOUR_DISCORD_WEBHOOK_URL"
TMPDIR="/data/data/com.termux/files/usr/tmp"  # Termux環境用。通常環境は /tmp でOK
LOCKFILE="$TMPDIR/session_start.lock"

# 5秒以内の重複実行を防止(SessionStartが2回発火するバグ対策)
if [ -f "$LOCKFILE" ]; then
  LOCK_AGE=$(( $(date +%s) - $(stat -c %Y "$LOCKFILE" 2>/dev/null || echo 0) ))
  if [ "$LOCK_AGE" -lt 5 ]; then
    exit 0
  fi
fi
touch "$LOCKFILE"

T=$(date '+%H:%M:%S')
PAYLOAD=$(jq -n --arg content "[$T] セッション開始" '{"username":"cc","content":$content}')

curl -sf -X POST "$WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -d "$PAYLOAD" &>/dev/null &

~/.claude/hooks/discord-stop.sh

#!/bin/bash
WEBHOOK_URL="YOUR_DISCORD_WEBHOOK_URL"

# stdinからJSONを読み取り
INPUT=$(cat)

# stop_hook_activeがtrueなら何もしない(無限ループ防止)
ACTIVE=$(echo "$INPUT" | jq -r '.stop_hook_active // false' 2>/dev/null)
if [ "$ACTIVE" = "true" ]; then
  exit 0
fi

# 最後の応答テキストを取得
MSG=$(echo "$INPUT" | jq -r '.last_assistant_message // "completed"' 2>/dev/null)

# 先頭に時刻を付与
TIMESTAMP=$(date '+%H:%M:%S')
MSG="[${TIMESTAMP}] ${MSG}"

# 2000文字制限(Discord制限)
MSG="${MSG:0:1900}"

# Discordに送信
PAYLOAD=$(jq -n --arg content "$MSG" '{"username":"cc","content":$content}')

curl -sf -X POST "$WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -d "$PAYLOAD" &>/dev/null &

依存

  • jq - JSON処理
  • curl - HTTP送信
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment