DEV Community

Vedant Gajbhiye
Vedant Gajbhiye

Posted on AI-assisted

Sloth Commit: a local AI that writes your commit messages and splits the messy ones

Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady Submission 🦥

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

What I Built

Writing a commit message is the smallest chore in programming and the one I put off the most. So I built Sloth Commit: a command-line tool where a local open-weight model reads your staged diff and writes the message for you.

git add .
git commit        # the editor opens with the message already written
Enter fullscreen mode Exit fullscreen mode

The model runs on my own laptop through Ollama. The tool is plain Python with no dependencies beyond the standard library. A diff is just your unreleased source code, and it never leaves the machine.

Writing a message from a diff is a one-line idea, so I spent the effort on the parts around it:

  • Style Mimic. It reads your repo's last 30 commits and copies how you write: Conventional Commits or plain subjects, casing, trailing periods, emoji, typical length. There's no config file, and it adapts to whatever repo you drop it into.
  • Secret Guard. Before a diff goes anywhere, it scans the staged changes for API keys, tokens, private keys, .env files and huge binaries, then warns you.
  • Commit Splitter. If you staged a bug fix and a README tweak together, it proposes separate commits, each with its own message, and makes them after you confirm.
  • Slow-and-steady mode. A small model drafts the message in a second or two. With --slow, a bigger model polishes the draft. Speed is a dial you control.
  • Sloth Stats and Standup. A local tally of the time you saved, with a sloth, and sloth-commit standup, which turns your week of commits into a few bullets. Anyone who has typed fix stuff at 1 a.m. gets to be a little lazier, and the history still comes out readable.

Demo

I ran it on a real project of mine, a clinical NLP pipeline, on a laptop with 16 GB RAM and an RTX 3050 with 6 GB of VRAM, using qwen2.5-coder:3b:

PS> sloth-commit doctor
ok    inside a git repository
ok    Ollama is running at http://localhost:11434 (1 models)
ok    fast model qwen2.5-coder:3b

PS> sloth-commit style
Learned from 7 recent commit(s):
  format    plain subject lines
  casing    Capitalised first word
  period    no
  emoji     no
  length    ~60 chars (limit 91)

PS> sloth-commit msg
Asking qwen2.5-coder:3b...
Update README.md with detailed project information
Enter fullscreen mode Exit fullscreen mode

The reply took a second or two. Style Mimic worked: my repo uses plain, capitalised subjects with no period, and that is exactly what came back, not the Conventional Commits default.

The message itself was only half right, and I'd rather show that than hide it. My test change was four comment lines added to frontend/app.py, plus a README edit that only removed a trailing newline. The model wrote about the README and ignored the code. My guess is it anchored on the first file in the diff, but I haven't tested that. This is the kind of mistake a 3B model makes on a tiny, odd diff, and it's why the tool shows the message and asks for confirmation instead of committing silently.

Code

sloth-commit

A lazy git commit assistant. A local open-weight model (via Ollama) reads your staged diff and writes the commit message, so you don't have to. Your code never leaves your machine, it works offline, and it costs nothing to run.

Zero Python dependencies: standard library only.

$ git add
$ git commit            # editor opens with the message already written

What makes it different






















Feature What it does
Style Mimic Reads your repo's last 30 commits and copies the conventions (Conventional Commits or plain, casing, length, emoji). No config file.
Secret Guard Scans staged changes for API keys, tokens, private keys, .env files and huge binaries before the model or your history sees them. Local regexes, so nothing is uploaded to check.
Commit Splitter Spots unrelated changes in one staged diff (a fix plus a README tweak) and commits them separately, each with its own message. Splits
…





How I Built It

The open pieces are what make it work:

  • Open-weight model via Ollama. The default is qwen2.5-coder:3b, which fits comfortably in 6 GB of VRAM. The slow model defaults to qwen2.5-coder:7b. Both are config, not code, so any model Ollama can run works.
  • A tiny Ollama client in the standard library. One HTTP call to /api/chat, with clear errors for the failures people actually hit: Ollama isn't running, or the model isn't pulled (it tells you the exact ollama pull command).
  • Diffs trimmed for small models. Lock files and binaries are summarised, each file and the total are capped, and the model is told when the diff was cut. A 3B model does much better with a focused diff than with 4,000 lines of package-lock.json.
  • Output cleaning. Small models love wrapping answers in code fences, quotes, "Here is the commit message:" or <think> blocks. All of that is stripped.
  • A hook that never gets in the way. sloth-commit hook install adds a prepare-commit-msg hook. It does nothing for -m, merges, squashes or amends, and if Ollama is down it silently lets you type the message yourself. It will never be why a commit fails, apart from one opt-in: SLOTH_GUARD=block stops commits that contain suspected secrets.
  • A splitter that fails safely. It groups whole files, never hunks. It refuses files that are partly staged, so it can't pull unstaged work into a commit. All the messages are written before the index is touched, so a model failure can't leave things half-rearranged, and if a commit fails mid-way the remaining files are staged again.
  • 44 tests against a fake Ollama server. They run with no GPU and no network, and include real git commit runs through the installed hook.

Why Does Open Innovation Matter?

Your diff is your source code. Hosted commit tools have to upload it to work. Sloth Commit can't, because there is nowhere for it to go. For private or unreleased projects, that's the whole difference.

Secret Guard only makes sense locally. Checking a diff for leaked API keys by sending it to someone else's server is a good way to leak the keys. With a local model, the scan, the prompt and the answer all stay on the machine.

It's free and works offline. No API key, no per-token bill, no rate limit. It works on a train, on campus Wi-Fi, or on a plane.

It's swappable. If a better small coding model appears next month, it's one environment variable: SLOTH_MODEL=.... You can also point it at another machine on your network or at your own fine-tune. A closed API gives you whichever model the provider decides to serve.

I didn't run a head-to-head benchmark against a hosted model, so I won't quote a number. A frontier model would very likely have described the app.py change that my 3B model missed. For me, a message that is good most of the time, is instant, and is free and private beats one that is slightly better but sends my code to a server I don't control. Where it isn't good enough, --slow and the confirm step catch it.

The Lazy Payoff

The model answers in a second or two on a 6 GB laptop GPU, which is faster than I can think of a message, let alone type one. I used it on my own repo this week, and the tool keeps a local tally (sloth-commit stats) of characters you didn't type and time saved. That estimate is based on assumed typing speed, so treat it as a rough figure. What I really gained is a repo history in a consistent style that I no longer have to think about.

Prize Categories

Gemma: Sloth Commit is model-agnostic, so I swapped Google's open-weight Gemma into it with one environment variable (SLOTH_MODEL=[the exact Gemma model name you pulled]) and compared it with Qwen on the same staged diff. [One or two honest sentences on what you saw, for example whether it described the app.py change that Qwen missed, or which one was faster on the RTX 3050.]

A huge shoutout to claude and shreyashkakad for contributing (https://dev.to/shreyashkakad)

Top comments (0)