Plan before you prompt: spec-driven AI development with OpenSpec
When an AI coding agent goes wrong, it's rarely because it can't write code. It's because it confidently built the wrong thing — fast. You asked for "add payout reconciliation," it produced 400 lines that look plausible, and only in review do you discover it ignored multi-currency rounding, never considered idempotency, and quietly invented an API shape you now have to live with.
The fix isn't a better prompt. It's a plan the agent has to agree to before it writes a line. That's what spec-driven development gives you, and OpenSpec is the lightest way I've found to do it.
What OpenSpec actually is
OpenSpec is an open-source spec-driven development (SDD) framework for AI coding assistants. The whole idea: proposals, specs, design notes, and task lists live in your repo, as files, and the agent implements against them. It works with 20+ tools — Claude Code, Cursor, Copilot — with no API keys and no MCP server to run. Your specs are just Markdown next to your code.
That last part matters more than it sounds. Context that lives in a chat window dies when the session ends. Context that lives in the repo survives across days, machines, and teammates.
The loop
npm install -g openspec # or your package manager of choice
cd your-project
openspec init # scaffolds the openspec/ workspace
From there you drive it from your AI assistant with slash commands:
/opsx:propose "add SRS price-ingestion with reconciliation"
# → generates a change folder:
# proposal.md why we're doing this, what changes
# specs/ requirements + concrete scenarios
# design.md the technical approach
# tasks.md an implementation checklist
/opsx:apply # implement strictly against the agreed spec
/opsx:archive # record the completed change as history
The key beat is the gap between propose and apply. You read proposal.md and design.md, you argue with them, you fix the edge cases on paper — and only then does the agent touch code.
Why this is the real "AI optimization"
Most "make AI coding better" advice is about prompt phrasing. That's optimizing the wrong layer. The expensive failure mode isn't a slightly worse function — it's building the wrong design and discovering it after it's load-bearing.
On the backend especially, the hard part was never the syntax; it's the decisions. When I scope something like a fixed-deposit maturity flow, the spec is where I pin down the things an agent will otherwise guess at:
- What happens on a partial fill, or a duplicate webhook? (idempotency keys, not hope)
- FX and rounding: which currency is authoritative, banker's rounding or not?
- Ex-date vs settlement-date accrual — stated once, in
specs/, not rediscovered in three PRs.
Writing those down takes twenty minutes. Finding them in review — or worse, in production reconciliation — takes a lot longer.
How I actually use it
- Keep proposals small. One change folder per coherent unit of work. A giant proposal is just a giant prompt with extra steps.
- Treat
specs/as the contract. If behavior isn't in the spec, the agent shouldn't be inventing it. If you want it, add it to the spec first. - Review
design.mdlike a real design doc. This is the cheapest place to catch an architectural wrong turn. - Archive religiously. The archived changes become a readable history of why the system looks the way it does — the context future-you (and your agent) will be grateful for.
Spec-driven development won't make the agent smarter. It changes what you're optimizing: from "how do I phrase this" to "do we agree on what 'done' means." Once the spec is right, the implementation is almost boring — which is exactly what you want from a system that moves money around.
If you've only ever vibe-coded features start to finish, try running your next non-trivial change through propose → apply → archive. The first time the agent ships something that's right the first time because the spec caught the edge case, you won't go back.