創刊準備号 · 2026年秋English · RSS
AgentKoji

UserPromptSubmitの使い方

UserPromptSubmit hookは既定で30秒で打ち切られます。文脈を足すhookと、APIキーを止めるhookを載せます。

要点(TL;DR)

  • UserPromptSubmit は、プロンプトを送ったとき Claude が処理する前に動く hook で、文脈を足したりプロンプトを止めたりできます。
  • 自分で打ったときだけでなく、予約タスクやバックグラウンドのサブエージェントの結果、別のセッションからのメッセージでも動きます。
  • decision: "block" で止めても、送った文は手元のセッションの記録に残ることがあります。防げるのは鍵がモデルに届くことです。

UserPromptSubmit は、プロンプトを送ったとき、Claude が処理する前に動く hook です。プロンプトに文脈を足したり、プロンプトそのものを Claude に届く前に止めたりできます。この記事では、ダミーの todo アプリを例に、今のブランチと日付を足す hook と、API キーらしき文字列を含むプロンプトを止める hook の2つを載せます。編集部の検証環境(macOS、Claude Code 2.1.309、jq 1.7.1、2026年10月23日)で、スクリプトにダミーの JSON を流して確かめました。実際のセッションの中で発火するところは見ていません(未実行)。hook を使う考え方はClaude Code hooks実践にまとめています。

いつ動き、何が渡されるか

UserPromptSubmit は、自分で打ったプロンプトのときだけ動くわけではありません。次のときにも動きます。

何かを止める hook を書く前に、これを頭に入れておきます。

入力の JSON には、共通のフィールドに加えて、送った文が prompt として入ります。貼り付けた文が [Pasted text #N] にまとめられていても、hook には展開された中身が届きます。セッションに独自の名前が付いていれば session_title も入ります。/deploy staging のように skill やコマンドを打った場合、hook が受け取るのは打ったとおりの1行で、展開された skill の中身ではありません。

{
  "hook_event_name": "UserPromptSubmit",
  "prompt": "todo に期限を付けたい"
}

出典:https://code.claude.com/docs/en/hooks 、2026-10-23確認

例1:プロンプトに文脈を足す

exit 0 で終わると、stdout に出した普通の文が Claude の文脈に足されます。JSON の additionalContext でも同じです。どちらも会話の画面には出ず、hook の名前で始まる system reminder として Claude に届きます。

#!/usr/bin/env bash
# .claude/hooks/prompt-context.sh  (UserPromptSubmit)
cd "${CLAUDE_PROJECT_DIR:?}" || exit 0
branch=$(git branch --show-current 2>/dev/null)
changed=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
echo "Current branch: ${branch:-unknown}. Uncommitted files: ${changed}. Today: $(date +%F)."
exit 0

feature/due-dates のブランチにしたダミーのリポジトリで流した結果です。

$ echo '{"hook_event_name":"UserPromptSubmit","prompt":"todo に期限を付けたい"}' | .claude/hooks/prompt-context.sh
Current branch: feature/due-dates. Uncommitted files: 4. Today: 2026-10-23.
exit=0

time で3回測ると、0.03〜0.04 秒でした。この1行は、セッションの間ずっと、プロンプトのたびに足されます。Claude が自分では調べられず、たいていのターンで要るものだけを足します。何の役にも立たない1行でも、毎回コンテキストを使います。

例2:API キーらしき文字列を止める

止めるときは、decision: "block" の JSON を出します。reason は人に見せる文で、Claude の文脈には入りません。

#!/usr/bin/env bash
# .claude/hooks/block-secrets-in-prompt.sh  (UserPromptSubmit)
prompt=$(jq -r '.prompt // ""')
if printf '%s' "$prompt" | grep -Eq 'sk-ant-[A-Za-z0-9_-]{10,}|AKIA[0-9A-Z]{16}|ghp_[A-Za-z0-9]{30,}'; then
  jq -n '{decision: "block",
          reason: "プロンプトに API キーらしき文字列があります。消してから、環境変数で渡してください。",
          hookSpecificOutput: {hookEventName: "UserPromptSubmit", suppressOriginalPrompt: true}}'
fi
exit 0

ダミーの鍵(sk-ant-api03-DUMMY...)を入れたプロンプトを流した結果です。

{
  "decision": "block",
  "reason": "プロンプトに API キーらしき文字列があります。消してから、環境変数で渡してください。",
  "hookSpecificOutput": {
    "hookEventName": "UserPromptSubmit",
    "suppressOriginalPrompt": true
  }
}
exit=0

「todo に期限を付けたい」では、何も出さずに exit 0 でした。

既定では、止めたときのメッセージの最後に Original prompt: と元の文が付きます。hookSpecificOutput の中で suppressOriginalPrompt: true にすると、これを省けます。

これで鍵がディスクに残らなくなるわけではありません。 公式によると、suppressOriginalPrompt が変えるのは止めたときのメッセージだけで、送った文はセッションの記録やプロンプトの履歴といった手元のファイルに残ることがあります。hook が防ぐのは、鍵がモデルに届くことです。貼ってしまった鍵は作り直します。考え方はClaude Codeに秘密を渡さないにあります。

出典:https://code.claude.com/docs/en/hooks 、2026-10-23確認

返し方の一覧

hook の出力効果
exit 0、普通の文を stdout に出すその文が Claude の文脈に足される
exit 0、JSON の additionalContextその文字列が Claude の文脈に足される
JSON の decision: "block" と reasonプロンプトが Claude に届かない。reason は人にだけ見える
hookSpecificOutput.suppressOriginalPrompt: true止めたときのメッセージから元の文を省く
hookSpecificOutput.sessionTitleセッションの名前を付ける
exit 2 と stderrプロンプトを止める。stderr は人に見せ、文脈には入らない

出典:https://code.claude.com/docs/en/hooks 、2026-10-23確認

settings.json と注意点

UserPromptSubmit は matcher に対応していないので、matcher は書きません。

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "hooks": [
          { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/prompt-context.sh" },
          { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-secrets-in-prompt.sh" }
        ]
      }
    ]
  }
}

この設定は jq を通り、claude doctor でも不正な設定は出ませんでした。

出典:https://code.claude.com/docs/en/hooks 、2026-10-23確認

ネットワークに出る処理やテストの実行は、ここに入れません。編集のあとにテストを回すなら PostToolUse が向いています。書き方はPostToolUseで整形とテストを自動化にあります。hook が動かないときの確かめ方はhooksが動かないときの確認にまとめています。

まとめ

関連記事