◉CLAUDE LABEN
●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り45日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました
記事一覧/Claude Code
⟐ Claude Code/2026-05-22中級

Claude Code Hooks と SwiftLint を組み合わせて iOS 個人開発の品質ゲートを6週間運用した記録

壁紙アプリと癒し系アプリの保守で、Claude Code の PostToolUse Hook と SwiftLint を組み合わせ、個人開発の品質ゲートを6週間運用した記録です。導入の動機から実装、運用してわかった調整ポイントまでを率直に書き残します。

claude-code132hooks22swiftlintios14個人開発130

2014年に最初の壁紙アプリをリリースしてから、私は12年間ずっと一人でアプリを作り続けています。アーティスト・クリエイターの廣川政樹です。アート活動と並行して、累計5,000万DL超の小さなアプリ事業を一人で回しています。

Claude Code を本格導入してから、コード生成のスピードは確かに上がりました。けれど一人で複数アプリを保守していると、生成されたコードがプロジェクト全体のスタイルからわずかにずれていく違和感が、少しずつ積み重なっていきます。インデント幅、命名規則、import の順序、guard と if let の使い分け。1ファイルなら気づきますが、10ファイル20ファイルと進むうちに、後で読み返したときの「私が書いた感」が薄れていくのが気になっていました。

そこで6週間前から、Claude Code の PostToolUse Hook に SwiftLint を組み込んで、ファイル編集の直後に自動でスタイルチェックがかかる仕組みを運用しています。完璧な仕組みではありません。けれど「私らしいコードベース」を保つ意味では、想像以上に効いています。この記事は、その6週間の運用記録です。

導入の動機 — 私の手元コードを「私らしく」保ちたい

両家の祖父はともに宮大工でした。宮大工の現場では、新しく入る材木も、既存の柱や梁との「揃い」を必ず確認します。釘1本の打ち方、面取りの角度、木目の方向。完成してから見れば気づかれない部分にも、揃いの基準があります。私はコードに対しても、同じ感覚を持ち続けたいと思っています。

Claude Code が出力する Swift コードは、ベースの品質としては申し分ありません。けれど SwiftUI のクロージャ内で return を省略するか書くか、@State プロパティの並び順、コメントの書き方の細部は、プロンプトでは指示しきれない揺らぎが残ります。私は手動レビューでそれを直していましたが、複数アプリ × 数十ファイルの編集が走るとレビュー負荷が積み上がりました。

「編集直後に SwiftLint を走らせて、違反があれば Claude Code 自身に直してもらう」というのが、今回の運用設計です。リンタを CI だけで動かすのでは遅すぎます。Claude Code が編集したまさにその瞬間に走らせる必要がありました。

PostToolUse Hook の最小構成

Claude Code の Hooks は、ツール呼び出しの前後に任意のシェルコマンドを実行できる仕組みです。Edit / Write / MultiEdit の直後に SwiftLint をかけるのが、今回の目的です。

~/.claude/settings.json に PostToolUse Hook を追加します。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "bash $HOME/.claude/scripts/swiftlint-after-edit.sh"
          }
        ]
      }
    ]
  }
}

matcher で対象ツールを絞っているのは、Read / Grep のたびに SwiftLint が走るのを避けるためです。最初はマッチャを書かずに全イベントで走らせていましたが、思考の流れまで遅くなるのに気づき、編集系だけに絞りました。

スクリプト本体は次のような最小構成です。

#!/usr/bin/env bash
# ~/.claude/scripts/swiftlint-after-edit.sh
set -euo pipefail
 
INPUT="$(cat)"
FILE_PATH="$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')"
 
# Swift 以外は何もしない
[[ "$FILE_PATH" == *.swift ]] || exit 0
 
# プロジェクトルートを推定(最も近い .swiftlint.yml を探す)
DIR="$(dirname "$FILE_PATH")"
while [[ "$DIR" != "/" ]]; do
  [[ -f "$DIR/.swiftlint.yml" ]] && break
  DIR="$(dirname "$DIR")"
done
 
# .swiftlint.yml が見つからないプロジェクトはスキップ
[[ -f "$DIR/.swiftlint.yml" ]] || exit 0
 
cd "$DIR"
OUTPUT="$(swiftlint --quiet --path "$FILE_PATH" 2>&1 || true)"
 
if [[ -n "$OUTPUT" ]]; then
  # Claude Code に違反を返す(stdout は会話に流れる)
  echo "SwiftLint findings for ${FILE_PATH}:"
  echo "$OUTPUT"
fi

jq で tool_input.file_path を取り出している部分が地味に重要です。Hooks は JSON を stdin で受け取るので、ここを間違えるとファイルパスが取れずに永遠に空振りします。私も最初の数日はこれで時間を取られました。

6週間運用してわかった3つの調整

1. .swiftlint.yml をアプリ別に分けたほうがよかった

私の手元には壁紙アプリと癒し系アプリが混在していて、UI の作り方も微妙に違います。最初は1つの .swiftlint.yml を共通で使っていましたが、線種の違うコードベースを同じルールで縛ると、片方では正しい書き方が片方では違反になる場面が出てきました。

結局、各アプリのリポジトリ直下に .swiftlint.yml を置き、上のスクリプトで「最も近い .swiftlint.yml を探す」ロジックにしました。プロジェクトごとに方言を許す方が、現実の保守には合っていました。

2. --fix を Hook 側で自動実行するのはやめた

最初は swiftlint --fix --quiet --path "$FILE_PATH" で自動修正までかけていました。確かに楽なのですが、Claude Code が編集している最中に裏でファイルが書き換わると、Claude 側の差分認識がずれます。一度、自動修正と Claude の連続編集がぶつかって、同じ修正が二度かかったことがありました。

それ以来、Hook 側では検出のみを返し、修正の判断は Claude Code 自身に任せています。違反内容を stdout で返せば、Claude は次のターンで「指摘された箇所を直しましょう」と動いてくれます。

3. 違反が多すぎる初期はノイズと割り切る

導入1週目は、過去に書いた古いファイルを編集するたびに既存違反が大量に表示され、Claude が混乱したり、本来直すべきでない箇所まで触ろうとしました。

対処として .swiftlint.yml に excluded: を増やし、only_rules: で対象ルールを絞り込みました。

# .swiftlint.yml の例
only_rules:
  - trailing_whitespace
  - colon
  - comma
  - vertical_whitespace
  - opening_brace
  - control_statement
  - identifier_name
  - line_length
 
excluded:
  - Pods
  - Carthage
  - Generated
  - Legacy   # 10年前のコードを置いてある場所

「全部のルールを入れるか、最小ルールから入れるか」は、好みが分かれるところです。私は最小から始めて、信頼できるルールを少しずつ足していく方が安心でした。

6週間で実感した4つの変化

ここまでの3つの調整を経て、運用は安定しました。手元の感覚としては、次のような変化があります。

第一に、レビュー時間が体感で半分以下になりました。SwiftLint が拾える範囲のスタイル違反は、編集ターンの中でほぼ消えるようになり、私の目視レビューは「設計判断」と「テスト観点」に集中できるようになりました。

第二に、Claude Code が出力するコードのスタイルが、回を追うごとに揃ってきました。Hook が違反を返すと Claude は次のターンで直し、その学習が同じセッション内では確実に蓄積されます。「私のリポジトリでは return を省略するスタイルだ」を、私が言葉で説明しなくても、リンタの違反から逆向きに伝わっていく感覚です。

第三に、過去の古いファイルに手を入れる際の心理的な障壁が下がりました。10年前の Objective-C 混在コードでも、Hook が「直すべき箇所」を機械的に示してくれるので、Claude に「最小差分で SwiftLint 違反だけ直してください」と頼みやすくなりました。

第四に、これは少し意外だったのですが、コミットメッセージが具体的になりました。違反が明示的に出ているので、Claude が「trailing_whitespace 4件と identifier_name 2件を修正」のような具体的なメッセージを書くようになりました。

落とし穴 — 私が踏んだもの

良かった点ばかり書いても誠実ではないので、6週間で踏んだ落とし穴も書いておきます。

swiftlint の起動オーバーヘッドは、Hook で1ファイルごとに走らせると意外と重く感じることがありました。M1 Mac では1ファイル数百ミリ秒ですが、MultiEdit で10ファイル一気に編集された直後は、明らかにテンポが落ちます。--quiet を付ける、only_rules: で絞る、excluded: を広めにとる、の3点で改善しましたが、リンタを編集のたびに走らせる以上、ゼロにはなりません。

もう一つは、Hook の標準出力が長くなると、Claude Code 側のコンテキストを地味に圧迫します。ファイル1つあたりの違反は最大10件までに絞るような後処理を、スクリプトに足しました。head -20 を最後にかぶせる程度で十分です。

次に試したいこと

この仕組みは、SwiftLint を別のリンタや型チェッカーに置き換えれば、同じ構造で他言語にも展開できます。私は次に、Python 製のスクリプト群で ruff を同じパターンで組み込もうとしているところです。

離れて暮らす子どもたちに何を残せるかと考えるたび、技術を分かりやすく書き残すことの意味を再確認します。Claude Code のように頼りになる相棒ができても、最終的に「私らしいコード」を残せるかどうかは、私自身の運用設計にかかっています。Hooks のような細い仕組みでも、長く運用すればその違いが現れます。

同じように一人でアプリ事業を続けている方、複数のリポジトリを行き来している方の参考になれば幸いです。お読みいただきありがとうございました。

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

⟐ Claude Code2026-05-27
壁紙アプリ 2 本の Crashlytics を Claude Code で 11 日間掘り続けた実装ログ
壁紙アプリ 2 本(綺麗な壁紙 v2.0.0 / 浮世絵壁紙 v1.7.0)でリリース後に Crashlytics と Play Console から噴き出した 30 件超のバグを、Claude Code で 11 日間掘り続けて v2.1.1 / v1.8.1 まで仕上げた工程を、スタックトレース → 原因仮説 → 修正コミットの順で公開します。
⟐ Claude Code2026-05-06
Claude Code で個人 SaaS を 90 日運用した記録 — 設計判断と、後から一次情報で訂正した箇所
Claude Code を中心に個人 SaaS を90日間つくった作業ノートです。設計対話の使い方、モデルの使い分け、Cloudflare Workers の制約への対処を記録し、公開後に一次情報で洗い直して誤っていた3点を訂正しました。
⟐ Claude Code2026-04-24
Claude Code Hooks の本番デバッグ術 — ログが足りない時、どこから切り分けるか
ローカルでは動くのに本番で沈黙するClaude Code Hooksの切り分け方を体系化しました。まず疑うべきは出力先という視点、ログ不足を補う3層の可観測性、最小再現環境を60秒で作るテクニック、JSON入出力とexit codeのプロトコル把握、マルチユーザー環境の権限診断まで扱います。