Created
May 13, 2025 16:50
-
-
Save gretel/a36b3ca8b593cbc3c8bf833851822a61 to your computer and use it in GitHub Desktop.
Git hook that uses LLMs via OpenWebUI to automatically generate conventional commit messages from staged changes
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
#!/bin/sh | |
# 1. Save as .git/hooks/prepare-commit-msg in your repository | |
# 2. Make executable with chmod +x .git/hooks/prepare-commit-msg | |
# 3. Set required environment variables: | |
# export OPENWEBUI_API_URL="https://your-openwebui-instance.com" | |
# export OPENWEBUI_API_TOKEN="your_token_here" | |
# export OPENWEBUI_API_MODEL="claude-3-7-sonnet" # Optional | |
# 4. Stage your changes with git add and commit normally with git commit | |
# Get the commit message from the temporary file | |
COMMIT_MSG_FILE="$1" | |
COMMIT_SOURCE="$2" | |
# Check for required environment variables | |
if [ -z "$OPENWEBUI_API_URL" ]; then | |
echo "Error: OPENWEBUI_API_URL environment variable is not set." >&2 | |
exit 1 | |
fi | |
if [ -z "$OPENWEBUI_API_TOKEN" ]; then | |
echo "Error: OPENWEBUI_API_TOKEN environment variable is not set." >&2 | |
exit 1 | |
fi | |
# Use configured model or default to claude-3-7-sonnet | |
MODEL=${OPENWEBUI_API_MODEL:-claude-3-7-sonnet} | |
# Skip processing if this is a merge, rebase, etc. | |
if [ -n "$COMMIT_SOURCE" ] && [ "$COMMIT_SOURCE" != "message" ]; then | |
echo "Skipping LLM commit message for $COMMIT_SOURCE." >&2 | |
exit 0 | |
fi | |
# Get the git diff to understand what changed | |
DIFF=$(git diff --cached) | |
# Check if there are staged changes | |
if [ -z "$DIFF" ]; then | |
echo "Warning: No staged changes found." >&2 | |
exit 0 # Exit without error so the commit can continue | |
fi | |
# Create temporary files | |
TEMP_PROMPT_FILE=$(mktemp) | |
TEMP_FULL_PROMPT=$(mktemp) | |
# Write the prompt and diff to files | |
cat > "$TEMP_PROMPT_FILE" << 'EOT' | |
Generate a conventional commit message based on this git diff. | |
Follow the format 'type(scope): description' where type is one of: feat, fix, docs, style, refactor, perf, test, build, ci, chore. | |
Keep it concise, clear, and on one line. | |
Be sparse but friendly and supportive. | |
Output in the language best matching the language used in the git diff. | |
Here's the diff: | |
EOT | |
cat "$TEMP_PROMPT_FILE" > "$TEMP_FULL_PROMPT" | |
echo "$DIFF" >> "$TEMP_FULL_PROMPT" | |
# Use Python to properly JSON-encode the prompt | |
if command -v python3 >/dev/null 2>&1; then | |
JSON_ENCODED_PROMPT=$(python3 -c "import json, sys; print(json.dumps(sys.stdin.read()))" < "$TEMP_FULL_PROMPT") | |
else | |
JSON_ENCODED_PROMPT=$(python -c "import json, sys; print(json.dumps(sys.stdin.read()))" < "$TEMP_FULL_PROMPT") | |
fi | |
# Create the JSON payload | |
PAYLOAD="{\"model\":\"$MODEL\",\"messages\":[{\"role\":\"user\",\"content\":$JSON_ENCODED_PROMPT}],\"stream\":false,\"temperature\":0.1}" | |
# Send request to OpenWebUI API | |
RESPONSE=$(curl -s -X POST "$OPENWEBUI_API_URL/api/chat/completions" \ | |
-H "Content-Type: application/json" \ | |
-H "Authorization: Bearer $OPENWEBUI_API_TOKEN" \ | |
-d "$PAYLOAD") | |
# Clean up temp files | |
rm -f "$TEMP_PROMPT_FILE" "$TEMP_FULL_PROMPT" | |
# Extract the message from the response | |
SUGGESTED_MSG=$(echo "$RESPONSE" | grep -o '"content":"[^"]*"' | head -1 | sed 's/"content":"//;s/"$//') | |
# Write the suggested message to the commit message file | |
if [ -n "$SUGGESTED_MSG" ]; then | |
# Save comments (lines starting with #) | |
COMMENTS=$(grep "^#" "$COMMIT_MSG_FILE" || true) | |
# Write our message, then the comments | |
echo "$SUGGESTED_MSG" > "$COMMIT_MSG_FILE" | |
if [ -n "$COMMENTS" ]; then | |
echo "$COMMENTS" >> "$COMMIT_MSG_FILE" | |
fi | |
echo "Commit message: $SUGGESTED_MSG" >&2 | |
else | |
echo "Could not generate commit message. Using default template." >&2 | |
fi | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment