{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreic7c4z3dwnnfx2lmtwqh5jpovrrp7u6u3ioomnfj3ilyazwtvclwu",
"uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mos3fqn3nyc2"
},
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreif6w6noeezlvogexuwgym6heazafd62mv4dep7obq7nmbipqdu5ja"
},
"mimeType": "image/webp",
"size": 67326
},
"path": "/enjoy_kumawat/i-fixed-the-ai-commit-messages-problem-in-50-lines-of-python-3a5a",
"publishedAt": "2026-06-21T09:14:30.000Z",
"site": "https://dev.to",
"tags": [
"git",
"python",
"ai",
"devtools",
"Claude Code",
"github.com/enjoy-kumawat/my-git-manager",
"@mcp.tool"
],
"textContent": "You've probably seen that trending post — _\"I Asked AI to Write My Commit Messages and It Was Embarrassing.\"_\n\nSame. But instead of accepting embarrassing output, I fixed it.\n\nHere's the thing: the problem isn't AI writing commit messages. The problem is _how_ you ask it. One clear system prompt + the actual diff = surprisingly good results.\n\n## The Setup\n\nNo new packages. No API key. If you have Claude Code, you're already set.\n\n\n\n #!/usr/bin/env python3\n import subprocess\n\n SYSTEM = (\n \"You are a git commit message generator. \"\n \"Output ONLY the commit message — no explanation, no markdown, no quotes. \"\n \"Follow Conventional Commits: type(scope): subject. \"\n \"Types: feat, fix, docs, style, refactor, test, chore. \"\n \"Subject: imperative, lowercase, max 72 chars.\"\n )\n\n diff = subprocess.check_output([\"git\", \"diff\", \"--staged\"], text=True)\n if not diff.strip():\n print(\"Nothing staged. Run `git add` first.\")\n raise SystemExit(1)\n\n msg = subprocess.check_output(\n [\"claude\", \"-p\", SYSTEM + \"\\n\\n\" + diff],\n text=True,\n ).strip()\n print(msg)\n\n\nThat's it. 20 lines. Uses the `claude` CLI under the hood — no API key, no config, just your existing Claude Code OAuth session.\n\n## Why It Works\n\n**The system prompt does the heavy lifting.** Three constraints:\n\n 1. `Output ONLY the commit message` — no preamble, no explanation\n 2. `Follow Conventional Commits` — `feat`, `fix`, `chore`, etc.\n 3. `max 72 chars` — keeps it readable in git log\n\n\n\n**The diff is the context.** You're not asking \"write a commit message\". You're asking \"given these exact changes, what happened?\" That's a much more answerable question.\n\n## Usage\n\n\n # No setup needed if you have Claude Code. Just:\n git add .\n python /path/to/git_commit.py\n # → feat(server): add AI commit message generator via Claude CLI\n\n\nOr wire it into a git alias:\n\n\n\n git config --global alias.ai '!python /path/to/git_commit.py'\n # git ai\n\n\n## The Results\n\nBefore:\n\n\n\n update stuff\n fix bug\n WIP\n added the thing\n\n\nAfter:\n\n\n\n feat(api): add generate_commit_message tool to MCP server\n fix(auth): handle expired token on refresh\n refactor(db): extract query builder into separate module\n\n\n## As an MCP Tool Too\n\nI also wrapped it as an MCP tool so Claude Code can call it directly from any conversation:\n\n\n\n @mcp.tool()\n def generate_commit_message(diff: str) -> str:\n \"\"\"Generate a Conventional Commits message from a git diff string.\"\"\"\n full = SYSTEM + \"\\n\\n\" + diff\n return subprocess.check_output([\"claude\", \"-p\", full], text=True).strip()\n\n\nFull project: github.com/enjoy-kumawat/my-git-manager\n\n20 lines. No new dependencies. No API key. Conventional Commits every time.\n\nThe embarrassing part was waiting this long to build it.",
"title": "I Fixed the \"AI Commit Messages\" Problem in 20 Lines of Python"
}