Created
February 9, 2026 14:55
-
-
Save dkotama/3c4fd191cc81056e0e17e0b3c89336f1 to your computer and use it in GitHub Desktop.
git-acommit - Git Auto Commit message using Openrouter Free LLM Inference
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/bash | |
| # git-acommit: AI-powered auto commit using OpenRouter | |
| # Static API key (as requested) | |
| OPENROUTER_API_KEY=OPENROUTER_API_KEY | |
| # Colors for output | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| NC='\033[0m' # No Color | |
| # Check if we're in a git repository | |
| if ! git rev-parse --git-dir > /dev/null 2>&1; then | |
| echo -e "${RED}β Not a git repository${NC}" | |
| exit 1 | |
| fi | |
| # Parse arguments | |
| DRY_RUN=false | |
| while [[ $# -gt 0 ]]; do | |
| case $1 in | |
| --preview|-p) | |
| DRY_RUN=true | |
| shift | |
| ;; | |
| --help|-h) | |
| echo "Usage: git acommit [options]" | |
| echo "" | |
| echo "Options:" | |
| echo " -p, --preview Preview the generated message without committing" | |
| echo " -h, --help Show this help message" | |
| echo "" | |
| echo "Automatically generates a commit message using OpenRouter AI" | |
| exit 0 | |
| ;; | |
| *) | |
| echo -e "${RED}Unknown option: $1${NC}" | |
| exit 1 | |
| ;; | |
| esac | |
| done | |
| # Get staged diff, if empty stage all changes | |
| DIFF=$(git diff --cached --no-color 2>/dev/null) | |
| if [ -z "$DIFF" ]; then | |
| echo -e "${YELLOW}β οΈ No staged changes found. Staging all modifications...${NC}" | |
| git add -A | |
| DIFF=$(git diff --cached --no-color 2>/dev/null) | |
| fi | |
| if [ -z "$DIFF" ]; then | |
| echo -e "${RED}β No changes to commit${NC}" | |
| exit 1 | |
| fi | |
| # Build the prompt with the diff | |
| PROMPT="Write a concise, meaningful git commit message (max 50-72 characters) for these code changes. Be specific but brief. Do not wrap in quotes. Changes: | |
| $DIFF" | |
| # Create JSON payload using Python for proper escaping (more reliable than shell) | |
| # If python is not available, fall back to shell method | |
| if command -v python3 &> /dev/null; then | |
| JSON_PAYLOAD=$(python3 -c " | |
| import json | |
| import sys | |
| prompt = sys.argv[1] | |
| payload = { | |
| 'model': 'openrouter/free', | |
| 'messages': [ | |
| {'role': 'user', 'content': prompt} | |
| ] | |
| } | |
| print(json.dumps(payload)) | |
| " "$PROMPT") | |
| elif command -v python &> /dev/null; then | |
| JSON_PAYLOAD=$(python -c " | |
| import json | |
| import sys | |
| prompt = sys.argv[1] | |
| payload = { | |
| 'model': 'openrouter/free', | |
| 'messages': [ | |
| {'role': 'user', 'content': prompt} | |
| ] | |
| } | |
| print(json.dumps(payload)) | |
| " "$PROMPT") | |
| else | |
| # Fallback: manual escaping (basic) | |
| ESCAPED_PROMPT=$(echo "$PROMPT" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g' | tr '\n' ' ' | sed 's/ */ /g') | |
| JSON_PAYLOAD="{\"model\":\"openrouter/free\",\"messages\":[{\"role\":\"user\",\"content\":\"$ESCAPED_PROMPT\"}]}" | |
| fi | |
| echo -e "${BLUE}π€ Generating commit message via OpenRouter...${NC}" | |
| # Call OpenRouter API | |
| RESPONSE=$(curl -s -X POST https://openrouter.ai/api/v1/chat/completions \ | |
| -H "Content-Type: application/json" \ | |
| -H "Authorization: Bearer $OPENROUTER_API_KEY" \ | |
| -d "$JSON_PAYLOAD" 2>/dev/null) | |
| # Check if curl failed | |
| if [ $? -ne 0 ]; then | |
| echo -e "${RED}β Failed to connect to OpenRouter API${NC}" | |
| exit 1 | |
| fi | |
| # Extract the commit message using Python if available (most reliable) | |
| if command -v python3 &> /dev/null; then | |
| COMMIT_MSG=$(echo "$RESPONSE" | python3 -c " | |
| import json | |
| import sys | |
| try: | |
| data = json.load(sys.stdin) | |
| content = data['choices'][0]['message']['content'] | |
| print(content) | |
| except Exception as e: | |
| print('') | |
| ") | |
| elif command -v python &> /dev/null; then | |
| COMMIT_MSG=$(echo "$RESPONSE" | python -c " | |
| import json | |
| import sys | |
| try: | |
| data = json.load(sys.stdin) | |
| content = data['choices'][0]['message']['content'] | |
| print(content) | |
| except Exception as e: | |
| print('') | |
| ") | |
| else | |
| # Fallback: grep/sed extraction | |
| COMMIT_MSG=$(echo "$RESPONSE" | sed -n 's/.*"content":"\([^"]*\)".*/\1/p' | head -1) | |
| COMMIT_MSG=$(echo "$COMMIT_MSG" | sed 's/\\n/\n/g; s/\\t/\t/g; s/\\"/"/g; s/\\\\/\\/g') | |
| fi | |
| # Fallback if extraction failed | |
| if [ -z "$COMMIT_MSG" ] || [ "$COMMIT_MSG" = "null" ]; then | |
| echo -e "${YELLOW}β οΈ Failed to generate message from AI${NC}" | |
| echo -e "${YELLOW}Raw response: $RESPONSE${NC}" | |
| COMMIT_MSG="Update code" | |
| fi | |
| # Clean up the message - remove surrounding quotes if present, trim whitespace | |
| COMMIT_MSG=$(echo "$COMMIT_MSG" | sed 's/^["'"'"']*//;s/["'"'"']*$//' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') | |
| echo "" | |
| echo -e "${GREEN}π Generated commit message:${NC}" | |
| echo " $COMMIT_MSG" | |
| echo "" | |
| # If dry run, exit here | |
| if [ "$DRY_RUN" = true ]; then | |
| echo -e "${BLUE}βΉοΈ Preview mode - not committing${NC}" | |
| exit 0 | |
| fi | |
| # Ask for confirmation | |
| read -p "Commit with this message? [Y/n/e(edit)]: " CONFIRM | |
| case "$CONFIRM" in | |
| [Nn]*) | |
| echo -e "${RED}β Aborted${NC}" | |
| exit 0 | |
| ;; | |
| [Ee]*) | |
| read -p "Enter your commit message: " CUSTOM_MSG | |
| if [ -z "$CUSTOM_MSG" ]; then | |
| echo -e "${RED}β Empty message, aborting${NC}" | |
| exit 1 | |
| fi | |
| COMMIT_MSG="$CUSTOM_MSG" | |
| ;; | |
| *) | |
| # Proceed with commit | |
| ;; | |
| esac | |
| # Perform the commit | |
| git commit -m "$COMMIT_MSG" | |
| if [ $? -eq 0 ]; then | |
| echo -e "${GREEN}β Committed successfully!${NC}" | |
| else | |
| echo -e "${RED}β Commit failed${NC}" | |
| exit 1 | |
| fi |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How it works:
Workflow:
Example output:
π€ Generating commit message via OpenRouter...
π Generated commit message:
Append "modified content" to test.txt
Commit with this message? [Y/n/e(edit)]:
Notes:
β’ Uses Python for JSON escaping (most reliable method)
β’ Falls back to shell-based extraction if Python unavailable
β’ The API key is embedded in the script (not via env var)
β’ Added ~/bin to your ~/.zshrc PATH