DEV Community

Lucas Neves Pereira
Lucas Neves Pereira

Posted on

I Built a CLI Tool That Writes My Commit Messages

Hello guys! We've all been there. You just finished a feature, you're ready to commit, and then you stare at the terminal for 30 seconds trying to come up with a decent commit message.

Sometimes I'd spend more time thinking about the message than writing the actual code. So I did what any developer would do. I automated it.

How it started

I already had Claude installed on my machine. One day I realized I could just pipe my git diff into it and ask for a commit message. So I added this little function to my .zshrc:

gpm() {
  git diff HEAD | claude -p "propose a conventional commit message for these changes. output only the message, nothing else."
}
Enter fullscreen mode Exit fullscreen mode

That was it. Run gpm, get a message, copy paste it. Simple.

Then I wanted to go further. Why not commit directly with the proposed message?

gac() {
  msg=$(git diff HEAD | claude -p "propose a conventional commit message for these changes, one line only. output only the message, nothing else.")
  echo "\n$msg\n"
  read "confirm?Commit with this message? [y/N] "
  if [[ "$confirm" == "y" ]]; then
    git add -A && git commit -m "$msg"
  fi
}
Enter fullscreen mode Exit fullscreen mode

This worked great for a while. But I kept wanting more. What about code review? PR descriptions? What if I could choose the model? What about using the API directly instead of going through the CLI?

At some point I realized these shell functions were becoming a full tool. So I decided to build one.

Meet claude-git

claude-git is a CLI that reads your git diff and sends it to Claude to generate commit messages, review code, write PR descriptions, and more. It's written in bash, runs entirely in your terminal, and installs in one command.

curl -fsSL https://raw.githubusercontent.com/lucasnevespereira/claude-git/main/install.sh | bash
Enter fullscreen mode Exit fullscreen mode

Let's go through the main features.

Proposing a commit message

The most basic command. Stage your changes, run claude-git msg, and you get a conventional commit message.

claude-git msg
# -> feat: add user authentication with JWT tokens
Enter fullscreen mode Exit fullscreen mode

That's it. It reads the diff, sends it to Claude, and outputs a message. You can copy it or use it however you want.

Committing directly

If you don't want to copy paste, claude-git commit will propose a message and ask you to confirm before committing.

claude-git commit

feat: add user authentication with JWT tokens

Commit with this message? [y/N] y
Enter fullscreen mode Exit fullscreen mode

And if you're feeling confident and want to skip the confirmation:

claude-git commit -y
Enter fullscreen mode Exit fullscreen mode

Prefix mode

At work we often need to prefix commits with a ticket ID. Something like PROJ-42: fix login redirect. I got tired of typing the prefix manually so I added a prefix command that auto detects the ticket from your branch name.

If your branch is called feature/PROJ-42-login-fix, running claude-git prefix will automatically extract PROJ-42 and prepend it to the message.

claude-git prefix
# -> PROJ-42: fix login redirect after session expiry
Enter fullscreen mode Exit fullscreen mode

You can also pass the prefix manually:

claude-git prefix PROJ-42
Enter fullscreen mode Exit fullscreen mode

Code review

Before pushing, I sometimes want a quick sanity check. The review command sends your diff to Claude and asks it to flag bugs, security issues, or logic errors.

claude-git review
Enter fullscreen mode Exit fullscreen mode

It's not a replacement for a real code review, but it's useful to catch obvious mistakes before opening a PR.

PR descriptions

Writing PR descriptions is another thing that takes longer than it should. The pr command looks at all commits and the full diff against your base branch and generates a structured description.

claude-git pr
Enter fullscreen mode Exit fullscreen mode

By default it compares against main, but you can specify another branch:

claude-git pr develop
Enter fullscreen mode Exit fullscreen mode

Explaining changes

Sometimes you come back to some changes you made yesterday and forgot what they do. The explain command gives you a quick summary.

claude-git explain
# -> These changes add rate limiting to the API endpoints using a token bucket...
Enter fullscreen mode Exit fullscreen mode

Short aliases

I like short commands. The installer automatically adds aliases to your shell config:

cg      # claude-git
cgm     # claude-git msg
cgc     # claude-git commit
cgcy    # claude-git commit --yes
cgrev   # claude-git review
cgpr    # claude-git pr
cgex    # claude-git explain
cgpx    # claude-git prefix
Enter fullscreen mode Exit fullscreen mode

So in practice, committing with AI looks like this:

cgcy
Enter fullscreen mode Exit fullscreen mode

Three characters and you're done.

Configuration

You can configure the model, the max diff size, and whether to use the API directly or go through the Claude CLI.

claude-git config model sonnet      # use a more capable model
claude-git config api_key sk-ant-...  # use API calls directly (faster)
claude-git config max_lines 5000    # handle larger diffs
Enter fullscreen mode Exit fullscreen mode

By default it uses Haiku which is fast and cheap. If you set an API key, it will call the Anthropic API directly instead of going through Claude Code, which is noticeably faster.

The config lives in ~/.claude-git as a simple key=value file. Nothing fancy.

Why bash?

I get this question a lot. Bash is not glamorous. But for a tool that wraps git commands and pipes text to an API, it's actually the perfect fit. No compile step, no dependencies, no runtime. It just works on any machine that has bash and git.

The entire tool is a single file. That makes it easy to install, easy to read, and easy to contribute to.

What I learned

Building this tool taught me a few things. First, sometimes the best projects come from automating your own annoyances. I didn't sit down and plan this. It grew from a two line function in my shell config.

Second, keeping things simple pays off. bash is not the fanciest choice but it made the tool easy to distribute and maintain. No build system, no package manager drama.

And finally, AI is really good at reading diffs. The commit messages Claude generates are genuinely useful. Most of the time I accept them as is.

Try it out

If you want to give it a try:

curl -fsSL https://raw.githubusercontent.com/lucasnevespereira/claude-git/main/install.sh | bash
Enter fullscreen mode Exit fullscreen mode

The repo is here: github.com/lucasnevespereira/claude-git

It's open source under MIT. Feedback and contributions are welcome.

Hope you find it useful!

Top comments (0)