--- name: commiter description: | 会話内容とgit diffからConventional Commits準拠のコミットメッセージを生成し、対話的にステージング・承認を経てコミットを実行するスキル。 デフォルトではコミット実行までを担い、`--suggest` 指定時はメッセージ提案のみに留める。 `--auto` 指定時はステージ対象とコミットメッセージの承認確認を省略し、既にステージ済みの変更だけを生成したメッセージでコミットする。 `--push` 指定時はコミット成功後に push まで行う。 以下の状況で必ず使用すること: (1) ユーザーが「コミットして」「コミット作って」「commitして」と依頼した時 (2) ユーザーが「変更をコミットして」「この変更でコミットを作って」と依頼した時 (3) ユーザーが明示的に「commiter スキル」の実行を指示された時 (4) ユーザーが「コミットメッセージを提案して」「コミットメッセージを考えて」と依頼した時(この場合は `--suggest` モード相当として扱う) (5) ユーザーが「実装完了したのでコミットお願い」「ここまでの変更を記録して」と依頼した時 (6) ユーザーが「コミットしてpushして」と依頼した時(`--push` を補って実行) (7) ユーザーが「確認なしでコミットして」「メッセージはそのままでいいから自動でコミットして」「承認を省略して」と依頼した時(`--auto` を補って実行) メッセージ提案のみが目的の場合は `--suggest` を付けて呼び出すこと。 通常の git ワークフロー(ステージング→コミット)をユーザーが任せたい意図を見せたら、このスキルを優先してトリガーする。 argument-hint: "[--suggest] [--auto] [--push] [--mode short|long] [--scope スコープ] [--lang en|ja]" --- # commiter 会話コンテキストと git の差分情報を分析し、Conventional Commits 仕様に準拠したコミットメッセージを生成して、対話的にコミット(必要なら push)を実行する。 **ユーザーとのやり取りはすべて日本語で行う。** ## 引数 ``` `commiter` スキル [--suggest] [--auto] [--push] [--mode short|long] [--scope ] [--lang en|ja] [--export-dir ] ``` - `--suggest` (任意): 提案モード。コミットは実行せず、メッセージ提案のみを行う(旧バージョン互換動作)。 - `--auto` (任意): 自動承認モード。ステージング対象の確認(Step 2)とコミットメッセージの承認確認(Step 5)を省略し、既にステージ済みの変更だけを生成したメッセージでコミットする。未ステージ変更・未追跡ファイルは自動追加しない。ステージ済み変更がなければコミットせず終了する。main/master への直接 push 確認(Step 7)は省略しない。`--suggest` と併用された場合は無視する(提案モードはそもそもコミットを実行しないため)。 - `--push` (任意): コミット成功後に `git push` まで実行する。`--suggest` と併用された場合は無視する。 - `--mode` (任意): `short`(デフォルト)または `long`。メッセージ形式を指定。 - `--scope` (任意): スコープを明示指定。省略時は差分から自動推定。 - `--lang` (任意): メッセージ本文の記述言語。`en`(デフォルト)または `ja`。type と scope は常に英語。 - `--export-dir` (任意): **`--suggest` モード専用**。提案メッセージを `commit-{YYYYMMDDHHMMSS}-{title}.txt` のファイル名で保存するディレクトリ。コミット実行モードで指定された場合は警告して無視する。 呼び出し時に `--suggest` を含むかどうかでモードが分岐する。以下、本文では特に断りがない限り「コミット実行モード」を前提に記述する。 ## モード分岐の判定 呼び出し引数を解析し、最初に以下を決定する: 1. `--suggest` が含まれる → **提案モード**(後述の「提案モード」セクションへ) 2. それ以外 → **コミット実行モード**(以降の Step 1 から実行) `--push` がコミット実行モードで指定された場合、Step 6 で push を行う。 `--auto` がコミット実行モードで指定された場合、Step 2 のステージング対象確認と Step 5 のメッセージ承認確認を省略する。 ## コミット実行モード ### Step 1: 差分情報の収集 以下の順序で git の差分を取得する: 1. `git status --short` で現在の作業ツリー全体の状態を把握する 2. `git diff --cached --stat` でステージ済み変更のサマリを確認 3. ステージ済み変更がある場合 → `git diff --cached` で詳細を取得 4. ステージ済み変更がない場合 → `git diff --stat` と `git diff` で未ステージ変更を取得 5. どちらもない、かつ未追跡ファイルもない場合 → 「コミット対象の変更がありません」と報告して終了 新規追加(untracked)ファイルは `git diff` には現れないため、`git status --short` の `??` 行から個別に拾い、内容が必要なら `git diff --no-index /dev/null ` で参照する。 ### Step 2: ステージング対象の決定 `--auto` の有無で分岐する。 #### 通常時(`--auto` なし) 「どこまでをこのコミットに含めるか」を必ずユーザーに確認する。完全に自動で `git add` してはいけない(意図しないファイルが混入する事故を防ぐため)。 ##### 確認の流れ 1. 現在のステージ済みファイルと未ステージ変更・未追跡ファイルを一覧で表示する。 ``` 【ステージ済み】 - path/to/foo.ts (modified) - path/to/bar.ts (added) 【未ステージ】 - path/to/baz.ts (modified) - path/to/qux.ts (untracked) ``` 2. 推奨案を含む複数の選択肢を提示して以下を確認する: - **ステージ済みのみコミット**: 既に `git add` 済みのものだけを対象にする - **未ステージも含めて全てコミット**: 表示中の未ステージ変更・未追跡ファイルもまとめてステージしてコミット - **対象ファイルを個別指定**: どのファイルを含めるかをユーザーがテキストで指定(パス列挙) - **中止**: 何もしない 3. 「全てコミット」または「個別指定」が選ばれた場合は `git add ` でステージング。完了後 `git diff --cached --stat` で確定内容を再確認させる。 ステージ済みも未ステージも両方無い場合(未追跡ファイルのみ)でも、ユーザーが「これをコミットしたい」と意図している可能性が高いため、未追跡ファイル一覧を提示して「全て追加 / 個別指定 / 中止」を選ばせる。 #### `--auto` 指定時 ステージング対象の確認を行わず、既にステージ済みの変更だけをコミット対象として確定する。`git add` は実行せず、未ステージ変更・未追跡ファイルは対象外として作業ツリーに残す。 - ステージ済み変更がある場合: `git diff --cached --stat` を情報として表示し、確認を待たず Step 3 へ進む - ステージ済み変更がない場合: 「`--auto` でコミットできるステージ済みの変更がありません」と報告し、`git add` と `git commit` を実行せず終了する ### Step 3: 会話コンテキストの分析 現在の会話履歴から以下を抽出する: - ユーザーが依頼した作業内容(「なぜ」この変更が必要だったか) - 実装中に行った設計上の判断やトレードオフ - 解決した問題やバグの内容 会話コンテキストが不十分な場合は差分内容のみから推定する。「なぜ」を捉えるのに会話の情報は非常に有用なので、可能な限り活用する。 ### Step 4: Conventional Commits の分類 差分と会話コンテキストから、以下の要素を決定する。 #### type(必須) | type | 用途 | |------|------| | `feat` | 新機能の追加 | | `fix` | バグ修正 | | `docs` | ドキュメントのみの変更 | | `style` | コードの意味に影響しない変更(フォーマット、セミコロン等) | | `refactor` | バグ修正でも機能追加でもないコード変更 | | `perf` | パフォーマンス改善 | | `test` | テストの追加・修正 | | `build` | ビルドシステムや外部依存の変更 | | `ci` | CI 設定ファイルやスクリプトの変更 | | `chore` | その他(上記に当てはまらない保守作業) | 複数の type にまたがる変更の場合は、最も主要な変更の type を選択する。明確に分離可能な場合は「複数のコミットに分けることを推奨する」旨をアドバイスとして付記し、ユーザーに分割を提案する。 #### scope(任意) 変更の影響範囲を表す短い名詞。差分のファイルパスやディレクトリ構造から推定する。 - 変更が単一のモジュール/ディレクトリに閉じている → そのディレクトリ名 - 複数にまたがるが共通の親がある → 親ディレクトリ名 - 広範囲 → 省略 `--scope` で明示指定された場合はそれを優先する。 #### description(必須) 変更内容を簡潔に表す命令形フレーズ。先頭は小文字、末尾にピリオドは付けない。 - `--lang en`(デフォルト): 英語で記述 - 良い例: `add user authentication with JWT` - 悪い例: `Added user authentication.` / `User authentication was added` - `--lang ja`: 日本語で記述 - 良い例: `JWTによるユーザー認証を追加` - 悪い例: `JWTによるユーザー認証を追加しました。` ユーザーが会話中に「日本語で」「英語で」等を明示した場合は引数より優先する。 ### Step 5: メッセージの生成と承認 #### shortモード ``` type(scope): description ``` scope なしなら `type: description`。全体 72 文字以内を目指し、Breaking change がある場合は `type(scope)!: description`。 #### longモード ``` type(scope): description 本文(なぜこの変更が必要だったかの説明) - 変更点1の説明 - 変更点2の説明 BREAKING CHANGE: (あれば)破壊的変更の説明 ``` - 本文最初の段落で「なぜ」を述べる(会話コンテキストから抽出) - 主要変更点を箇条書きで列挙(差分から抽出) - 72 文字で折り返す - `--lang` で指定された言語で記述 #### 承認フロー `--auto` の有無で分岐する。 ##### 通常時(`--auto` なし) 生成したメッセージをコードブロックでユーザーに提示し、推奨案を含む複数の選択肢を提示して以下を選ばせる: 1. **実行**: このメッセージで `git commit` を実行 2. **メッセージ修正**: ユーザーから自由記述でフィードバックを受け取り、Step 4 に戻ってメッセージを再生成し、再度承認を求める(無限ループに見えないよう、修正要望の要点を確認しつつ進める) 3. **中止**: 何もせず終了 修正フィードバック例: - 「type は refactor にして」→ type を変更して再生成 - 「日本語にして」→ `--lang ja` 相当として再生成 - 「もっと簡潔に」→ description を短くして再生成 修正は何回繰り返してもよい。ユーザーが満足するまで対話する。 ##### `--auto` 指定時 生成したメッセージをコードブロックでユーザーに提示するが、選択肢提示による承認確認は行わず、そのまま Step 6 に進んで `git commit` を実行する。 `--auto` は Step 2 のステージング対象確認と Step 5 のメッセージ承認確認を省略する。`--push` 併用時の Step 7 の main/master への直接 push 確認は省略しない。 ### Step 6: コミットの実行 通常時は承認を得たら、`--auto` 指定時はメッセージ生成後、HEREDOC を使って `git commit -m` を実行する。**Co-Authored-By 行は付与しない**。 ```bash git commit -m "$(cat <<'EOF' feat(auth): add JWT-based authentication セッションCookieによる認証はモバイルAPIクライアントで問題が 発生していた。JWTトークンにより、全クライアントで動作する ステートレスな認証機構を実現する。 - JWTトークンの生成・検証ミドルウェアを追加 - リフレッシュトークンのローテーションを実装 EOF )" ``` #### pre-commit hook の扱い pre-commit hook は**常に実行する**。`--no-verify` 相当のオプションは提供しない。hook が失敗した場合: 1. 失敗内容をそのままユーザーに伝える 2. 修正方針(ファイル修正してから再コミット / 中止)をユーザーに委ねる 3. このスキル内で安易に再試行や `--no-verify` 適用は行わない #### コミット後の確認 成功時: - `git log -1 --format='%h %s'` で作成されたコミットの SHA と件名を表示 - `git status --short` で残っている変更があるか報告 ### Step 7: push(`--push` 指定時のみ) `--push` が指定されていた場合のみ、以下を行う: 1. 現在のブランチ名を `git symbolic-ref --short HEAD` で取得 2. リモート追跡ブランチが設定済みか `git rev-parse --abbrev-ref --symbolic-full-name @{u}` で確認 3. 未設定なら `git push -u origin `、設定済みなら `git push` 4. main / master ブランチへの直接 push を検出したら、実行前に選択肢提示で「本当に main へ push するか」を確認する `--push` が指定されていない場合は push せず、「コミット完了。push が必要な場合はユーザー側で実行してください」と報告して終了する。 ## 提案モード(`--suggest` 指定時) 旧バージョンと同等の動作。コミットは一切実行しない。 ### フロー 1. **差分情報の収集**: コミット実行モードの Step 1 と同じ 2. **会話コンテキストの分析**: 同 Step 3 3. **Conventional Commits の分類**: 同 Step 4 4. **メッセージの生成**: 同 Step 5 のメッセージ生成部分まで 5. **提案の提示**: - 生成したメッセージをコードブロックで表示 - 複数コミットに分割すべきと判断した場合は分割案も提示 - type の選択が微妙な場合は代替案も提示(例: 「`refactor` としましたが、`chore` も妥当です」) 6. **ファイル保存**(`--export-dir` 指定時のみ): - 指定ディレクトリに `commit-{YYYYMMDDHHMMSS}-{title}.txt` の名前で保存 - ディレクトリが未指定で、かつユーザーが保存を望むか不明な場合は選択肢提示でデフォルト `./tmp/` を提示 `--export-dir` がコミット実行モードで指定された場合は、「提案モード専用オプションのため無視します」と一言警告した上でコミット実行を続行する。 ## 出力例 ### コミット実行モード(shortモード, English) ``` feat(auth): add JWT-based authentication ``` → 承認 → `git commit` 実行 → `a1b2c3d feat(auth): add JWT-based authentication` を報告 ### コミット実行モード(longモード, 日本語) ``` feat(auth): JWTベースの認証を追加 セッションCookieによる認証はモバイルAPIクライアントで問題が 発生していた。JWTトークンにより、全クライアントで動作する ステートレスな認証機構を実現する。 - JWTトークンの生成・検証ミドルウェアを追加 - リフレッシュトークンのローテーションを実装 - 環境変数によるトークン有効期限の設定を追加 - ユーザーログインエンドポイントをJWTペア返却に変更 BREAKING CHANGE: /api/login のレスポンス形式がセッションCookie からaccess_tokenとrefresh_tokenを含むJSONボディに変更 ``` ### 提案モード 提案メッセージのみをコードブロックで提示し、コミットは実行しない。 ## 注意事項 - 通常時はステージング対象とコミットメッセージについて必ずユーザーの承認を得てから `git commit` を実行する。`--auto` 指定時は両方の承認を省略する。 - `--auto` 指定時は既にステージ済みの変更だけをコミットする。未ステージ変更・未追跡ファイルを自動で `git add` しない。 - 提案モードと実行モードを取り違えないよう、最初に `--suggest` の有無を判定する。 - `--auto` と `--suggest` が併用された場合は `--auto` を無視する(提案モードはコミットを実行しないため意味を持たない)。 - `--lang` で言語を指定可能。デフォルトは英語。type と scope は常に英語で記述する。 - `--lang` 未指定でも、ユーザーが会話中に「日本語で」等と明示した場合は `--lang ja` と同等に扱う。 - pre-commit hook は常に実行する。`--no-verify` は提供しない。 - Co-Authored-By 行は付与しない(ユーザーが必要と判断した場合は手動で追記してもらう)。 - push は `--push` 指定時のみ。main/master への push は実行前に追加確認する。