DEV Community

Cover image for I built a CLI that turns your git commits into social media posts
Vladimir Simić
Vladimir Simić

Posted on

I built a CLI that turns your git commits into social media posts

The problem

Every week I ship things. Features, fixes, refactors. It's all there in git.

But writing a post about it? I'd either skip it entirely or spend 20 minutes staring at a blank box writing something that sounded nothing like me.

I knew what I built. Git knew what I built. The gap was just turning one into the other.

What I built

commitpost — a CLI that reads your git history, sends it to Claude AI, and writes a post in your voice. Optionally generates a cover image with your actual code as the background.

npm install -g commitpost
commitpost generate --include-image
Enter fullscreen mode Exit fullscreen mode

That's it. One command. Post and image ready to copy-paste.

How it works

  1. Runs git log --author --since to grab your recent commits
  2. Sends them to Claude with your tone profile (a writing sample you set once)
  3. Generates the post text
  4. Extracts a real changed file from your commits for the cover image
  5. Syntax-highlights it, applies blur, overlays the headline
  6. Outputs a 1200×627px PNG ready for LinkedIn, Bluesky, or X

The interesting technical parts

Cover image without a browser

My first instinct was Puppeteer. Installed it, no Chrome binary. Pivoted to satori (Vercel's JSX→SVG renderer) + @resvg/resvg-js (Rust SVG→PNG) + sharp for compositing.

No headless browser. No Electron. Pure Node, works anywhere.

Blurring code correctly
Blurring sounds simple. It wasn't.

SVG feGaussianBlur clips at element boundaries — above ~sigma 20, no visible effect. Switched to sharp.blur(). But blurring a transparent PNG destroys the alpha channel and the layer disappears entirely when composited.

The fix: render background + code as one solid image first, then blur. Solid pixels blur correctly. Then composite the UI (headline, author) on top as a separate transparent layer.

Code that starts at something meaningful

Initially the image showed the first 20 lines of a file — which is always imports and require statements. Nobody wants to see import React from 'react' as their cover image.

Added findMeaningfulStartLine() — scans for the first class/function definition per language and starts there instead. Works for JS/TS, PHP, Python, Ruby, Java, Go, Rust, C#.

Tone profiles
One-time setup: paste a writing sample (old blog post, previous tweet, anything). Stored in ~/.commitpost/config.json. Every generated post runs through that sample as a style guide. Posts sound like you, not like ChatGPT.

The meta moment

I used commitpost to generate the LinkedIn post announcing commitpost. It worked.

Try it

# Install
npm install -g commitpost

# Set your API key (Anthropic)
commitpost config --set-key sk-ant-...

# Generate
commitpost generate

# With cover image
commitpost generate --include-image --image-style dark_code
Enter fullscreen mode Exit fullscreen mode

GitHub: vsimke/commitpost
npm: commitpost

Post length is configurable (--length short/medium/long), there are 4 image styles, and 5 built-in tone profiles if you don't want to set up your own.

Open source, MIT. Would love feedback — especially from people using it on non-JS projects.

Top comments (0)