Skip to content

Section 1: 自作 Claude スキルによる、コミットメッセージの提案

使うツール: /git-commit スキル

目的

  • git commit -m "fix: xxx" タイトルメッセージだけで済ませてしまう。
  • コミットメッセージの本文まで考えるのがめんどう
  • git diff を毎回読んで要点をAIにまとめてもらってコミットメッセージを提案してもらいたい
  • Conventional Commits に準拠したい

やること

  1. 実装する
  2. Claude Code で /git-commit を実行
  3. AI が diff を読み、feat: ... / fix: ... を含む候補メッセージを提示
  4. 承認するとコミットする

準備

Section 0 でクローンした svelte-todo/ に移動します。 フォーク・クローンは済んでいる前提なので、ここでは新規作成しません。

bash
# 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
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 を起動する。(新しく開き直さないとスキルが読み込まれない)

claude

Claude Code上で補完される様になったらok

/git-commit

/help コマンドの custom-commands タブから登録されていることの確認もできる。

3-1. スキルの実行1

Section 4 の PR 作成につなげるため、main に直接コミットせずトピックブランチで作業する。 題材は svelte-todo に既にある src/lib/index.ts (現状はコメント 1 行のプレースホルダ) を使い、アプリ名定数を 1 つ生やすだけの最小変更を入れる。

bash
# 練習用ブランチを作る
git switch -c feat/app-title origin/main

src/lib/index.ts を以下の内容に編集する (1 行追記)。

ts
// place files you want to import through the `$lib` alias in this folder.

export const APP_TITLE = "Svelte Todo";

/git-commit を起動する。

Claude Code で:

/git-commit

AI の提案例:

md
## 差分サマリー

| 区分      | ファイル数 | +行 | -行 |
| --------- | ---------: | --: | --: |
| 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

bash
# 用意している練習用ブランチに切り替え
git switch -c feat/todo-enhancements origin/feat/todo-enhancements

# 雑なコミットの取り消し
git reset --soft HEAD~

claude
/git-commit

AI の提案例:

md
## 差分サマリー

| 区分      | ファイル数 |  +行 | -行 |
| --------- | ---------: | ---: | --: |
| 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-invocationtrue にすると モデルが自律的に呼ばない ようになり、ユーザーが明示的に /git-commit と打った時だけ起動。誤発火を防ぐ用途。true (コミットは必ず人間トリガで)
allowed-toolsスキル実行中に使えるツールをホワイトリストで制限。Bash(git *)git で始まる Bash コマンドのみ許可、という意味で、rmnpm などは弾かれる。Bash(git *)

補足: allowed-tools は省略するとそのセッションの既定権限がそのまま使える。安全側に倒したいスキル (コミット・push 系) では明示的に絞るのがおすすめ。 補足: disable-model-invocation を付けないと、会話の流れで Claude が「ここでコミットすべき」と判断したタイミングで勝手に /git-commit 相当の処理を呼ぶことがある。ステージング状態を確認してから実行したい運用なら付けておく。

補足: 本文中のテクニック

スキル本文 (フロントマター以下の Markdown) でも、Claude Code 固有の記法をいくつか使っている。

1. ! プレフィックスによるコマンド埋め込み (起動時コンテキスト)

markdown
- 現在ブランチ: !`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-toolsBash(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 で意図した内容になっている

2026-05-07 開催 / 開発フロー自動化ハンズオン