Section 1: 自作 Claude スキルによる、コミットメッセージの提案
使うツール: /git-commit スキル
目的
- git commit -m "fix: xxx" タイトルメッセージだけで済ませてしまう。
- コミットメッセージの本文まで考えるのがめんどう
git diffを毎回読んで要点をAIにまとめてもらってコミットメッセージを提案してもらいたい- Conventional Commits に準拠したい
やること
- 実装する
- Claude Code で
/git-commitを実行 - AI が diff を読み、
feat: .../fix: ...を含む候補メッセージを提示 - 承認するとコミットする
準備
Section 0 でクローンした svelte-todo/ に移動します。 フォーク・クローンは済んでいる前提なので、ここでは新規作成しません。
# Section 0 でクローンしたフォークに移動
cd svelte-todo手順
1. スキルの作成
~/.claude/skills/git-commit/SKILL.md ファイルを作成します。(右上のコピーボタンで取得)
mkdir -p ~/.claude/skills/git-commit
vi ~/.claude/skills/git-commit/SKILL.md---
name: git-commit
description: |
`staged` / `unstaged` diff を解析してコミット計画を提案し、
ユーザー承認後に Conventional Commits 形式でコミットを実行する。
disable-model-invocation: true
allowed-tools: Bash(git *)
---
## 起動時コンテキスト
- 現在ブランチ: !`git branch --show-current`
- 作業ツリー状態: !`git status --short`
- `staged` diff (要約): !`git diff --staged --stat`
- `unstaged` diff (要約): !`git diff --stat`
- 直近 5 コミット (スタイル参考用): !`git log -5 --oneline`
## 事前チェック
1. `git status --short` で `staged` / `unstaged` / `untracked` の有無を確認。
2. `staged` changes があれば `git diff --staged` を読む。
3. `unstaged` changes があれば `git diff` を読み、コミット対象に含めたいかユーザーへ確認。
- `untracked` files は `git status --short` と必要に応じて `git ls-files --others --exclude-standard` で確認。
- ユーザー承認なしに `unstaged` / `untracked` files を `git add` しない。
- `unstaged` を含めない回答なら、`staged` changes だけで計画を作る。
4. `staged` changes がなく、`unstaged` / `untracked` を含める承認もない場合は中止。
5. `.env`、鍵、トークン、認証情報、個人情報らしきファイルや差分があれば、計画提示前に警告して確認を取る。
## 手順
1. **差分サマリー → 変更の意図 → コミット計画 → 確認** の 4 ブロックを、この順で 1 度ずつだけ提示する。同じ情報を別表現で繰り返さない。
2. **差分サマリー** (下記フォーマット) を最初に提示。
- `staged` / `unstaged` / `untracked` を分けて表示。
- ファイル別の概要は最大 5 件。超える場合は表のみ。
3. **変更の意図** を 2〜4 行で要約し、単一/複数コミット判断を最後に 1 行で示す。
- 分割の目安: 10 ファイル超、300 行超、目的が複数、ドキュメントと実装が混在、リファクタと仕様変更が混在。
- ユーザーが単一コミットを明示した場合でも、履歴が読みにくくなるなら理由を短く指摘してから従う。
4. **コミット計画を提示** (下記「コミット計画」フォーマット)。
- 単一コミット: メッセージ案、対象ファイル、含めないファイル、注意点。
- 複数コミット: コミット順 / 各コミットの対象ファイル(または hunk) / メッセージ案 / 分割理由 / 検証コマンド。
5. ユーザー承認後、計画どおりに staging してコミットする。
- `unstaged` / `untracked` を含める場合は、承認済みのファイルだけ `git add` する。
- hunk 単位の分割が必要なら `git add -p` を使う前に対象 hunk を説明し、対話操作で迷う場合は中止してユーザーに確認。
- 複数コミットでは、各コミット前に `git diff --staged --stat` で対象を確認する。
6. type 判定:
- 新機能追加: `feat:`
- バグ修正: `fix:`
- 内部リファクタ: `refactor:`
- ドキュメント: `docs:`
- テスト: `test:`
- 設定・雑務: `chore:`
- パフォーマンス: `perf:`
- CI/CD: `ci:`
7. コミットメッセージ形式:
```
<type>: <概要 (50文字以内)>
- 箇条書きで詳細 (任意, 各 72 文字以内)
```
8. 承認後、here-doc でコミット。
- `--amend` は使わない (pre-commit フックが落ちた場合は新規コミットで作り直す)
```bash
git commit -F - <<'EOF'
<commit message>
EOF
```
## 差分サマリー (提示フォーマット)
最初の応答で必ず次のテーブルを表示する。`主な変更領域` は **5 件以内** に絞り、超える場合は省略して表だけ出す。
```markdown
## 差分サマリー
| 区分 | ファイル数 | +行 | -行 |
| --------- | ---------: | --: | --: |
| staged | N | +X | -Y |
| unstaged | N | +X | -Y |
| untracked | N | - | - |
| 合計 | N | +X | -Y |
主な変更領域 (最大 5 件):
- `<path/dir>`: 1 行の概要 (+X / -Y)
- ...
## 変更の意図
<2〜4 行。表に書いた内容の言い換えはしない>
判定: 単一コミット / 複数コミット (理由を 1 行)
```
`git diff --staged --stat` / `git diff --stat` / `git status --short` から数値を集計する。
## コミット計画 (提示フォーマット)
`## コミット計画` 見出しは出力中 **1 回のみ**。各コミットのメッセージ本文は **必ず fenced code block** で囲み、ターミナル幅で破断しないようにする。
### 単一コミットの場合
````markdown
## コミット計画 (1 件)
**[1/1]** `<type>: <概要>`
- 対象: `path/a.ts`, `path/b.ts`
- 除外: (任意)
- 検証: (任意: lint/test コマンドなど)
メッセージ:
```text
<type>: <概要>
- 詳細1
- 詳細2
```
````
### 複数コミットの場合
````markdown
## コミット計画 (N 件)
分割理由: <1〜2 行>
**[1/N]** `<type>: <概要>` (+X / -Y)
- 対象: `path/a.ts`, `path/b.ts (新規)`
- 対象 hunk: <hunk 単位なら明記>
メッセージ:
```text
<type>: <概要>
- 詳細
```
**[2/N]** `<type>: <概要>` (+X / -Y)
- 対象: ...
メッセージ:
```text
<type>: <概要>
```
順序の理由: <例: 先にリファクタ、後で機能追加>
検証順: <任意>
````
各コミットでどのファイル(または hunk)が含まれ、どんなメッセージになるかが一目で分かる粒度で書く。
## 確認フォーマット
差分サマリーと計画提示後、必ず次の順にユーザーへ確認する。
1. `unstaged` / `untracked` changes がある場合: 「これらも今回のコミット対象に含めますか?」
2. 差分が大きい場合: 「上記の N コミット分割案で進めますか? (単一にまとめる場合は指示してください)」
3. 最終確認: 「この計画で staging / commit を実行してよいですか?」
承認が曖昧な場合は実行しない。
## 出力ルール
- 言語: 日本語
- 絵文字は使わない。
- 「なぜ」を優先し、「何を」はコードが語るので簡潔に。
- 同じ情報を別表現で繰り返さない (例: 表に書いたファイル一覧を地の文で再列挙しない)。
- 各セクション間の地の文は最大 4 行。長くなる場合は箇条書きに切り替える。
- コミットメッセージ本文は必ず fenced code block で囲む。
- `## 差分サマリー` `## コミット計画` などの見出しは出力中 1 回のみ。
- コミット後に `git status --short` と、作成した各コミットの hash / subject を一覧で報告する。2. スキルの確認
ファイルを作成した後に claude を起動する。(新しく開き直さないとスキルが読み込まれない)
claudeClaude Code上で補完される様になったらok
/git-commit※ /help コマンドの custom-commands タブから登録されていることの確認もできる。
3-1. スキルの実行1
Section 4 の PR 作成につなげるため、main に直接コミットせずトピックブランチで作業する。 題材は svelte-todo に既にある src/lib/index.ts (現状はコメント 1 行のプレースホルダ) を使い、アプリ名定数を 1 つ生やすだけの最小変更を入れる。
# 練習用ブランチを作る
git switch -c feat/app-title origin/mainsrc/lib/index.ts を以下の内容に編集する (1 行追記)。
// place files you want to import through the `$lib` alias in this folder.
export const APP_TITLE = "Svelte Todo";/git-commit を起動する。
Claude Code で:
/git-commitAI の提案例:
## 差分サマリー
| 区分 | ファイル数 | +行 | -行 |
| --------- | ---------: | --: | --: |
| staged | 0 | 0 | 0 |
| unstaged | 1 | +1 | 0 |
| untracked | 0 | - | - |
| 合計 | 1 | +1 | 0 |
主な変更領域:
- `src/lib/index.ts`: `APP_TITLE` 定数を `$lib` から export (+1 / -0)
## 変更の意図
アプリ全体で参照できる定数 `APP_TITLE` を `$lib` 経由で公開するための追加。
判定: 単一コミット (変更は 1 ファイル 1 行のみ)
## コミット計画 (1 件)
**[1/1]** `feat: $libからAPP_TITLE定数をexport`
- 対象: `src/lib/index.ts` (現在 unstaged → 承認後 add)
- 除外: なし
- 検証: 任意
メッセージ:
```text
feat: $libからAPP_TITLE定数をexport
```
- `unstaged` の `src/lib/index.ts` を今回のコミットに含めてよいですか?
- 上記計画で staging / commit を実行してよいですか?ok で承認 → 1 件のコミットが作られる。
3-2. スキルの実行2
# 用意している練習用ブランチに切り替え
git switch -c feat/todo-enhancements origin/feat/todo-enhancements
# 雑なコミットの取り消し
git reset --soft HEAD~
claude
/git-commitAI の提案例:
## 差分サマリー
| 区分 | ファイル数 | +行 | -行 |
| --------- | ---------: | ---: | --: |
| staged | 7 | +198 | -22 |
| unstaged | 0 | - | - |
| untracked | 0 | - | - |
| 合計 | 7 | +198 | -22 |
主な変更領域:
- `src/lib/components/`: `TodoStats.svelte` / `ConfirmModal.svelte` 新規 (+79)
- `src/routes/+page.svelte`: 残件カウント・完了一括削除・モーダル連携・CSS クラス抽出 (+42 / -22)
- `src/app.css`: Tailwind コンポーネントクラスを集約 (+34)
- `README.md`: プロジェクト説明と開発スクリプトを記載 (+30)
- `.gitignore` / `+layout.svelte`: IDE 無視設定とフッター追加 (+13)
## 変更の意図
Todo アプリに「残件/完了数の表示」「完了タスクの一括削除(確認モーダル付き)」を追加し、Tailwind の繰り返し記述を `app.css` に抽出してマークアップを整理。あわせて README とフッター、`.gitignore` を整備。
判定: 複数コミット(feat / docs / chore で目的が分かれるため)
## コミット計画 (3 件)
分割理由: feature 追加・ドキュメント・無視設定/レイアウト雑務で目的が異なる。`+page.svelte` の CSS クラス抽出は新機能追加と同一 hunk に絡むため feat にまとめる。
**[1/3]** `chore: IDE / ログファイルを gitignore に追加` (+11 / -0)
- 対象: `.gitignore`
メッセージ:
```text
chore: IDE/ログファイルを gitignore に追加
- .idea/ と .vscode/ (extensions.json は許可) を除外
- *.log 系を除外
```
**[2/3]** `docs: README にアプリ概要と開発スクリプトを追記` (+30 / -0)
- 対象: `README.md`
メッセージ:
```text
docs: README にアプリ概要と開発スクリプトを追記
- 機能・技術スタック・使い方を追加
- 開発スクリプト一覧表を追加
```
**[3/3]** `feat: 残件表示と完了一括削除・確認モーダルを追加` (+157 / -22)
- 対象: `src/lib/components/TodoStats.svelte` (新規), `src/lib/components/ConfirmModal.svelte` (新規), `src/routes/+page.svelte`, `src/app.css`, `src/routes/+layout.svelte`
- 補足: `+page.svelte` のクラス抽出 (`app.css` への集約) は新機能追加と同一ファイル/hunk のためまとめて含める
メッセージ:
```text
feat: 残件表示と完了一括削除・確認モーダルを追加
- TodoStats で残件/完了数を表示し完了タスク一括削除を提供
- ConfirmModal で削除前に確認ダイアログを表示
- 入力時の trim を addTodo 側で実施
- 繰り返し利用する Tailwind 指定を app.css のコンポーネント
クラスに集約しマークアップを簡潔化
- レイアウトにフッターを追加
```
順序の理由: 雑務・ドキュメント先、機能追加を最後に置きレビュー時の差分が見やすい。
この計画で staging / commit を実行してよいですか?ok で承認 → 1 件のコミットが作られる。
補足: フロントマターの読み方
スキル冒頭の YAML フロントマターは Claude Code がスキルを認識するためのメタ情報。各フィールドの意味は以下:
| フィールド | 役割 | このスキルでの値 |
|---|---|---|
name | スラッシュコマンド名 (/git-commit) として登録されるキー。group:command 形式にするとグルーピング表示される。 | git-commit |
description | スキル一覧やモデルがスキルを選ぶときに参照する説明文。1〜2 行で「何をするか」を端的に書く。 | コミットメッセージ案を作って承認後にコミット |
disable-model-invocation | true にすると モデルが自律的に呼ばない ようになり、ユーザーが明示的に /git-commit と打った時だけ起動。誤発火を防ぐ用途。 | true (コミットは必ず人間トリガで) |
allowed-tools | スキル実行中に使えるツールをホワイトリストで制限。Bash(git *) は git で始まる Bash コマンドのみ許可、という意味で、rm や npm などは弾かれる。 | Bash(git *) |
補足:
allowed-toolsは省略するとそのセッションの既定権限がそのまま使える。安全側に倒したいスキル (コミット・push 系) では明示的に絞るのがおすすめ。 補足:disable-model-invocationを付けないと、会話の流れで Claude が「ここでコミットすべき」と判断したタイミングで勝手に/git-commit相当の処理を呼ぶことがある。ステージング状態を確認してから実行したい運用なら付けておく。
補足: 本文中のテクニック
スキル本文 (フロントマター以下の Markdown) でも、Claude Code 固有の記法をいくつか使っている。
1. ! プレフィックスによるコマンド埋め込み (起動時コンテキスト)
- 現在ブランチ: !`git branch --show-current`
- 作業ツリー状態: !`git status --short`
- staged diff (要約): !`git diff --staged --stat`
- unstaged diff (要約): !`git diff --stat`
- 直近 5 コミット (スタイル参考用): !`git log -5 --oneline`- バッククォート直前の
!は「スキル起動時にこのシェルコマンドを実行し、その出力を本文に展開」する記法。 - AI に Bash ツールを呼ばせるよりも 1 ターン早く事実を渡せるので、
git statusのような 毎回必ず見る情報 を先回りで注入したいときに使う。 - 副作用のないコマンド (
git status,ls,cat README.mdなど) に限定する。git pushのような書き込み系は絶対に書かない (起動の度に走る)。 allowed-toolsでBash(git *)を許可していないと、ここで使うgitコマンドも弾かれる点に注意。
2. なぜ「起動時コンテキスト」を冒頭に置くのか
- AI は最初に渡された情報ほど判断材料として参照しやすい。
- 「diff を見て要約しろ」より「以下が staged diff の summary です。これを踏まえて本文を読め」のほうが、無駄な探索ターンが減る。
- ブランチ名や直近コミットのスタイル (英語/日本語、語調) を最初に渡しておくと、出力スタイルが安定する。
3. 手順を番号付きリストで書く
- スキル本文は AI 向けの実行手順書。曖昧な「いい感じに」を避け、
1. → 2. → 3.で分岐や条件 (「未 staged があれば確認」など) まで明示する。 - 出力フォーマット (コミットメッセージのテンプレ) もコードブロックで具体例を見せると、ブレが小さくなる。
4. ガードレールは「やらないこと」も明記
--amend は使わない,絵文字は使わない,.env が staged にあれば警告のような NG ルール を本文末に集約。- AI は「やっていいこと」より「やってはいけないこと」のほうが守りやすいので、禁止事項は箇条書きで残す。
チェックポイント
-
/git-commitが AI からメッセージ案を提示する - Conventional Commits プレフィックスが正しく推論されている
- コミット後、
git logで意図した内容になっている