Skip to content

原文(日本語訳)

フックブロッキングエラー(終了コード2)が発生した際、標準エラー出力(stderr)がユーザーに表示されなかった問題を修正しました。

原文(英語)

Fixed hook blocking errors (exit code 2) not showing stderr to the user

概要

Claude Code 2.1.39では、設定されたフック(hooks)が終了コード2でブロッキングエラーを返した際、エラーの詳細情報(標準エラー出力)がユーザーに表示されず、問題の原因を特定できなかった問題が修正されました。修正後は、フックがブロックした理由が明確に表示されるようになり、デバッグが容易になりました。

フックとは

Claude Codeのフック(hooks)は、特定のイベント(ツール呼び出し、プロンプト送信など)に応じて自動実行されるシェルコマンドです。これにより、セキュリティチェック、ログ記録、承認フローなどを実装できます。

終了コードの意味

終了コード意味動作
0成功処理を続行
1エラーエラーを表示して続行
2ブロッキング処理を中止(ブロック)

実践例

セキュリティチェックフックの例

bash
# ~/.claude/hooks/pre-bash.sh
#!/bin/bash

# 危険なコマンドをブロック
if echo "$CLAUDE_TOOL_COMMAND" | grep -qE "rm -rf|format|dd"; then
  echo "Error: Dangerous command blocked!" >&2
  echo "Attempted command: $CLAUDE_TOOL_COMMAND" >&2
  echo "Reason: This command could cause data loss" >&2
  exit 2  # ブロッキングエラー
fi

exit 0

修正前の動作

bash
claude
# > "Delete all temporary files with rm -rf /tmp/*"

# ユーザーに表示される内容:
# Error: Hook blocked the operation (exit code 2)

# 何が問題なのか、なぜブロックされたのか不明

修正後の動作

bash
claude
# > "Delete all temporary files with rm -rf /tmp/*"

# ユーザーに表示される内容:
# Error: Hook blocked the operation (exit code 2)
#
# Hook output (stderr):
# Error: Dangerous command blocked!
# Attempted command: rm -rf /tmp/*
# Reason: This command could cause data loss

# 問題の原因が明確に表示される

コード品質チェックフック

bash
# ~/.claude/hooks/pre-write.sh
#!/bin/bash

FILE_PATH="$CLAUDE_TOOL_FILE_PATH"
FILE_CONTENT="$CLAUDE_TOOL_CONTENT"

# TODOコメントの残留をチェック
if echo "$FILE_CONTENT" | grep -q "TODO\|FIXME\|HACK"; then
  echo "Error: Code quality check failed" >&2
  echo "File: $FILE_PATH" >&2
  echo "Issue: Code contains TODO/FIXME/HACK comments" >&2
  echo "Please resolve these before proceeding" >&2
  exit 2
fi

exit 0

修正後は、どのファイルのどの箇所が問題なのか、詳細が表示されます。

API使用制限チェック

bash
# ~/.claude/hooks/pre-prompt.sh
#!/bin/bash

# API使用量をチェック
USAGE=$(curl -s https://api.anthropic.com/usage)
LIMIT=1000000  # トークン上限

CURRENT=$(echo "$USAGE" | jq '.tokens_used')

if [ "$CURRENT" -gt "$LIMIT" ]; then
  echo "Error: API usage limit exceeded" >&2
  echo "Current usage: $CURRENT tokens" >&2
  echo "Limit: $LIMIT tokens" >&2
  echo "Please wait until the next billing cycle" >&2
  exit 2
fi

exit 0

コンプライアンスチェック

bash
# ~/.claude/hooks/pre-bash.sh
#!/bin/bash

# 本番環境での操作をブロック
if [ "$CLAUDE_PROJECT_ENV" = "production" ]; then
  echo "Error: Production environment detected" >&2
  echo "Direct modifications to production are not allowed" >&2
  echo "Please use the staging environment and deployment pipeline" >&2
  echo "" >&2
  echo "To override (not recommended):" >&2
  echo "  export CLAUDE_ALLOW_PROD=1" >&2
  exit 2
fi

exit 0

フック設定ファイルの例

json
// ~/.claude/settings.json
{
  "hooks": {
    "pre-bash": "~/.claude/hooks/pre-bash.sh",
    "pre-write": "~/.claude/hooks/pre-write.sh",
    "pre-prompt": "~/.claude/hooks/pre-prompt.sh",
    "post-response": "~/.claude/hooks/post-response.sh"
  }
}

デバッグのベストプラクティス

詳細なエラーメッセージの出力

bash
#!/bin/bash

# 良い例: 詳細な情報を stderr に出力
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" >&2
echo "Hook: pre-bash" >&2
echo "Error: Command validation failed" >&2
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" >&2
echo "Command: $CLAUDE_TOOL_COMMAND" >&2
echo "Reason: Contains dangerous pattern" >&2
echo "Suggestion: Use safer alternatives" >&2
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" >&2

exit 2

ログファイルへの記録

bash
#!/bin/bash

LOG_FILE="$HOME/.claude/logs/hooks.log"
TIMESTAMP=$(date -Iseconds)

# ログファイルに詳細を記録
{
  echo "[$TIMESTAMP] Hook blocked operation"
  echo "  Command: $CLAUDE_TOOL_COMMAND"
  echo "  Reason: Security policy violation"
} >> "$LOG_FILE"

# ユーザーにも表示
echo "Error: Operation blocked by security policy" >&2
echo "Details logged to: $LOG_FILE" >&2

exit 2

注意点

  • stderrへの出力: エラー情報は必ず標準エラー出力(>&2)に出力してください。標準出力に出力してもユーザーには表示されません
  • 終了コード: ブロックする場合は必ず終了コード2を使用してください
  • パフォーマンス: フックは各操作で実行されるため、重い処理は避けてください
  • デバッグモード: CLAUDE_DEBUG=1環境変数を設定すると、フックの詳細なログが表示されます

トラブルシューティング

フックが正しく動作しない場合

bash
# フックスクリプトに実行権限を付与
chmod +x ~/.claude/hooks/*.sh

# フックのテスト実行
CLAUDE_TOOL_COMMAND="test" ~/.claude/hooks/pre-bash.sh
echo "Exit code: $?"

デバッグモードの有効化

bash
# 詳細なフック情報を表示
export CLAUDE_DEBUG=1
claude

# すべてのフック実行がログに記録される

フックの一時的な無効化

bash
# すべてのフックを無効化
export CLAUDE_DISABLE_HOOKS=1
claude

# 特定のフックのみ無効化
export CLAUDE_DISABLE_PRE_BASH=1
claude

関連情報