Skip to content

Instantly share code, notes, and snippets.

@dragonworx
Created July 31, 2026 13:57
Show Gist options
  • Select an option

  • Save dragonworx/3299365ced9c909e94c2acd020f245c6 to your computer and use it in GitHub Desktop.

Select an option

Save dragonworx/3299365ced9c909e94c2acd020f245c6 to your computer and use it in GitHub Desktop.
# ── commit ───────────────────────────────────────────────────────────────────
# stage everything, let haiku write the message, then commit and push after a
# confirm. Enter or y accepts; esc, n or anything else leaves changes staged.
commit() {
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || {
print -u2 "commit: not inside a git repository"; return 1
}
# Colours stay empty when stdout isn't a terminal, so piping stays clean.
local C_RESET C_DIM C_BOLD C_GREEN C_RED
if [[ -t 1 ]]; then
C_RESET=$'\e[0m' C_DIM=$'\e[2m' C_BOLD=$'\e[1m' C_GREEN=$'\e[32m' C_RED=$'\e[31m'
fi
git add -A || return 1
if git diff --cached --quiet; then
print -u2 -- "${C_RED}commit:${C_RESET} nothing staged, working tree is clean"; return 1
fi
# Feed the diff in on stdin rather than letting claude shell out to git: no
# tool calls, no permission prompt, and nothing to narrate about. --stat goes
# first so the file list survives even when the diff itself gets truncated.
local diff raw msg
diff=$(git diff --cached --stat; print; git diff --cached | head -c 60000)
# Transient status line — haiku takes a few seconds and the wait is otherwise
# a blank screen. Erased in place on a tty, left as a plain line otherwise.
local files=$(git diff --cached --name-only | wc -l)
if [[ -t 1 ]]; then
print -n -- "${C_DIM}commit: reading ${files} staged file(s), writing message…${C_RESET}"
else
print -- "commit: reading ${files} staged file(s), writing message…"
fi
raw=$(print -r -- "$diff" | command claude --model haiku \
--append-system-prompt "You are a commit message generator. You reply with exactly one line and nothing else. You never explain your reasoning and never write a preamble." \
-p "Write the commit message for this staged diff. Format: '<type>: <summary>' \
where <type> is exactly one of feat, fix, doc, chore. Under 72 characters. \
Output only that one line.")
local rc=$?
[[ -t 1 ]] && print -n -- $'\r\e[2K'
(( rc == 0 )) || return 1
# Take the first line that actually looks like a commit message. Haiku likes
# to prepend a sentence of reasoning; this steps over it instead of committing it.
msg=$(print -r -- "$raw" | grep -m1 -E '^(feat|fix|doc|chore)(\([^)]+\))?!?: .+')
msg=${msg%"${msg##*[![:space:]]}"} # trim trailing space
if [[ -z $msg ]]; then
print -u2 -- "${C_RED}commit: no usable message in claude's output:${C_RESET}"
print -u2 -r -- "$raw"
print -u2 -- "${C_RED}commit:${C_RESET} changes left staged, nothing committed"
return 1
fi
print -r -- "${C_DIM}commit:${C_RESET} ${C_GREEN}${msg}${C_RESET}"
# Single keystroke, so esc registers on its own — a line read would swallow it
# until Enter. Read failure (EOF, no tty) aborts: no silent push off a pipe.
local key
print -n -- "${C_DIM}commit: commit and push? [${C_RESET}${C_BOLD}Y${C_RESET}${C_DIM}/n, esc cancels]${C_RESET} "
read -s -k 1 key || { print; return 1 }
print
case $key in
$'\n'|$'\r'|y|Y) ;;
*) print -u2 -- "${C_RED}commit: cancelled${C_RESET}, changes left staged"; return 1 ;;
esac
git commit -m "$msg" || return 1
if git rev-parse --abbrev-ref --symbolic-full-name '@{upstream}' >/dev/null 2>&1; then
git push
else
git push -u origin HEAD
fi
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment