Skip to main content
Nick Sergeant
August 20, 2025

Have Claude Code write your commit messages automatically

I've been using Claude Code for many things lately such as coding, writing technical plans, drafting copy for review, analyzing harebrained financial scenarios, and summarizing articles that were probably written by AI.

While sometimes Claude is writing commit messages for the work it's doing, I still, gasp, write code manually from time-to-time, and outside of my day job I'm not the best at writing descriptive commit messages. Which is a shame, because I do find myself grepping old commit messages fairly often trying to find things.

So I (...Claude) wrote a zsh function that stages everything, passes the diff to Claude, and gets back a properly formatted commit message. Here's what it looks like in action:

GIF demo here showing: typing gcam, Claude generating a message, vim opening with the message, editing if needed, then committing

...which resulted in this commit.

The function itself is pretty straightforward:

gcam() {
  # Stage all changes
  git add -A
  
  # Get the staged diff
  local diff=$(git diff --cached)
  
  # Check if there are staged changes
  if [ -z "$diff" ]; then
    echo "No changes to commit"
    return 1
  fi
  
  # Generate commit message using Claude and edit it with nvim via vipe
  local final_msg=$(echo "$diff" | claude -p "Generate a simple, straightforward git commit message for these changes. Be concise but specific about what was changed. Include specific keywords and technical terms (function names, file types, configuration settings, etc.) that would be useful for searching commit history later. Do not be overly detailed. Use proper sentences with correct capitalization and punctuation, including periods at the end of sentences. Return only the commit message without any explanation or formatting." --output-format text | EDITOR=nvim vipe)
  
  # If the message is not empty, commit with it
  if [ -n "$final_msg" ]; then
    git commit -m "$final_msg"
  else
    echo "Commit aborted (empty message)"
    return 1
  fi
}

The stack here is simple: zsh function → git diff → Claude Code → vipe (for piping in-and-out of $EDITOR) -> nvim → git commit. Everything gets staged automatically, Claude generates a searchable commit message with the right technical terms, and you get a chance to edit it in nvim before it's committed. 🎉