Claude Code の hooks でファイル編集のたびに lint と format を自動実行する
Claude Code の hooks 機能を使って、ファイル編集後に Prettier や ESLint、ruff を自動実行する設定を解説します。PostToolUse の書き方、stdin から編集ファイルを取り出す方法、失敗時に Claude へ修正を促す方法を紹介します。
目次
「フォーマットを揃えてからコミットして」と CLAUDE.md に書いても、Claude が実行を忘れることがあります。指示は確率的に守られるものだからです。この問題を確実に解決するのが hooks です。hooks は Claude の判断を介さず、Claude Code 本体が決められたタイミングでシェルコマンドを実行する仕組みです。
この記事では、Claude がファイルを編集するたびに Prettier や ESLint、Python なら ruff を自動実行し、失敗したら Claude 自身に修正させる設定を作ります。
KEY POINT
この記事で分かること
- hooks のイベント種類と設定ファイルの書き方
- 編集されたファイルだけを対象に lint / format を走らせる方法
- lint 失敗を Claude にフィードバックして自動修正させる方法
hooks の仕組み
hooks は settings.json の hooks キーに書きます。イベントごとに「どのツールに反応するか(matcher)」と「実行するコマンド」を指定します。
| イベント | 発火タイミング | 主な用途 |
|---|---|---|
PreToolUse | ツール実行前 | 危険なコマンドのブロック、事前チェック |
PostToolUse | ツール実行後 | lint / format の自動実行、テスト |
UserPromptSubmit | ユーザーが指示を送信したとき | 指示への情報付加、検証 |
Notification | Claude が確認や通知を出すとき | デスクトップ通知、Slack 連携 |
Stop | Claude が応答を終えたとき | 最終チェック、完了通知 |
SubagentStop | サブエージェントが終了したとき | サブエージェントの成果物検証 |
SessionStart | セッション開始時 | 環境変数の読み込み、コンテキストの注入 |
PreCompact | コンテキスト圧縮の直前 | 重要情報の退避 |
hook コマンドには、標準入力(stdin)で JSON が渡されます。PostToolUse の場合、tool_name と tool_input(編集なら file_path を含む)が入っています。
設定例:編集後に Prettier と ESLint を実行する
.claude/settings.json に次のように書きます。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|MultiEdit",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/format.sh"
}
]
}
]
}
}
matcher はツール名に対する正規表現です。ファイルを変更するツールは Edit、Write、MultiEdit なので、この 3 つを | でつなぎます。
次に、.claude/hooks/format.sh を作ります。stdin の JSON から編集されたファイルのパスを取り出し、対象のファイルだけをフォーマットします。
#!/usr/bin/env bash
set -euo pipefail
# stdin の JSON から file_path を取り出す(jq が必要)
file=$(jq -r '.tool_input.file_path // empty')
[ -z "$file" ] && exit 0
[ -f "$file" ] || exit 0
case "$file" in
*.ts|*.tsx|*.js|*.jsx|*.json|*.css|*.md)
npx prettier --write "$file" >/dev/null
;;
esac
case "$file" in
*.ts|*.tsx|*.js|*.jsx)
if ! npx eslint "$file"; then
echo "ESLint がエラーを報告しました。上記の指摘を修正してください: $file" >&2
exit 2
fi
;;
esac
exit 0
chmod +x .claude/hooks/format.sh
用語解説
終了コードの意味: 0 は成功。2 は「ブロック」で、標準エラー出力の内容が Claude に渡され、Claude は指摘に従って修正を試みます。それ以外の終了コードは処理を止めずにユーザーへ警告を表示します。
Python プロジェクトの場合(ruff)
#!/usr/bin/env bash
set -euo pipefail
file=$(jq -r '.tool_input.file_path // empty')
[[ "$file" == *.py ]] || exit 0
[ -f "$file" ] || exit 0
ruff format "$file" >/dev/null
if ! ruff check "$file"; then
echo "ruff の指摘を修正してください: $file" >&2
exit 2
fi
ruff check --fix を使えば自動修正できる項目は hook 側で直せます。その場合、残ったエラーだけが Claude に渡ります。
動作確認
/hooksコマンドで登録された hook が表示されることを確認します。- Claude に「
src/example.tsにわざとフォーマットの崩れた関数を追加して」と指示します。 - 編集直後に Prettier が走り、ファイルが整形されていれば成功です。
- ESLint エラーになるコード(未使用変数など)を書かせ、Claude が指摘を受けて修正するか確認します。
hook の実行ログは、Claude Code を claude --debug で起動すると詳細が見られます。
運用上の注意
hook は毎回実行される
PostToolUse は編集のたびに走ります。プロジェクト全体の lint(eslint .)を書くと、1 回の編集ごとに数十秒かかることがあります。必ず「編集されたファイルだけ」を対象にしてください。
- hook 内で Claude の編集を上書きする場合は慎重に: フォーマッタは安全ですが、コード生成やファイル移動を hook で行うと Claude の認識とファイルの実体がずれます。
- jq のインストールが必要: macOS は
brew install jq、Ubuntu はapt install jq。jq を避けたい場合は Python でパースする方法もあります。 - チームで共有する場合: hook スクリプトはリポジトリに入れ、
settings.json(共有)から相対パスで呼びます。個人環境だけの hook はsettings.local.jsonに書きます。
発展:PreToolUse で危険なコマンドを止める
同じ仕組みで、実行前に危険なコマンドを検査できます。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/guard.sh"
}
]
}
]
}
}
#!/usr/bin/env bash
cmd=$(jq -r '.tool_input.command // empty')
if echo "$cmd" | grep -Eq 'rm -rf /|git push --force|DROP TABLE'; then
echo "このコマンドは hooks により禁止されています: $cmd" >&2
exit 2
fi
exit 0
permissions の deny と組み合わせると二重の保護になります。deny の書き方は settings.json で permissions を設計する を参照してください。
まとめ
- hooks は Claude の判断を介さず確実に実行されるため、lint / format の自動化に向いている
PostToolUse+matcher: "Edit|Write|MultiEdit"で編集後に走らせる- stdin の JSON から
tool_input.file_pathを取り出し、編集されたファイルだけを対象にする - 終了コード 2 と標準エラー出力で、Claude に修正を促せる
よくある質問
- hooks は Claude が勝手に無視することはありますか?
- ありません。hooks は Claude の判断ではなく Claude Code 本体が決定的に実行するため、指示の聞き漏らしが起きません。
- hooks が失敗したら Claude に伝わりますか?
- 終了コード 2 で終了すると、標準エラー出力の内容が Claude にフィードバックされ、修正を試みます。終了コード 0 なら成功、それ以外はユーザーへの警告として表示されます。
- hooks の設定はどこに書きますか?
- settings.json の hooks キーです。ユーザー・プロジェクト・ローカルの各スコープに書けます。/hooks コマンドから対話的に追加することもできます。
参考にした一次情報
この記事は公式ドキュメントを基に AI が下書きを作成し、運営者が内容を確認して公開しています。誤りを見つけた場合はお問い合わせからお知らせください。