Last Tuesday I was deep in a race condition in our WebSocket reconnect logic, hopping between three files, and by the time the tests went green I had a diff worth committing. Then I just... sat there. Was this a fix? A refactor? Both? What's the scope — 'ws', 'socket', 'realtime'? I stared at the cursor for sixty seconds writing literally nothing, the most expensive nothing I produce all day. I do that maybe eight times a day, and somewhere in there I realized I was losing close to an hour every week to the existential dread of a single line of text. Not to the code. To describing the code.
The embarrassing part is that I knew the Conventional Commits spec cold. I could recite the type list in my sleep. But knowing the rules and cheerfully applying them at 4:45pm on a Friday when you just want to push and go home are two completely different skills, and I only reliably had the first one. My commit history was a museum of good intentions: clean and disciplined for the first three commits of the day, then a slow descent into 'fix stuff', 'more', and the dreaded 'updates'.
The thirty-second fix
I grabbed the Turn a Git Diff into a Clean Conventional Commit Message prompt, wired it to a shell alias, and now I pipe `git diff --staged` straight into it with a one-line context note like 'guarding listener count on reconnect, ref #412'. I handed that race-condition diff to Claude Sonnet 4.6 and three seconds later got back `fix(ws): prevent double-emit on socket reconnect` with a tidy two-line body explaining that we now de-dupe listeners before re-binding. It picked the scope 'ws' off the file path. I did not have to think about a single character, which is exactly the point — the cognitive load of naming the change is now zero, and the part of my brain that used to seize up is free to think about the next problem.
Why Claude and why the XML tags
I picked Claude Sonnet 4.6 for this because the task is small, frequent, and needs to be cheap and fast — I run it dozens of times a day and I don't want to wait or pay for deep reasoning to format one line. The prompt leans on Claude's strength with structure: it wraps the diff in a `<diff>` block, the context in a `<context>` block, and lists the rules and the output format explicitly. Claude follows that kind of light XML scaffolding almost annoyingly well. The single most valuable instruction in the whole thing is 'output ONLY the commit message — no code fences, no preamble.' Earlier versions I tried with a looser prompt would return 'Here's a great commit message for you!' and I'd have to delete the pleasantry every single time, which defeats the entire purpose of saving keystrokes.
The things it does that I always forget
Claude is genuinely good at the boring discipline I let slide once the day gets long. The 'think before you write' instruction means it actually reads the diff before deciding the type, so it doesn't just pattern-match 'there's a new function, must be feat.'
- It infers the scope from the file paths, so I never have to invent one or argue with myself about whether 'realtime' or 'ws' is the canonical name
- When I accidentally renamed a public export, it added a BREAKING CHANGE footer naming the exact symbol — I'd absolutely have shipped that as a plain 'refactor' and broken a downstream import
- It writes a body only when the why isn't obvious, so trivial chores stay one line and the log stays skimmable instead of bloating with restated summaries
- It trusts the diff over my context note, which caught me describing a change I'd actually backed out before staging
What it doesn't do
It is not a substitute for thinking about whether the change should be committed at all. Twice it cheerfully summarized a diff that contained a stray `console.log` and a commented-out block — the message was perfect, the diff was not. The model will happily write you a beautiful description of a mistake. So I still read what I'm staging before I run it, and honestly that's the right division of labor: my attention goes on the code, the model's goes on the prose. It also can't read your team's unwritten conventions — if your team insists on a specific scope vocabulary, you have to put that in the context note, because the diff doesn't know your folklore.
Three weeks in, a reviewer actually commented out of nowhere that our history had gotten easy to bisect, which is the kind of compliment you only get when you've been quietly fixing something annoying. When I pair this with my Generate a Helpful PR Description from the Branch's Commits prompt at the end of a branch, the whole story from individual commit to merge-ready PR writes itself, and the commits are clean enough that the synthesis has good raw material to work from. Grab the Turn a Git Diff into a Clean Conventional Commit Message prompt on Prompt Dock, alias it to two letters, and run it on your own staged diff — the first time it nails the scope you didn't want to think about, you'll quietly delete the part of your brain that used to do it badly.