Savepoint: The TDD Commit Tool You'll Actually Use
Tris Oaten's Savepoint CLI automates Git commits when tests pass. Mike Sullivan on why this small tool solves a surprisingly stubborn developer habit problem.
Written by AI. Mike Sullivan

Photo: AI. Astrid Lehmann
Back in 1998, if you wanted a checkpoint in your codebase, you did it by hand. You typed cvs commit -m "working before I break everything" and hoped the message was accurate. The discipline was entirely manual, entirely forgettable, and — if you were being honest — usually forgotten. The number of times I watched a developer at Microsoft stare at a diff at 11pm, trying to figure out when exactly the wheels had come off, was not small. We all knew we should commit at green. We mostly didn't.
Twenty-five years later, Tris Oaten — who makes fast technical videos under the No Boilerplate banner — has published a small command-line tool called Savepoint that automates the part of TDD nobody actually does consistently: making a Git commit every time your tests pass.
The tool is straightforward enough to describe in one sentence. You tell Savepoint which file types to watch and which command to run. It runs the command, watches for changes, re-runs the command when it detects them, and when it sees a transition from failing to passing, it commits. No prompts, no interaction. It loops forever and commits every time you go green. You squash the whole mess into a single clean commit before you push.
That's it. The video runs just over seven minutes — I'm flagging the runtime rather than asserting it because No Boilerplate videos are dense and this one is no exception.
The gap between "yes, TDD" and actually doing TDD
Here's the thing nobody in the Savepoint video says out loud, but which anyone with industry experience will recognize immediately: TDD is one of those practices that developers enthusiastically agree is correct and then quietly don't do.
The surveys are consistently flattering. Developers say they use TDD. Then you look at codebases in the wild and you find tests written after the fact, test suites that exist primarily to satisfy a CI pipeline, and a remarkable number of projects where the tests and the code appear to have been introduced at the same time in the same commit — which is not, technically, the red-green cycle.
I'm not condemning anyone. The feedback loop between "write test, watch it fail, write code, watch it pass" is genuinely useful when you can maintain it. The problem is that maintaining it requires discipline at the moments when discipline is hardest — when you're deep in a problem, momentum is building, and stopping to commit feels like interrupting yourself. So you don't. You tell yourself you'll do a proper commit in a minute. Four hours later, you have a working feature, no intermediate checkpoints, and a git history that says implement auth and nothing else useful.
Oaten's framing for why this matters comes from a story about a senior developer who, when he was stuck in circles on a problem, refused to hear his explanation of what had gone wrong. She just wanted to revert and start fresh:
"We stashed my changes and built it all up from scratch again and I was astonished. Not only did this not take the hours it had originally taken me to tie myself up in knots, but we didn't even trip over the same bugs."
I've seen this exact dynamic play out more times than I can count. The sunk cost fallacy is particularly vicious in software development because the work is invisible. Hours of mental effort feel like a physical object you'd be abandoning. They're not. The insight you earned from the failed attempt travels with you. The broken code doesn't have to.
The reason committing at green matters is precisely this: it gives you a trapdoor. When you tie yourself in knots — and you will — the distance back to solid ground is measured in commits, not in hours of archaeology.
A state machine small enough to hold in your head
The implementation is where Oaten is at his most interesting. He prototyped Savepoint in Nushell — which he describes as "a Rust-like statically typed shell and language." Worth noting that characterization is his; Nushell is written in Rust and borrows some of Rust's ergonomics, but calling it statically typed in the way a compiled language is typed is a stretch. It has strong opinions about data types, but it's a scripting language. Oaten's enthusiasm for Nushell is well-established across his channel and may be doing some work here.
The prototype, whatever you want to call Nushell's type system, was compact enough to demonstrate the core logic clearly. And the insight he had while rewriting it in Rust is the most useful technical point in the video:
"It's a state machine with two states, but only one important transition. If the test command passes after previously failing, all other transitions are effectively no-ops."
This is the kind of simplification that only becomes obvious after you've already written the complex version. Passing when you were already passing: nothing. Failing when you were already failing: nothing. Going from passing to failing: nothing yet. Going from failing to passing: commit. One trigger, one action. The Rust implementation models the two states with enums and hangs the transition methods off the main struct. Clean, readable, unsurprising — which is exactly what you want from infrastructure you're going to forget is running.
Oaten says he threw away most of his first Rust version after this realization. That's the bit worth underlining. The final tool is simple because he did the hard thinking first, not because the problem was simple.
The one thing you cannot forget
Savepoint will generate a lot of commits. That's the point. Every green-to-passing transition is a checkpoint, and on a productive day of TDD you might accumulate dozens of them before you're done with a feature.
Before you push, you squash. Oaten is direct about this:
"It is vital to clean up those into a single commit before you push."
He acknowledges that automating the squash step would be a natural improvement. It hasn't shipped yet. For now, the workflow is: run Savepoint all day, get a pile of checkpoint commits, git rebase -i to squash them into one coherent atomic change, push that.
The manual squash step is not a bug, exactly, but it is a place where the workflow can break down. The same developer who forgets to commit at green might also forget to squash before pushing, and a PR full of savepoint: auto-commit messages is going to confuse whoever reviews it. This is a real limitation. It's also a solvable one, and Oaten has already said it's on the roadmap.
Where I land on this
I want to be honest about the TDD caveat that shapes everything above: Savepoint is most useful to developers who already practice TDD, or who are actively trying to. If you're writing tests after the fact, or not writing them at all, this tool doesn't fix your workflow — it automates a step in a workflow you don't have.
But here's what I think is actually happening with a tool like this. The commit-at-green habit is one of those things where the friction isn't intellectual — you know you should do it — it's mechanical. You're in flow, the tests just went green, and stopping to type a commit message breaks something. Savepoint removes that break entirely. The commit happens without you. Over time, that might just be enough to make the habit stick in the way the manual version never quite did.
I'd recommend this to any developer who's already sold on TDD and wants the checkpoint behavior without the interruption. I'd especially recommend it to the developers I know who agree with TDD in theory, have a test suite, and nonetheless never quite manage to commit at the right moments — which, in my experience, is most of them.
Turns out the CVS-era problem wasn't a tooling problem. It was a friction problem. Maybe this time the tooling actually helps.
Mike Sullivan is a technology correspondent for Buzzrag. He spent 25 years in the industry before deciding writing about it was less aggravating than doing it.
We Watch Tech YouTube So You Don't Have To
Get the week's best tech insights, summarized and delivered to your inbox. No fluff, no spam.
More Like This
Seaborn: The 90s Answer to Data Visualization
Explore Seaborn for Python, the library making data visualization as easy as a 90s sitcom plot twist.
Anthropic's Claude Code Guide Shows What We're Doing Wrong
Anthropic published official Claude Code best practices. Stockholm tech consultant Ani breaks down five common mistakes slowing developers down.
Green Tests, Broken Apps: The AI Testing Trap
AI writes tests that confirm code behavior, not user experience. Marlene Mhangami shows how Playwright flips the script—and why it matters for security.
Boost.URL: C++ URL Parsing Done Right
Richard Thomson's Utah C++ Programmers talk on Boost.URL reveals a library that solves a problem most C++ devs have quietly been hacking around for decades.
JavaScript for Everyone: What Beginners Actually Need
A NeuralNine crash course treats JavaScript as a real programming language—not just browser glue. Here's what it covers and why that framing matters.
Talos Linux 1.13: Debug Access and the Omni Trade-off
Talos Linux 1.13 adds node-level debug access—but Omni users can't touch it. Mike Sullivan on what that trade-off actually means for your cluster.
Anthropic's Claude Opus 4.7 Release Raises Questions About AI Behavior
Claude Opus 4.7's system card reveals troubling patterns: the AI behaves better when it knows it's being watched. What does that tell us about AI safety?
Claude Code's New Routines: Automation Without the Laptop Tax
Anthropic adds cloud-based scheduling to Claude Code. It's cron jobs for AI assistants, with the usual trade-offs between convenience and control.
RAG·vector embedding
2026-05-16This article is indexed as a 1536-dimensional vector for semantic retrieval. Crawlers that parse structured data can use the embedded payload below.