Spec-driven development
· 4 min read

Working with an LLM on a codebase is like pairing with a brilliant colleague who wakes up every morning with amnesia. The code arrives fast; the intent evaporates. On my side projects I stopped fighting this with longer prompts and started fixing it with structure: every change begins as a spec, not a chat.
Contents
- What spec-driven development is
- The loop I actually run
- Small features or nothing
- The open questions are the point
- Documentation as a by-product
- What changed for me
- What it does not solve
- References
What spec-driven development is
Specification-driven development is an old idea: write down what the software should do, and let that document be the source of truth while you build. LLMs made code cheap, and the bottleneck moved from can this be built to is this what I meant. A written spec becomes the one artefact the model cannot drift away from, because every prompt starts from it.
The version I run is OpenSpec. Specs live next to the code, changes are proposed as deltas against them, and nothing merges into the source of truth until it has actually shipped.
The loop I actually run
Every change moves through four stages:
Explore is a conversation with no code — the model reads the codebase and challenges the idea. Propose turns the surviving idea into a proposal, a design doc, delta specs, and a task list. Apply is implementation, checkbox by checkbox. Archive merges the deltas into the living specs and files the change away.
A recent example on this personal site: I wanted a flag to keep certain posts out of the gallery. Explore found a latent bug in how that gallery was loaded, so the proposal grew from “add a flag” to “add a flag and fix the loader”. Without that step I would have shipped both.
Small features or nothing
Almost every change I ship this way is tiny. That is the point. A change small enough to describe in one proposal is small enough for the model to hold while implementing, and small enough for me to review properly. When one turns out to be a bad idea, throwing it away costs almost nothing.
The alternative is the sprawling prompt that asks for a feature with five concerns baked in. The model obliges. What comes back is a diff nobody can honestly review.
The open questions are the point
The part I value most is that the propose stage flags what it cannot decide. The model can argue both sides all day. It cannot know what I want — so it asks, I answer, and the decision is recorded before any code is written.
That keeps the judgement with me and the typing with the model.
Documentation as a by-product
I have never sat down to document these projects. They are documented anyway. Each shipped change leaves behind specs and an archive entry — the why, the decisions, the task list. When I open a fresh LLM session, it reads the specs and knows the rules without me re-explaining anything. The amnesia problem does not go away; it just stops mattering.
Even the writing goes through the loop. The post about turning request logs into WAF rules and the one about optimising a Cloud Build pipeline each started as a proposal. So did the post you are reading.
What changed for me
Since I picked up this workflow, I have not hand-written a line of code on my side projects. Every change starts as a proposal and comes out as a diff I read and either accept or send back. My time went from typing syntax to deciding what should exist.
Any new side project I start now begins the same way: explore first, spec before code. One weekend this year I used the loop on an idea I had wanted to build for years. By Sunday night I had a working MVP — built the same way as the tiny changes, just stacked back to back.
What it does not solve
The ceremony is real. A one-line fix does not deserve a full proposal, and giving it one anyway wastes time. Specs stay alive only if you keep archiving. And nothing in the loop verifies anything: a wrong idea written as a spec is still wrong. I still read every diff before it lands.
What it buys me is simple: when the model and I disagree, we disagree about something small, early, and written down.
References
- OpenSpec
- Specification-driven development — Wikipedia
- GitHub Spec Kit — the broader spec-driven movement