Skip to content

Instantly share code, notes, and snippets.

@gretel
Created May 13, 2025 16:50
Show Gist options
  • Save gretel/a36b3ca8b593cbc3c8bf833851822a61 to your computer and use it in GitHub Desktop.
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
#!/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