Spec-driven development: the rise of Markdown

Spec-driven development: the rise of Markdown

# ai# agents# markdown# programming
Spec-driven development: the rise of MarkdownEmeka Adirije

Open my editor on a normal working day and most of the tabs are .md files. Five years ago that would...

Open my editor on a normal working day and most of the tabs are .md files.

Five years ago that would have been an odd thing to admit. The work lived in .java, .ts, .php, etc. Markdown was for READMEs and the occasional doc nobody opened. Now the markdown is where the decisions get made, and the implementation file is increasingly something I read rather than something I type.

That shift has a name. Spec-driven development starts from the observation that when an agent can produce a working implementation from a clear enough description, the description becomes the thing worth version-controlling, reviewing and arguing over. You write a specification. The agent builds from it. When you want something different, you change the specification and regenerate, rather than hand-patching the output and letting the two drift apart.

GitHub puts it more directly than I would dare to. Their post on the subject is titled "Using Markdown as a programming language when building with AI".

How quickly it happened

Look at where the important text in a modern repository actually lives.

Agent instructions are markdown. AGENTS.md is now in more than 60,000 repositories, read natively by Codex, Cursor, Copilot, Gemini CLI, Aider, Windsurf, Zed and twenty-odd others, and the spec is stewarded by the Agentic AI Foundation under the Linux Foundation.

Specifications are markdown. GitHub's Spec Kit generates a spec-template.md. Kiro's requirements phase produces a requirements.md.

So are the skills an agent loads, the prompt files teams check in, the plans, the runbooks, the context documents. All of it, one format, in roughly eighteen months.

Nobody argued about the format

Here is the part I find genuinely strange.

There was a real standards fight, and it was about the filename. AGENTS.md against CLAUDE.md against .cursorrules and the rest. It went on long enough and mattered enough that a Linux Foundation project now stewards the outcome.

The extension was never on the agenda. Nobody proposed YAML, which every CI system in the world already parses. Nobody proposed JSON, which has schemas and validators and editor support that would tell you about a missing field before an agent ever read it. Nobody built a small DSL, which is what this industry has done roughly every other time it needed machines and humans to agree on a document.

Markdown won before anyone thought to hold a vote.

It won for a good reason, and it is worth being precise about what the reason is. Markdown is the only format a person reads comfortably in a diff and a model reads natively with no parser, no schema and no ceremony at all. You can put a table in it, or a paragraph, or a numbered list, or three sentences of hedging about an edge case nobody has resolved yet. That flexibility is exactly why it spread into every corner of the toolchain in a year and a half.

It is also the whole problem.

What we brought with us

Two things came across from source code, and both are good.

Specs live in the repository. They are versioned, they diff, and you can see who changed what and when. That alone puts spec-driven development ahead of every requirements process I worked under before this.

And specs get reviewed. They arrive in pull requests, people comment on them, and a bad one can be argued with before anything is built. Moving the argument earlier is most of the value the movement claims, and the claim is fair.

That is where the inheritance stops.

What we left behind

Everything else we demand of source code is absent.

There are no types. Nothing checks that a section called Success Criteria contains anything resembling a criterion. You can leave it empty, or fill it with a sentence that means nothing, and every tool downstream will accept the document and proceed.

There is no compiler. Nothing reads the spec before an agent acts on it and tells you that requirement four contradicts requirement nine, or that the acceptance criteria describe a behaviour the functional requirements never mention. In a .ts file, a contradiction that blunt is a red squiggle. In a .md file it is valid markdown, and the first thing that notices is an agent confidently building one of the two.

There are no tests. The nearest thing the ecosystem has produced is a lint-spec.prompt.md, which asks a model to read your specification and grade it for clarity and completeness. That is a non-deterministic check, run by the same class of system that will consume the document, on an input with no defined structure. It is better than nothing and it is not a test.

What tooling does exist mostly confirms the gap. markdownlint checks style, which is formatting rather than meaning. OpenSpec ships a validate command, and a 2026 comparison of these tools describes it plainly: it checks structure rather than behaviour, so the spec is a convention rather than an enforced contract. The same comparison notes that verification of code against the spec is the phase most tools treat as optional.

Convention rather than enforced contract. That is a fair description of the entire layer, and that layer is now where the decisions are made.

The obvious objection

Markdown's looseness is a feature, and rigidity is why nobody wrote specs before. Every attempt to make requirements machine-checkable in the last forty years produced a format so tedious that teams quietly stopped using it, which is the actual history of UML, of heavyweight RUP documents, of most of IEEE 830.

That is true and I would not trade it back.

A stricter format would miss the point. You can keep every bit of the prose and still have something that reads the document before an agent does and says that a mandatory section is empty, that two requirements cannot both hold, that an acceptance criterion names a behaviour nothing else in the file mentions. None of that requires giving up a single sentence of English.

The rigour is missing for a duller reason than the format. We moved our most important text into a new home in about eighteen months, and we have not yet got around to building any.

Why the stakes changed

When markdown was for READMEs, an incoherent document cost you a confused reader who went and asked someone. The blast radius was one person and ten minutes.

That same document is now the input to a system that reads it literally, fills every gap you left with its own judgement, and emits a few thousand lines in a couple of minutes. A sentence that could be read two ways no longer waits for someone to ask. It gets resolved, silently, by whichever reading the model found most plausible, and the result arrives looking like completed work.

We spent forty years building tools that refuse to let us commit incoherent source, and then moved the decisions that matter most into a format where anything you type is valid.

In part two I will take one specific thing that absence lets through, and it is a bigger one than it looks: a gap in every mainstream spec format that makes the result impossible for anyone except its author to verify.