水曜日, 7月 23, 2025
水曜日, 7月 23, 2025
- Advertisment -
ホームニューステックニュースClaude Code Hooksを使って編集したGoファイルだけ必ず自動フォーマットする

Claude Code Hooksを使って編集したGoファイルだけ必ず自動フォーマットする



Claude Codeを使ってGoのファイルを操作したあとはHooks機能を使って必ずgofmtgoimportsを実行する設定を書いてみました。

TL;DR

  • Claude Code v1.0.38で追加されたHooks機能を使って、ファイル編集後に自動的にgofmtgoimportsを実行
  • 編集されたファイルパスを利用して必要なファイルのみを処理するため高速
  • Hooks設定により必ず実行することができる
  • 自動生成コマンドなどの場合はファイルパスが取得できないため実行できなそう

設定方法は(プロジェクトごとに設定する場合).claude/settings.jsonに以下のように記述します。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path | select(endswith(\".go\"))' | xargs -r -I {} sh -c 'gofmt -w \"$1\" && goimports -w \"$1\"' _ {}"
          }
        ]
      }
    ]
  }
}

実行バージョン

macOS 15.5
$ claude -v
1.0.56 (Claude Code)

$ jq -V
jq-1.8.1

はじめに

Claude Codeを使ってGoのコードを編集していると、フォーマットが崩れたり、ファイル終端の改行が削除されたりすることがあります。CLAUDE.mdにフォーマットルールを記載しても、コンテキスト量によっては忘れられることがありました。

そこで、Claude Code v1.0.38で追加されたHooks機能を活用して、Goファイルの編集時に自動的にフォーマットを実行します。

https://docs.anthropic.com/en/docs/claude-code/hooks

Hooks設定の内容

やり方は簡単で、以下の設定をClaude Codeの設定ファイルに追加します

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path | select(endswith(\".go\"))' | xargs -r -I {} sh -c 'gofmt -w \"$1\" && goimports -w \"$1\"' _ {}"
          }
        ]
      }
    ]
  }
}

設定の解説

この設定では以下の仕組みで動作します:

  1. WriteEditMultiEditツールが実行されたあとに発火します。
  2. jqを使って編集されたファイルパスが.goで終わるものだけを抽出します。
  3. 該当ファイルに対してgofmtgoimportsを順次実行します

工夫している点

効率的なファイル処理

PostToolUseフックは編集されたファイルのパスを取得できるため、そのファイルのみを処理対象とできます。
これによりプロジェクト内のファイル数に関係なく、編集されたファイルのみにフォーマットを実行できるため必要最低限の実行時間で完了します。

競合回避

1つのフック内でgofmtgoimportsを直列実行(&&で接続)することで、複数のフォーマッターが同時実行されて編集結果が競合することを防いでいます。

応用例と制限事項

Monorepo対応

特定のディレクトリ配下のGoファイルのみを対象にしたい場合は、以下のようにフィルタリングできます:

jq -r '.tool_input.file_path | select(contains(\"'$(git rev-parse --show-toplevel)'/go/\") and endswith(\".go\"))'

ファイルパスは絶対パスで渡されるため、このようにパス判定を行います。

制限事項

  • 自動生成コマンドなど、編集したファイル名が引数として取得できない場合は正常に動作しない可能性があります

Tips: Hooksのデバッグ方法

Hooksに渡される情報を確認したい場合、たとえば以下のような設定でデバッグできます。

{
  "permissions": {
    "allow": ["Bash(afplay:*)"],
    "deny": []
  },
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs -r -I {} sh -c 'echo \"Processing: $1\"' _ {}"
          }
        ]
      }
    ]
  }
}

claude -dコマンドでデバッグモードで起動すると、Tool実行後以下のような出力が確認できます。

[DEBUG] Hook command completed with status 0: jq -r '.tool_input.file_path' | xargs -r -I {} sh -c 'echo $1' _ {}
[DEBUG] Hook stdout: /Users/budougumi0617/go/src/github.com/budougumi0617/zenn-docs/CLAUDE.md

おわりに

Claude Code HooksのPostToolUse機能を活用することで、Goファイルの編集時に自動的にフォーマットを実行する環境を構築できました。
コマンド内容を変えれば他の言語でも流用できると思います。 これによりPR作成後、フォーマット漏れでCIが落ちることもなくなりました。

参考リンク

https://docs.anthropic.com/en/docs/claude-code/hooks

https://azukiazusa.dev/blog/claude-code-hooks-run-formatter/



Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -