Created
November 29, 2025 16:29
-
-
Save u1aryz/6a2e18818bd16c304280a6701b90fb6a to your computer and use it in GitHub Desktop.
Generate and select AI-powered commit messages
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| function aicommit -d "Generate and select AI-powered commit messages" | |
| # Parse arguments using argparse | |
| argparse -n aicommit h/help -- $argv | |
| or return | |
| if set -q _flag_help | |
| echo "使い方: aicommit [オプション]" | |
| echo "" | |
| echo "AIを使用してConventional Commit形式のコミットメッセージを生成し、選択してコミットします。" | |
| echo "言語とAIプロバイダーはfzfで対話的に選択します。" | |
| echo "" | |
| echo "オプション:" | |
| echo " -h, --help このヘルプメッセージを表示" | |
| return 0 | |
| end | |
| # Check if there are staged changes | |
| set -l diff_output (git diff --cached 2>&1) | |
| or begin | |
| echo "エラー: gitリポジトリではないか、gitコマンドが失敗しました" | |
| return 1 | |
| end | |
| test -n "$diff_output" | |
| or begin | |
| echo "ステージされた変更がありません。" | |
| return 0 | |
| end | |
| # Select language with fzf | |
| set -l lang (printf "ja\nen\n" | fzf --prompt="言語を選択: " --height=40% --reverse) | |
| if test -z "$lang" | |
| echo "キャンセルされました。" | |
| return 0 | |
| end | |
| # Select AI provider with fzf | |
| set -l provider (printf "claude\ncodex\ngemini\n" | fzf --prompt="AIプロバイダーを選択: " --height=40% --reverse) | |
| if test -z "$provider" | |
| echo "キャンセルされました。" | |
| return 0 | |
| end | |
| # Get git status for context (only staged files) | |
| set -l git_status (git diff --cached --name-status) | |
| # Prepare prompt | |
| set -l lang_instruction (test "$lang" = ja; and echo "in Japanese"; or echo "in English") | |
| set -l prompt "Analyze the following git diff and git status, then suggest 3 conventional commit messages $lang_instruction. | |
| Each message should follow this format: | |
| - type: subject format (no scope needed) | |
| - type should be one of: feat, fix, docs, style, refactor, test, chore, etc. | |
| - subject should concisely describe the changes | |
| - subject can start with either lowercase or uppercase letter | |
| - Each message should be a single line | |
| git status: | |
| $git_status | |
| git diff: | |
| $diff_output | |
| Output format: | |
| 1. <commit message 1> | |
| 2. <commit message 2> | |
| 3. <commit message 3> | |
| Output only the numbered messages in the above format. No explanations needed." | |
| # Call AI provider to generate commit messages | |
| echo "コミットメッセージを生成中 ($provider)..." | |
| # Use a temporary file to pass the prompt to avoid quoting issues | |
| set -l prompt_file (mktemp) | |
| echo "$prompt" >$prompt_file | |
| # Execute command based on provider with timeout | |
| set -l ai_output | |
| set -l ai_status | |
| switch $provider | |
| case claude | |
| set ai_output (timeout 60 claude --model sonnet -p <$prompt_file 2>&1) | |
| set ai_status $status | |
| case gemini | |
| set ai_output (timeout 60 sh -c "cat '$prompt_file' | gemini --model flash-lite 2>&1") | |
| set ai_status $status | |
| case codex | |
| set ai_output (timeout 60 sh -c "cat '$prompt_file' | codex --model codex-mini-latest exec - 2>&1") | |
| set ai_status $status | |
| end | |
| rm -f $prompt_file | |
| # Check for timeout (exit code 124) | |
| if test $ai_status -eq 124 | |
| echo "エラー: AI CLI ($provider) の呼び出しがタイムアウトしました (60秒)" | |
| return 1 | |
| end | |
| if test $ai_status -ne 0 | |
| echo "エラー: AI CLI ($provider) の呼び出しに失敗しました (exit code: $ai_status)" | |
| echo "$ai_output" | |
| return 1 | |
| end | |
| # Parse the output to extract commit messages | |
| set -l messages_file (mktemp) | |
| echo "$ai_output" | perl -pe 's/ (\d+)\. /\n$1. /g' | grep '^\d\.' | sed -E 's/^[0-9]+\. //' >$messages_file | |
| # Check if we found any messages | |
| set -l message_count (wc -l <$messages_file | string trim) | |
| if test "$message_count" -eq 0 | |
| echo "エラー: AIの出力からコミットメッセージをパースできませんでした" | |
| echo "AIの出力:" | |
| echo "$ai_output" | |
| rm -f $messages_file | |
| return 1 | |
| end | |
| # Let user select a message with fzf | |
| set -l selected (fzf --prompt="コミットメッセージを選択: " --height=40% --reverse <$messages_file) | |
| set -l messages (cat $messages_file) | |
| rm -f $messages_file | |
| if test -z "$selected" | |
| echo "キャンセルされました。生成されたコミットメッセージ:" | |
| printf '%s\n' $messages | |
| return 0 | |
| end | |
| # Perform the commit | |
| if git commit -m "$selected" | |
| echo "コミットが完了しました: $selected" | |
| else | |
| echo "エラー: コミットに失敗しました" | |
| return 1 | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment