はじめに
Claude Code で開発作業を行う際、「あの時どんな指示をして、どう解決したか」を後から振り返りたいことがあります。この記事では、Claude Code のフック機能を使って、ユーザーの指示と Claude の応答を Slack にリアルタイムで記録する方法を紹介します。
こんな場面で役立ちます:
- チームメンバーと AI 活用事例を共有したい
- 作業ログを時系列で確認したい
- Claude Code での問題解決プロセスをドキュメント化したい
Claude Code のフック機能とは
Claude Code には、特定のイベント発生時にカスタムスクリプトを実行できる「フック機能」があります。フックは.claude/settings.local.jsonや.claude/settings.json等で設定し、以下のようなイベントに対応できます:
- UserPromptSubmit - ユーザーがプロンプトを送信したとき
- Stop - Claude の応答が完了したとき
- その他、ツールの使用前後、通知、セッション開始/終了などのイベント
これらのフックを活用することで、Claude Code との対話を外部サービスと連携させることができます。
実装の全体像
この実装では、以下の 2 つのタイミングで Slack に投稿を行います:
-
ユーザー指示送信時 (
UserPromptSubmitイベント)- ユーザーが入力したプロンプトを取得して Slack に投稿
-
Claude 応答完了時 (
Stopイベント)- トランスクリプトファイルから最新の Claude 応答を抽出
ディレクトリ構成
your-project/
├── .claude/
│ ├── hooks/
│ │ ├── user_prompt_submit.sh
│ │ └── assistant_response_complete.sh
│ └── settings.local.json
└── .env
セットアップ手順
1. 前提条件
- Claude Code がインストールされていること
- Slack Incoming Webhook が設定されていること (Slack の説明ページ Sending messages using incoming webhooks などを参照してください)
-
jqコマンドがインストールされていること(JSON パース用)
動作確認済み環境
- macOS Tahoe (26.0.1)
2. リポジトリからスクリプトを取得
実装の詳細とスクリプトは、以下の GitHub リポジトリで公開しています:
リポジトリ: https://github.com/ddpi/PublicArticles/tree/main/claude_code/hooks_slack_integration
リポジトリには以下が含まれています:
-
user_prompt_submit.sh- ユーザー指示投稿スクリプト -
assistant_response_complete.sh- Claude 応答投稿スクリプト -
settings.example.json- フック設定サンプル -
README.md- 詳細なセットアップ手順とカスタマイズ方法
# プロジェクトディレクトリで実行
cd your-project
# .claudeディレクトリとhooksディレクトリを作成
mkdir -p .claude/hooks
# リポジトリからスクリプトをダウンロード
curl -o .claude/hooks/user_prompt_submit.sh \
https://raw.githubusercontent.com/ddpi/PublicArticles/main/claude_code/hooks_slack_integration/user_prompt_submit.sh
curl -o .claude/hooks/assistant_response_complete.sh \
https://raw.githubusercontent.com/ddpi/PublicArticles/main/claude_code/hooks_slack_integration/assistant_response_complete.sh
curl -o .claude/settings.example.json \
https://raw.githubusercontent.com/ddpi/PublicArticles/main/claude_code/hooks_slack_integration/settings.example.json
# 実行権限を付与
chmod +x .claude/hooks/*.sh
3. 環境変数の設定
プロジェクトルートに.envファイルを作成し、Slack Webhook URL を設定します:
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
主要な実装ポイント
1. フック設定 (settings.local.json)
{
"hooks": {
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/user_prompt_submit.sh"
}
]
}
],
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/assistant_response_complete.sh"
}
]
}
]
}
}
ポイント解説
-
$CLAUDE_PROJECT_DIR 環境変数
- プロジェクトディレクトリを動的に参照するための変数
- 異なるプロジェクト間でも同じ設定を使い回せる
-
Stop イベントの使用
- Claude Code では応答完了時に
Stopイベントが発火 -
AssistantResponseCompleteイベントは存在しないため注意
- Claude Code では応答完了時に
2. Slack へ投稿するスクリプト
Hooks に登録する 2 つのシェルスクリプトの概要は以下のとおりです。
2.1. user_prompt_submit.sh(ユーザー指示投稿)
このスクリプトは、ユーザーがプロンプトを送信した際にその内容を Slack に投稿します。
環境変数の読み込みと設定
set -euo pipefail
# .envファイルから環境変数を読み込み
if [ -f "${CLAUDE_PROJECT_DIR}/.env" ]; then
export $(grep -v '^#' "${CLAUDE_PROJECT_DIR}/.env" | grep -v '^$' | xargs)
fi
# Webhook URLが設定されていることを確認
: "${SLACK_WEBHOOK_URL:?Set SLACK_WEBHOOK_URL in your env or .env file}"
set -euo pipefailにより、エラー発生時に即座にスクリプトを終了します。SLACK_WEBHOOK_URLが未設定の場合もエラーメッセージを表示して終了します。
JSON ペイロードの処理
Claude Code はフックに対して JSON 形式でデータを渡します。これをjqコマンドでパースします:
payload="$(cat)"
session_id="$(echo "$payload" | jq -r '.session_id')"
prompt="$(echo "$payload" | jq -r '.prompt // ""')"
cwd="$(echo "$payload" | jq -r '.cwd // ""')"
メッセージの整形と Slack 投稿
# 500文字を超える場合は切り詰め
truncated_message="${display_user_message:0:500}"
if [ ${#display_user_message} -gt 500 ]; then
truncated_message="${truncated_message}..."
fi
# Slackメッセージの構築と投稿
TEXT=$(printf "💬 *ユーザ指示受信*\n\n%s" "$truncated_message")
curl -sS -X POST \
-H 'Content-type: application/json' \
--data "$(jq -Rn --arg txt "$TEXT" '{text:$txt}')" \
"$SLACK_WEBHOOK_URL" >/dev/null
2.2. assistant_response_complete.sh(Claude 応答投稿)
このスクリプトの核心は、トランスクリプトファイルから最新の Claude 応答を抽出する処理です。
トランスクリプトファイルからの応答抽出
Claude Code は各セッションの会話履歴を JSONL 形式のトランスクリプトファイルに記録しています。このファイルから最新のアシスタント応答を取り出します:
if [ -f "$transcript_path" ]; then
# 最後のアシスタント応答のUUIDを取得
last_assistant_uuid="$(tail -20 "$transcript_path" | jq -r 'select(.type == "assistant" and .message.role == "assistant") | .uuid' | tail -1)"
# そのUUIDに対応するテキストコンテンツをすべて抽出
last_assistant_text="$(tail -20 "$transcript_path" | jq -r --arg uuid "$last_assistant_uuid" 'select(.type == "assistant" and .uuid == $uuid) | .message.content[] | select(.type == "text") | .text' | paste -sd "\n" -)"
display_assistant_message="${last_assistant_text:-(応答なし)}"
この処理のポイント:
-
tail -20でファイルの最後の 20 行を取得 -
jqでtypeがassistantかつroleがassistantのエントリを抽出 - 該当する UUID のすべての
textタイプのコンテンツを結合
文字数制限とエラーハンドリング
# 15,000文字を超える場合は切り詰め
if [ ${#display_assistant_message} -gt 15000 ]; then
truncated_message="${display_assistant_message:0:15000}..."
else
truncated_message="$display_assistant_message"
fi
else
# トランスクリプトファイルが見つからない場合の代替メッセージ
TEXT=$(printf "🤖 *Claude応答完了*\n\n⚠️ *エラー:* トランスクリプトファイルが見つかりません")
fi
共通の設計パターン
両スクリプトは以下の原則に従っています:
-
エラーハンドリング:
set -euo pipefailでエラー時に即座に終了 -
環境変数の読み込み:
.envファイルから設定を動的にロード - 文字数制限: Slack API の制限を考慮した切り詰め処理
-
非ブロッキング: 常に
exit 0で終了し、Claude Code の通常動作を妨げない
完全なコードはGitHub リポジトリで公開しています。
動作イメージ
Claude Code でコマンドを実行すると、Slack に以下のような投稿が順次表示されます:
💬 ユーザ指示受信
プロジェクトのREADMEを更新してください
🤖 Claude応答完了
READMEファイルを更新しました。以下の変更を行いました:
- プロジェクト概要の追加
- インストール手順の詳細化
- ...
注意点
- 機密情報: プロンプトや応答に機密情報が含まれる可能性があるため、投稿先の Slack チャンネルのアクセス権限を適切に設定してください。.env は.gitignore に追加し、リポジトリに登録しないように注意してください。
- 文字数制限: Slack API には投稿サイズの制限があるため、長いメッセージは切り詰めています
まとめ
Claude Code のフック機能を活用することで、AI アシスタントとの対話を Slack に記録できるようになります。この記事では基本的なセットアップ方法と重要なポイントを紹介しました。
リポジトリ: https://github.com/ddpi/PublicArticles/tree/main/claude_code/hooks_slack_integration
参考リンク
この記事が役に立ったら、ぜひ「いいね」をお願いします!