Posts
Removing a Leaked SSH Key from Git History with BFG Repo-Cleaner
How to surgically remove an accidentally committed SSH private key from a Git repository's history using BFG Repo-Cleaner — the fast, focused alternative to git filter-branch
It happens to almost everyone, eventually.
You stage your changes, type git commit -am "wip", push — and a few minutes later realize that id_rsa (or .env, or credentials.json) was sitting in the working directory the whole time. The file is now in the remote, in every clone, in every CI cache, and worst of all: in the git history, where a simple git rm won’t touch it.
This post walks through fixing exactly that scenario with BFG Repo-Cleaner — a tool purpose-built for ripping unwanted blobs out of git history.
A Guide to Upgrading Your Library to a Major Release in Go
Practical walkthrough of bumping a Go module to v2+: import paths, branches, tags, and what not to forget.
Bumping a Go library to a new major version is not just a git tag v2.0.0. Go’s Semantic Import Versioning makes the module path itself part of the version contract — so v2+ means rewriting go.mod, every internal import, and (often) reorganizing branches. This is the short, command-driven version of the official guide, with the operational steps that are easy to forget.
auto-mr: one command from feature branch to merged PR
A Go CLI that pushes your branch, opens an MR/PR, waits for CI, and merges — works on both GitLab and GitHub
I push a feature branch a dozen times a week. Every single time, the dance is the same: git push, switch to the browser, click the “Create MR” button, set assignee, set reviewer, add labels, wait for CI, click merge, switch back to terminal, git checkout main, git pull, git branch -d feature/.... It’s not hard. It’s just tedious — and the kind of friction that adds up over a week.
I had a shell script glued together with glab, gh, jq, yq, and gum doing this for years. It worked, but it broke whenever any of those tools updated and was a pain to ship to a fresh laptop. So I rewrote the whole thing in Go and called it auto-mr. One binary, no external CLIs, works on both GitLab and GitHub.
bullets: a colorful, goreleaser-style logger for Go CLIs
A small Go logging library focused on beautiful terminal output — bullets, spinners, progress, and updatable lines — without dragging in a heavy framework.
I love how goreleaser looks when it runs. Tidy bullets, indented sub-steps, the right amount of color, occasional spinners. Every time I write a Go CLI of my own, I want that aesthetic — and I don’t want to pull in a 100-dependency logging framework to get it. So I wrote bullets.
calcdate: date arithmetic that doesn't make you cry
A Go CLI for date math, range generation, and timezone conversion with a readable expression syntax
Every shell scripter has, at some point, googled “date subtract day mac” or “GNU date macOS BSD difference” and wished they hadn’t. The date command is one of the most platform-fragmented tools in any Unix toolbox: GNU date and BSD date disagree on basically every flag that matters. And once you’ve worked out the syntax for “yesterday,” you still need to do something useful with it — like generate a range of timestamps for a backfill, or compute end-of-month, or skip weekends.
I got tired of this. So I wrote calcdate. Same binary on Linux, macOS, anywhere. One expression syntax. Version 2 just landed and the syntax is now genuinely pleasant to use.