<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Zhixin Qin</title>
    <description>The latest articles on DEV Community by Zhixin Qin (@ziwenqingshu).</description>
    <link>https://dev.to/ziwenqingshu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4196415%2Fd85b5d81-b525-4164-9961-8d64cc80407e.png</url>
      <title>DEV Community: Zhixin Qin</title>
      <link>https://dev.to/ziwenqingshu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ziwenqingshu"/>
    <language>en</language>
    <item>
      <title>SlothCommit: a 1B Gemma on a plain CPU now writes my commit messages (after I caught it copying its homework)</title>
      <dc:creator>Zhixin Qin</dc:creator>
      <pubDate>Tue, 20 Oct 2026 14:55:17 +0000</pubDate>
      <link>https://dev.to/ziwenqingshu/slothcommit-a-1b-gemma-on-a-plain-cpu-now-writes-my-commit-messages-after-i-caught-it-copying-its-1na7</link>
      <guid>https://dev.to/ziwenqingshu/slothcommit-a-1b-gemma-on-a-plain-cpu-now-writes-my-commit-messages-after-i-caught-it-copying-its-1na7</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;There are two pieces of writing I put off as a CS student. One is the commit message at 11:40 pm, when the bug is finally fixed and my brain has nothing left. That's how my history ends up full of &lt;code&gt;fix&lt;/code&gt;, &lt;code&gt;fix2&lt;/code&gt;, &lt;code&gt;ok now it works&lt;/code&gt; and the classic &lt;code&gt;asdf&lt;/code&gt;. The other is the weekly "so what did you do this week?" update, which always means scrolling back through those same useless commits to work out what I actually did.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SlothCommit&lt;/strong&gt; hands both jobs to a small open-weight model running on my own machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sloth commit&lt;/code&gt; reads my staged diff and writes a &lt;a href="https://www.conventionalcommits.org/" rel="noopener noreferrer"&gt;Conventional Commit&lt;/a&gt; (&lt;code&gt;fix(cli): ...&lt;/code&gt;, with a short body), then asks &lt;strong&gt;Yes / Edit / No&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sloth week&lt;/code&gt; turns the last 7 days of commits into a changelog grouped by type, with a 2–4 sentence summary I can paste into a standup or group chat. &lt;code&gt;--lang zh&lt;/code&gt; writes it in Chinese.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sloth hook install&lt;/code&gt; is for when even typing &lt;code&gt;sloth&lt;/code&gt; is too much. It adds a &lt;code&gt;prepare-commit-msg&lt;/code&gt; hook, so a plain &lt;code&gt;git commit&lt;/code&gt; arrives with the message already filled in. If the model is down, the hook gets out of the way and never blocks the commit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The model is &lt;strong&gt;Gemma 3 1B&lt;/strong&gt;, running through &lt;strong&gt;llama.cpp&lt;/strong&gt;. No API key, no account, no per-token bill, and no diff ever leaves &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's for anyone who writes code and hates writing &lt;em&gt;about&lt;/em&gt; code, and for every teammate who has to read &lt;code&gt;git log&lt;/code&gt; afterwards.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;A real terminal session, recorded with asciinema. The GIF renderer caps idle pauses at 2 seconds, so the timings Gemma prints in the terminal are the real ones. Every model output is unedited Gemma 3 1B, running on a 2-vCPU ARM cloud box with no GPU:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnzlxhnbiqirue2hexi2o.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnzlxhnbiqirue2hexi2o.gif" alt="SlothCommit demo: sloth commit, sloth week --lang zh, and the git hook" width="784" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To be upfront: the repo in the demo is a small GPA calculator I wrote just for the recording. Its first six commits were also written by &lt;code&gt;sloth commit&lt;/code&gt;, then backdated so &lt;code&gt;sloth week&lt;/code&gt; had a week to summarise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/ziwenqingshu" rel="noopener noreferrer"&gt;
        ziwenqingshu
      &lt;/a&gt; / &lt;a href="https://github.com/ziwenqingshu/slothcommit" rel="noopener noreferrer"&gt;
        slothcommit
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🦥 SlothCommit&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Let a local Gemma model do the git chores you keep putting off.&lt;/strong&gt;
Writes your commit messages, your weekly "what did I even do" report, and
(if you're truly committed to laziness) fills in &lt;code&gt;git commit&lt;/code&gt; for you
Offline. Free. Your code never leaves your machine.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/ziwenqingshu/slothcommit/docs/demo.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fziwenqingshu%2Fslothcommit%2FHEAD%2Fdocs%2Fdemo.gif" alt="SlothCommit demo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ git add -A &amp;amp;&amp;amp; sloth commit
🦥 Gemma via llama-server: 4.8s. Nothing left this machine.

fix(cli): add GPA calculation fix

- Fixed a potential error in the GPA calculation by adding a check for
  unknown grades and raising an UnknownGradeError
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;(That's a real, unedited output from Gemma 3 &lt;strong&gt;1B&lt;/strong&gt;. It's a first draft, not
an oracle: &lt;code&gt;sloth commit&lt;/code&gt; asks Yes / Edit / No before committing. Every commit
in &lt;strong&gt;this&lt;/strong&gt; repo's history was written by SlothCommit and left unedited, so you
can judge the quality yourself.)&lt;/em&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What it does&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Chore it removes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sloth commit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;reads &lt;code&gt;git diff --cached&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/ziwenqingshu/slothcommit" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;About 940 lines of Python (plenty of it docstrings) and no runtime dependencies (the in-process backend is an optional extra). There are 30 tests, MIT license, and a CI workflow. The tests swap Gemma for a fake backend, so they run in 0.2 seconds with no model. Credits for everything I built on are in &lt;code&gt;CREDITS.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There's one more thing I'm a bit proud of: &lt;strong&gt;every commit that built the tool was written by SlothCommit and pushed unedited.&lt;/strong&gt; (The one exception is a later hand-written touch-up to the demo GIF, and its message says so.) You can judge the quality yourself, and I'll say below where it falls short.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The stack.&lt;/strong&gt; I used &lt;a href="https://ai.google.dev/gemma" rel="noopener noreferrer"&gt;Gemma 3 1B instruction-tuned&lt;/a&gt;, as the Q4_0 GGUF from &lt;a href="https://huggingface.co/unsloth/gemma-3-1b-it-GGUF" rel="noopener noreferrer"&gt;unsloth/gemma-3-1b-it-GGUF&lt;/a&gt;, an ungated conversion, so the first run is a plain download with no Hugging Face login. It runs on llama.cpp's &lt;code&gt;llama-server&lt;/code&gt;. SlothCommit has three backends and picks whichever is available: &lt;code&gt;llama-server&lt;/code&gt;, then Ollama (&lt;code&gt;gemma3:1b&lt;/code&gt;), then in-process &lt;code&gt;llama-cpp-python&lt;/code&gt;. (Honesty note: the Ollama backend is unit-tested against Ollama's documented API, but I couldn't get the Ollama binary to download in my sandbox, so all the numbers below are from llama.cpp.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real work was keeping a 1B model honest.&lt;/strong&gt; My first version just sent the diff with a list of rules. On my 7 test diffs, Gemma wrote "handle empty input in parser" for four of them, which was the example sentence from my prompt. So the design ended up as "Gemma does the part that needs language, and Python does everything else":&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Schema-constrained output.&lt;/strong&gt; Gemma has to answer with JSON matching &lt;code&gt;{type, scope, subject, body}&lt;/code&gt;, and &lt;code&gt;llama-server&lt;/code&gt; compiles that schema into a grammar. The output always parses, and &lt;code&gt;type&lt;/code&gt; is always one of the ten valid commit types. It &lt;em&gt;can't&lt;/em&gt; answer with a poem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facts in code, not in the prompt.&lt;/strong&gt; If only Markdown files changed, I narrow the schema's &lt;code&gt;type&lt;/code&gt; enum to just &lt;code&gt;docs&lt;/code&gt; before Gemma sees it. The same goes for tests, CI, and brand-new code files (&lt;code&gt;feat&lt;/code&gt;). Scope cleanup (&lt;code&gt;gpa.py&lt;/code&gt; → &lt;code&gt;gpa&lt;/code&gt;), the 72-character header, line-wrapping and de-duplicating the body are all plain Python.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Few-shot instead of rules.&lt;/strong&gt; Three tiny examples (a README edit, an HTTP timeout fix, a pomodoro timer) taught the format far better than a paragraph of instructions. They never change, so &lt;code&gt;llama-server&lt;/code&gt; caches that prefix. A warm request only has to read my diff.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Condense big diffs instead of truncating them.&lt;/strong&gt; Small diffs go in as they are. Big ones (new modules, mostly) are cut down to each file's definitions, comments and docstrings. In that case Gemma isn't allowed to write bullet points, because with only an outline its "details" were mostly made up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A homework-copying detector.&lt;/strong&gt; This was my favourite bug. When I pointed SlothCommit at its own source code, the first batch of new files came back as &lt;code&gt;docs(readme): add install instructions&lt;/code&gt;. A later one was &lt;code&gt;fix(http): add request timeout and raise on http errors&lt;/code&gt;, word for word my few-shot example. Gemma had given up on the diff and copied its homework. Now, if the subject shares most of its words with one of the examples, SlothCommit says so and falls back to a boring but true message built from the file list.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The weekly report never invents the changelog.&lt;/strong&gt; Grouping commits into Features, Bug fixes, Docs and so on is deterministic code. Gemma only writes the summary on top. For Chinese I use a prompt written &lt;em&gt;in&lt;/em&gt; Chinese, because asking for Chinese in an English prompt got English back.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Two sandbox stories that made it into the code:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My requests to &lt;code&gt;localhost&lt;/code&gt; kept returning &lt;strong&gt;404&lt;/strong&gt;. The machine had an HTTP proxy configured, and Python's &lt;code&gt;urllib&lt;/code&gt; was politely sending my diff to it. SlothCommit now builds a proxy-free opener for local backends. That fixed the bug, and it also means a system proxy can never quietly carry your code anywhere.&lt;/li&gt;
&lt;li&gt;Speed: &lt;code&gt;llama-cpp-python&lt;/code&gt;'s prebuilt wheel read prompts at about 25 tokens/s. The official llama.cpp ARM build with the &lt;strong&gt;Q4_0&lt;/strong&gt; quant read them at &lt;strong&gt;182 tokens/s&lt;/strong&gt;, because Q4_0 gets repacked for the CPU's int8 matrix instructions. A commit message is mostly &lt;em&gt;reading&lt;/em&gt; a diff and barely &lt;em&gt;writing&lt;/em&gt;, so that one choice made the tool usable. (Along the way I also filled the sandbox's RAM-backed disk with a 4B model and an Ollama tarball, and spent a while confused about why every download came back 0 bytes. Sloth tip: run &lt;code&gt;df -h&lt;/code&gt; first.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;For this project, open weights aren't a philosophy slide. Each item below is something that would have broken with a closed API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The code never leaves the machine.&lt;/strong&gt; A commit tool reads &lt;em&gt;everything&lt;/em&gt; you write: coursework you're not supposed to share, internship code under an NDA, half-finished research. With a local Gemma, the whole data flow is "your disk → your RAM → your &lt;code&gt;.git&lt;/code&gt;". I didn't have to write a privacy policy because there's nothing to have a policy about.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It costs nothing and needs no account.&lt;/strong&gt; A tool you run on every commit can't come with a per-token bill or a credit card form, especially for students. Also, several big hosted model APIs don't officially serve mainland China. An ungated GGUF and an MIT-licensed runtime work the same everywhere, offline included.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I could look inside and fix things.&lt;/strong&gt; Every fix above came from having the whole stack open. I benchmarked quantizations myself and picked Q4_0 for a reason I can point to. I cached the few-shot prefix in the server and narrowed the grammar per request. When the model misbehaved I could see exactly what it was given and why. With a closed endpoint I'd just be tweaking a prompt and hoping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It can be swapped.&lt;/strong&gt; Want a smarter sloth? Set &lt;code&gt;SLOTH_OLLAMA_MODEL=gemma3:4b&lt;/code&gt; or point &lt;code&gt;SLOTH_MODEL&lt;/code&gt; at any GGUF. Nothing in SlothCommit is tied to a vendor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest trade-off: a 1B model is a first-draft writer, not an oracle. That's why &lt;code&gt;sloth commit&lt;/code&gt; asks before committing and the changelog is built in code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;Only numbers I actually measured. All of them come from a 2-vCPU ARM cloud box with no GPU, running Gemma 3 1B Q4_0 on &lt;code&gt;llama-server&lt;/code&gt;. A normal laptop should do at least as well.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;Measured&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;sloth commit&lt;/code&gt; on the demo repo, 8 commits&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.2 – 4.8 s each, mean 3.4 s&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SlothCommit writing its &lt;em&gt;own&lt;/em&gt; 10 build commits (bigger diffs)&lt;/td&gt;
&lt;td&gt;3.0 – 8.5 s each, mean 5.4 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;sloth week&lt;/code&gt; (6–7 commits, English or Chinese)&lt;/td&gt;
&lt;td&gt;3.0 – 4.7 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Small diff with the server warm vs. its very first request&lt;/td&gt;
&lt;td&gt;1.1 s vs. 8.2 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same diff in-process through &lt;code&gt;llama-cpp-python&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;67.9 s (use the server!)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory used by &lt;code&gt;llama-server&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;~1.6 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;$0, no network after the ~720 MB model download&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I didn't measure how long I &lt;em&gt;used&lt;/em&gt; to spend on commit messages, so I won't invent a "saves 2 hours a week" number. What I can say for sure is that this week, 11 commits went into SlothCommit's own history and I typed exactly zero characters of those messages.&lt;/p&gt;

&lt;p&gt;How good are they? About what you'd expect from a 1B model in a hurry. Most are fine. A few are sloth-quality: a &lt;code&gt;.gitignore&lt;/code&gt; commit typed as &lt;code&gt;feat&lt;/code&gt;, a body claiming it "improves performance" that nobody measured, one &lt;code&gt;test(tests): add test_git_and_cli.py&lt;/code&gt; that is technically true and spiritually lazy, and my favourite: a README edit summarised as &lt;code&gt;docs(readme): add GPA calculation fix&lt;/code&gt;, because the README quotes that line from the demo and Gemma simply quoted it back. The Chinese weekly summary sometimes adds achievements that never happened, so I read it before sending. My plan: keep the guard rails tight, and let anyone with more RAM switch to Gemma 3 4B.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best Use of Gemma.&lt;/strong&gt; Gemma 3 1B is the only model in SlothCommit and does every piece of writing in it: commit subjects and bodies, plus English and Chinese weekly summaries. The project is built around what a 1B Gemma can and can't do on a CPU: schema-constrained decoding, few-shot prompts with a cached prefix, deterministic type narrowing, condensed diffs, and a detector for when it copies its examples. It runs fully local through llama.cpp or Ollama, offline and free.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
