概要
Gitのpre-commitやpre-pushでフォーマッティング等を走らせるためにhuskyを使っていたが、Claude Codeに「モダンなgit hooks管理ツールを使いたい」と相談したところ、lefthookが選ばれた。なぜhuskyではなくlefthookなのか聞いてみたら、いくつか明確な違いがあったので、そのまとめ。
経緯
自分はこれまでGitフック管理にhuskyを使っていた。commitやpushのタイミングでフォーマッティングやlintを走らせるやつ。特に不満があったわけではないが、新規プロジェクトのセットアップをClaude Codeにやらせたところ、huskyではなくlefthookが選択された。
「なんでlefthookにしたの?」と聞いたら、比較情報を出してくれた。
比較
| 項目 | Husky | Lefthook |
|---|---|---|
| 実装言語 | JavaScript (Node.js) | Go (単一バイナリ) |
| 設定方法 | .husky/ フォルダにシェルスクリプト | 単一の lefthook.yml YAMLファイル |
| 実行方式 | 逐次実行 | デフォルトで並列実行 |
| ランタイム依存 | Node.js必須 | なし(スタンドアロンバイナリ) |
| エコシステム | JS/TSプロジェクト (npm/pnpm/yarn) | 言語非依存 (JS, Go, Ruby等) |
| ファイルフィルタリング | 別途 lint-staged が必要 | glob/files オプションで組み込み対応 |
| 速度 | 遅い(シェル + Node.jsオーバーヘッド) | 速い(Goバイナリ、キャッシュ、並列処理) |
lint-stagedが不要
huskyで変更ファイルだけにlinterを走らせようとすると、別途lint-stagedというパッケージが必要になる。husky + lint-stagedの2つを入れて、それぞれ設定を書いて……という構成になる。
lefthookはglobやfilesオプションがYAML設定に組み込まれているので、1つのツール、1つの設定ファイルで完結する。
並列実行がデフォルト
ESLint + Prettier + 型チェックのように複数のコマンドをpre-commitで走らせる場合、huskyだと逐次実行になる。lefthookはデフォルトで並列実行なので、pre-commitが体感で速くなる。
Node.jsに依存しない
Go製の単一バイナリなので、Node.jsが不要。Go, Python, Rubyなどが混在するpolyglotなリポジトリで、git hooksのためだけにNode.jsを入れる必要がない。JS/TSプロジェクトでしか使わないならあまり関係ないが、言語を問わず使えるのは汎用性がある。
設定がシンプル
huskyはv5以降、package.jsonでの設定から.husky/ディレクトリにシェルスクリプトを置く方式に変わった。つまりシェルスクリプトのフォルダ + lint-stagedの設定ファイルという構成になる。
lefthookはlefthook.ymlという1つのYAMLファイルに全部書く。設定の見通しが良い。
huskyがまだ合うケース
lefthookの方が優れている点が多いが、huskyが合うケースもある。
- 純粋なJS/TSプロジェクトで全員Node.jsを持っている場合
- すでにhuskyで動いていて、特に問題がない場合(わざわざ移行する必要はない)
- フックが1つだけのシンプルなケースで、並列実行の恩恵がない場合
動いているものをわざわざ変える必要はないので、既存プロジェクトで問題なく動いているならそのままで良い。
まとめ
Claude Codeがhuskyではなくlefthookを選んだのは合理的な判断だった。Go製の単一バイナリで速く、並列実行がデフォルトで、lint-stagedが不要で、設定もYAML 1ファイルでシンプル。新規プロジェクトならlefthookを選ぶのが良さそう。