Created
July 31, 2026 13:57
-
-
Save dragonworx/3299365ced9c909e94c2acd020f245c6 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
| # ── 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 } | |
| 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