Last active
December 19, 2025 05:17
-
-
Save ericclemmons/2a23cc0595c7570fd08f4fa2d3ddef48 to your computer and use it in GitHub Desktop.
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
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| COMMIT_MSG_FILE="$1" | |
| COMMIT_SOURCE="${2-}" | |
| # Allow opting out for a single commit or CI. | |
| if [ "${OPENCODE_COMMIT_MSG_DISABLE:-}" = "1" ]; then | |
| exit 0 | |
| fi | |
| # Skip merge/squash/amend flows; they already have meaningful defaults. | |
| case "$COMMIT_SOURCE" in | |
| merge|squash|commit) | |
| exit 0 | |
| ;; | |
| esac | |
| # If there's already a non-comment, non-empty line, do nothing. | |
| if grep -qvE '^[[:space:]]*($|#)' "$COMMIT_MSG_FILE"; then | |
| exit 0 | |
| fi | |
| # Only generate if opencode is available. | |
| if ! command -v opencode >/dev/null 2>&1; then | |
| exit 0 | |
| fi | |
| MODEL="${OPENCODE_COMMIT_MODEL:-opencode/grok-code}" | |
| # Write the prompt to a temp file | |
| PROMPT_FILE="$(mktemp)" | |
| cat > "$PROMPT_FILE" <<EOF | |
| Write a git commit message. | |
| Rules: | |
| - Line 1: subject (max 72 chars), imperative mood. | |
| - Then a blank line. | |
| - Then an optional body in Markdown (bullets OK). Keep lines <= 72 chars when possible. | |
| - Output ONLY the commit message. Do not wrap in code fences. | |
| - **DO NOT MAKE ANY TOOL CALLS OR PERFORM ANY GIT OR FILE OPERATIONS** | |
| Context: | |
| Branch: $(git symbolic-ref --quiet --short HEAD 2>/dev/null || echo "DETACHED") | |
| Staged changes (stat): | |
| $(git diff --staged --stat 2>/dev/null || true) | |
| Staged diff: | |
| $(git diff --staged 2>/dev/null | head -c 8000 || true) | |
| If there are no staged changes, still generate a sensible message. | |
| EOF | |
| printf "🤖 Generating default commit message (model: %s)…\n" "$MODEL" >&2 | |
| # Run opencode with permissions that deny file/git operations | |
| MESSAGE="$(OPENCODE_PERMISSION='{"bash":"deny","edit":"deny","write":"deny","webfetch":"deny","external_directory":"deny"}' opencode run --model "$MODEL" "$(cat "$PROMPT_FILE")" 2>/dev/null || true)" | |
| rm "$PROMPT_FILE" | |
| # Write the generated message to the commit message file | |
| if [ -n "$MESSAGE" ]; then | |
| MESSAGE="${MESSAGE%$'\n'}"$'\n\n'"🤖 Generated by $MODEL" | |
| ORIGINAL="$(cat "$COMMIT_MSG_FILE")" | |
| printf "%s\n\n%s" "$MESSAGE" "$ORIGINAL" > "$COMMIT_MSG_FILE" | |
| fi | |
| # WORKAROUND: opencode appears to stage files even with bash/edit/write denied | |
| # when run inside a git hook (but not when run manually with the same command). | |
| # This corrupts the git index, causing "invalid object" errors. | |
| # Nuclear fix: rebuild the index from HEAD to unstage any files opencode touched. | |
| # | |
| # 🚨 I've isolated this to **ONLY HAPPEN WHEN OPENCODE EXECUTES INSIDE THE GIT HOOK** | |
| rm -f .git/index | |
| git reset --quiet 2>/dev/null || true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment