はじめに
第1弾では Firebase プラグインのインストールとデータ取得、第2弾ではクラッシュの原因分析から修正コードの提案までを紹介しました。
しかし、第2弾で紹介した分析や修正のプロンプトを毎回手入力するのは面倒です。
このクラッシュについて以下を分析して:
1. 直接原因(どのコードが例外を起こしているか)
2. 根本原因(なぜその状態に至るか)
3. 再現条件の推定
4. 影響を受ける iOS バージョンやデバイスの傾向
こんなプロンプトを毎回コピペしていませんか?
本記事では、カスタムコマンドにワークフローと方針をまとめて配置することで、短いスラッシュコマンド一発で一連のワークフローを実行できるようにする方法を紹介します。
この記事でできるようになること
-
/crashlytics-dailyと入力するだけで日次のクラッシュ監視が完了する -
/crashlytics-analyzeで分析からコード特定まで自動実行される - 修正コードがプロジェクトのコーディング方針に沿って生成される
- レポート結果がドキュメントフォルダに自動保存され、履歴として蓄積される
カスタムコマンドとは
Claude Code では、~/.claude/commands/ に Markdown ファイルを配置すると、/ファイル名 でそのファイルの内容をプロンプトとして実行できます。
| 仕組み | 配置場所 | 読み込みタイミング |
|---|---|---|
| カスタムコマンド | ~/.claude/commands/*.md |
実行時のみ読み込まれる |
カスタムコマンドは /コマンド名 で実行したときだけ読み込まれるため、必要なときに必要な指示だけを渡せます。Crashlytics と関係ない作業をしているときにトークンを消費することもありません。
ファイル構成
~/.claude/
└── commands/
├── crashlytics-daily.md ← /crashlytics-daily で実行
├── crashlytics-analyze.md ← /crashlytics-analyze で実行
├── crashlytics-fix.md ← /crashlytics-fix で実行
└── crashlytics-report.md ← /crashlytics-report で実行
カスタムコマンドに方針を埋め込む
各カスタムコマンドには、ワークフローの手順だけでなく、コーディング方針や保存ルールも一緒に記述します。コマンド実行時にだけ読み込まれるので、方針を含めてもトークンの無駄がありません。
ハードルールではなく方針を書く
方針を記述するとき、最も重要なポイントは硬いルールではなく柔軟な方針を書くことです。
❌ 悪い例:硬いルール
## コーディング規約
- force unwrap(!)は原則禁止。guard let / if let を使用すること
- UI 更新は必ずメインスレッドで実行すること(DispatchQueue.main.async または @MainActor)
- Crashlytics.crashlytics().log() で重要な分岐のログを残すこと
この書き方の問題点は以下のとおりです。
-
IBOutletやfatalError意図の箇所でも force unwrap が禁止されてしまう -
DispatchQueue.main.asyncと@MainActorのどちらを使うべきか判断できない - 「重要な分岐」の定義が曖昧
結果として、Claude Code が文脈を無視した機械的な修正を提案してしまいます。
✅ 良い例:柔軟な方針
## コーディング方針
- force unwrap(!)は IBOutlet や fatalError 意図の箇所では許容する。
ランタイムデータ(API レスポンス、キャッシュ、UserDefaults 等)に対しては
安全なアンラップを使う
- UI 更新のスレッド安全性は文脈で判断する。既存コードが
DispatchQueue.main.async で統一されている箇所はそれに合わせ、
新規コードや Swift Concurrency 移行済みの箇所では @MainActor を使う
- Crashlytics のログは、クラッシュ調査時に役立つコンテキスト
(どの分岐を通ったか、主要な変数の状態)を残す。
ただし個人情報やトークンは含めない
こう書くことで、Claude Code がコードベースの文脈を読んで適切に判断してくれます。
この方針を、後述する各カスタムコマンドの中に直接埋め込みます。
カスタムコマンドのセットアップ
ここからが本記事のメインです。以下のコマンドをターミナルにそのままコピペすれば、カスタムコマンドが作成されます。
まず、ディレクトリを作成します。
mkdir -p ~/.claude/commands
crashlytics-daily — 日次監視
cat << 'EOF' > ~/.claude/commands/crashlytics-daily.md
日次のクラッシュ監視を実行してください。
## プロジェクト情報
- iOS アプリ(Swift)
- 最小サポート: iOS 16.7
- Firebase Crashlytics でクラッシュ監視を実施
## 手順
1. 過去24時間の Crashlytics Top Issues を FATAL / NON-FATAL に分類して取得
2. EARLY シグナル(起動1秒以内)のクラッシュを最優先としてハイライト
3. 前日比でイベント数が増加している issue があれば警告
4. 結果を以下のフォーマットで出力:
- 優先度: 高/中/低
- Issue 名(社外共有時は伏せ字にすること)
- イベント数 / 影響ユーザー数
- シグナル
- 推奨アクション
5. 結果を ~/Documents/crashlytics-reports/YYYY-MM-DD/daily.md に保存
- 保存先フォルダが存在しない場合は自動作成する
- daily は上書きせず日付フォルダごとに蓄積する
EOF
使い方:
/crashlytics-daily
これだけで、第1弾で紹介したデータ取得から第2弾の優先度判断までが一括で実行され、結果がドキュメントフォルダに自動保存されます。
crashlytics-analyze — 詳細分析
cat << 'EOF' > ~/.claude/commands/crashlytics-analyze.md
指定した Crashlytics issue の詳細分析を実行してください。
対象 issue: $ARGUMENTS
## プロジェクト情報
- iOS アプリ(Swift)
- 最小サポート: iOS 16.7
## コーディング方針
- force unwrap(!)は IBOutlet や fatalError 意図の箇所では許容する。
ランタイムデータ(API レスポンス、キャッシュ、UserDefaults 等)に対しては
安全なアンラップを使う
- UI 更新のスレッド安全性は文脈で判断する。既存コードが
DispatchQueue.main.async で統一されている箇所はそれに合わせ、
新規コードや Swift Concurrency 移行済みの箇所では @MainActor を使う
- Crashlytics のログは、クラッシュ調査時に役立つコンテキスト
(どの分岐を通ったか、主要な変数の状態)を残す。
ただし個人情報やトークンは含めない
## 手順
1. crashlytics_list_events でスタックトレースを取得
2. 以下の4項目を分析:
- 直接原因(どのコードが例外を起こしているか)
- 根本原因(なぜその状態に至るか)
- 再現条件の推定(OS バージョン、デバイス、タイミング)
- 影響範囲(同じパターンの潜在的な問題箇所)
3. プロジェクト内のソースコードと突き合わせて該当ファイル・行番号を特定
4. 修正コードを提案(修正前/修正後の対比形式)
5. 修正に対するユニットテストを提案
6. 結果を ~/Documents/crashlytics-reports/YYYY-MM-DD/analyze_$ARGUMENTS.md に保存
- 保存先フォルダが存在しない場合は自動作成する
EOF
使い方:
/crashlytics-analyze XXX_Runtime_SetProperty
$ARGUMENTS にスラッシュコマンドの後に入力した引数が渡されます。第2弾で紹介した Step 3〜5(スタックトレース取得 → 原因分析 → コード特定 → 修正提案 → テスト提案)が自動で実行され、分析結果がファイルとして残ります。
crashlytics-fix — 修正適用
cat << 'EOF' > ~/.claude/commands/crashlytics-fix.md
Crashlytics issue の分析結果に基づき、修正を適用してください。
対象 issue: $ARGUMENTS
## プロジェクト情報
- iOS アプリ(Swift)
- 最小サポート: iOS 16.7
## コーディング方針
- force unwrap(!)は IBOutlet や fatalError 意図の箇所では許容する。
ランタイムデータ(API レスポンス、キャッシュ、UserDefaults 等)に対しては
安全なアンラップを使う
- UI 更新のスレッド安全性は文脈で判断する。既存コードが
DispatchQueue.main.async で統一されている箇所はそれに合わせ、
新規コードや Swift Concurrency 移行済みの箇所では @MainActor を使う
- Crashlytics のログは、クラッシュ調査時に役立つコンテキスト
(どの分岐を通ったか、主要な変数の状態)を残す。
ただし個人情報やトークンは含めない
## 修正コード生成時の方針
- Optional のアンラップは guard let / if let / nil coalescing を文脈に応じて
選択する。ネストが深くなるなら guard let、単純な分岐なら if let、
デフォルト値で十分なら ?? を使う
- エラー発生時のログは、後から原因調査できる程度のコンテキストを残す。
ただし過剰なログは避ける
- UI スレッドの修正は、周囲の既存コードのスタイルに合わせる
- 修正のスコープは最小限に留め、リファクタリングの提案は別途行う
- 修正コードには「なぜこの修正が必要か」を簡潔にコメントする。
ただし自明な場合は省略可
## 手順
1. 該当 issue の分析が未実施の場合は、まず crashlytics-analyze の手順を実行
2. 修正コードを該当ファイルに適用
3. 関連する既存テストが壊れていないか確認
4. 新規ユニットテストを作成・追加
5. 変更ファイルの一覧と差分サマリーを出力
EOF
使い方:
/crashlytics-fix XXX_Runtime_SetProperty
分析がまだであれば analyze の手順から自動実行し、そのまま修正の適用まで進みます。
crashlytics-report — 期間レポート
cat << 'EOF' > ~/.claude/commands/crashlytics-report.md
指定期間の Crashlytics クラッシュレポートを生成してください。
対象期間: $ARGUMENTS
## プロジェクト情報
- iOS アプリ(Swift)
- 最小サポート: iOS 16.7
## 手順
1. 指定期間の Top Issues を取得
2. FATAL / NON-FATAL それぞれの Top 10 を集計
3. 以下の観点でサマリーを作成:
- クラッシュフリー率の推移
- 新規 issue と既知 issue の分類
- バージョン別のクラッシュ傾向
- 対応推奨の優先度リスト
4. 結果を ~/Documents/crashlytics-reports/YYYY-MM-DD/report_$ARGUMENTS.md に保存
- 保存先フォルダが存在しない場合は自動作成する
EOF
使い方:
/crashlytics-report 過去1週間
/crashlytics-report 3/1-3/31
週次・月次のふりかえりや、リリース判定時のクラッシュレポート作成に使えます。
方針の重複が気になる場合
ここまで見て、「コーディング方針が複数のコマンドにコピペされていて冗長では?」と感じた方もいるかもしれません。
これは意図的な設計です。カスタムコマンドは実行時にだけ読み込まれるため、方針を埋め込んでも他の作業に影響しません。むしろ、各コマンドが単体で完結していることで以下のメリットがあります。
- コマンド単体を読めば、何をどういう方針で実行するか把握できる
- チームメンバーへの共有時に「このファイルだけコピーすれば動く」と言える
- 方針を変更したいコマンドだけ個別に調整できる
とはいえ、方針が頻繁に更新されるプロジェクトでは、CLAUDE.md に方針を集約してカスタムコマンドからは手順だけにする構成も有効です。プロジェクトの運用に合わせて使い分けてください。
実際の運用イメージ
朝の開発開始時の流れは、こんな感じになります。
# 1. VS Code で Claude Code を起動
# 2. 日次チェック
/crashlytics-daily
# → FATAL 3件、うち EARLY 2件が検出される
# → ~/Documents/crashlytics-reports/2026-03-30/daily.md に保存される
# 3. 最優先の issue を深掘り
/crashlytics-analyze XXX_Runtime_SetProperty
# → 原因特定、修正コード提案、テスト提案まで出力される
# → ~/Documents/crashlytics-reports/2026-03-30/analyze_XXX_Runtime_SetProperty.md に保存される
# 4. 内容を確認して修正適用
/crashlytics-fix XXX_Runtime_SetProperty
# → ファイル編集、テスト追加、差分サマリーが出力される
# 5. VS Code 上で diff を確認して Accept
従来は Firebase Console → Xcode → テストコード手書き、と複数ツールを横断していた作業が、VS Code のターミナル1つで完結します。レポート結果は自動でドキュメントフォルダに蓄積されるので、過去の分析を振り返りたいときもファイルを開くだけです。
まとめ
カスタムコマンドにワークフローと方針をまとめることで、以下の改善が得られます。
| 従来 | カスタムコマンド導入後 |
|---|---|
| 毎回プロンプトを手入力・コピペ |
/crashlytics-daily で即実行 |
| 分析のたびに方針を口頭で伝える | コマンド内に方針が埋め込み済み |
| 硬いルールで文脈を無視した修正が出る | 方針ベースで文脈に応じた判断 |
| 分析結果がチャットに流れて消える | ドキュメントフォルダに自動蓄積 |
ポイントは3つです。
カスタムコマンドに方針もワークフローもまとめる。 実行時のみ読み込まれるので、他の作業に影響しない。各コマンドが単体で完結しているため、共有や管理もしやすい。
$ARGUMENTS で引数を渡す。 issue 名や対象期間をコマンド実行時に指定できるので、汎用的に使い回せる。
ルールではなく方針を書く。 「禁止」「必須」ではなく「こういう場面ではこう判断する」と書くことで、Claude Code が文脈に応じた柔軟な提案をしてくれる。
