nikkie-ftnextの日記

イベントレポートや読書メモを発信

Claude Code のフックを Python スクリプトで書ける cchooks で hatch fmt を実行するフックを書く

はじめに

七尾百合子さん、お誕生日 225日目 おめでとうございます! nikkieです。

シェルスクリプトではなく Python スクリプトで Claude Code のフックを書けると知り、手を動かしました。

目次

cchooks

Claude Code のフックの偉大さを実感した nikkie 氏。
積ん読の「Claude CodeのHooksは設定したほうがいい - じゃあ、おうちで学べる」を読んでいたところ、awesomeの存在を知ります(「なぜHooksを設定したほうがいいのか」参照)。

awesome-claude-code の Hooks を見ていたところ、Python ライブラリの存在に気づきました。

https://pypi.org/project/cchooks/

A lightweight Python SDK with a clean API and good documentation

cchooks で書いた Python スクリプトによるフック

hatch fmtと同様のフックを実装しました。

ディレクトリ構成

.claude/
├── hooks/
│   └── format_python.py
└── settings.local.json

settings.local.json

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/format_python.py"
          }
        ]
      }
    ]
  }
}

format_python.pychmod u+xしています)

このフックを設定した後の Claude Code の様子です(動作確認のため think off です)
https://gist.github.com/ftnext/490250598c37698f5f1c6581945d2430
Hatch のメッセージの修正漏れがありましたが、このフックは通るまで逃さないので最終的にはちゃんと直せました!

実装メモ

PostToolUse の例を参考にしました。
https://github.com/GowayLee/cchooks/tree/v0.1.4?tab=readme-ov-file#posttooluse-auto-formatter

気づき

cchooks.create_context()で Claude Code がフックに入力した JSON を受け取ります。

c.tool_input.get("file_path", "").endswith(".py")Trueが返ったら、c.tool_inputにはfile_pathというキーがあることになるので、c.tool_input["file_path"]とできる!

subprocess.run()hatch fmtを実行。
整形が必要な場合はcchooks.exit_block()で Hatch の出力を Claude Code に見せています。
整形の必要がない場合はcchooks.exit_success()で終了します。
ref: https://github.com/GowayLee/cchooks/tree/v0.1.4?tab=readme-ov-file#direct-control

工夫

一番の工夫はシバンのuv run
cchooks 自体が inline script metadata とめちゃめちゃ相性がいいと感じました。

Hatch をどうインストールするかについては(炎上覚悟で)uvxでやってみました。

例にあるPostToolUseContextかのチェックは(JSONファイルでの設定からそうに決まっているので)省略。
また、tool_nameのチェックも同様の理由で省略しました。

終わりに

cchooks を使って Python スクリプトで Claude Code のフックを書きました。
cchooks は inline script metadata と非常に相性がいいと思いますので、cchooks を使う際は一緒の使用をぜひご検討ください!(本家リポジトリに布教しに行こうかな)