← Blog

Spec Driven Development: A Guide for Parallel Agents

10 min read

Key takeaways

  • Spec driven development means writing scope, file paths, constraints, and self-checkable acceptance criteria before prompting, so an agent can execute without you in the loop.
  • Specs matter most when running parallel coding agents, because the spec is the only context that survives between sessions and the artifact you verify diffs against.
  • GitHub's Spec Kit formalizes the flow as specify, plan, and tasks; Claude Code and Cursor agents can follow the same three artifacts as markdown files in the repo.
  • Keep specs in the same repo as the code, version them with git, and treat spec drift as a defect with the same priority as a failing test.
  • Skip the spec for one-file fixes you can review in one sitting; write one when the task spans files or repos, runs in parallel, or is mechanical work.

Spec driven development means writing a short, structured spec (context, constraints, acceptance criteria) before you prompt, so a coding agent like GitHub Copilot can execute the work without you babysitting every step. This guide shows what an executable spec looks like, compares spec formats across Copilot and competing agents, and gives you copy-paste templates for feature and refactor work.

What is spec-driven development and how does it differ from vibe coding?

Spec-driven development means writing an executable specification first: the requirements, acceptance criteria, and constraints the agent must satisfy, then letting it generate the plan, tasks, and code from that spec. Vibe coding is the inverse: you prompt reactively, review the diff, and queue the next prompt based on what you see. GitHub formalized the spec-first workflow in its spec-kit toolkit, which moves through specify, plan, and tasks phases (GitHub spec-kit documentation).

What vibe coding looks like in practice

Six terminals open, each agent mid-refactor, and you are the glue between every step. When a model misunderstands the file structure in step one, every later prompt inherits the error, and you have no record of where it went wrong.

Where the two approaches sit on a spectrum

Most teams mix both: specs for multi-file or cross-repo changes like Changements multi-dépôts avec des agents — Aerunit, direct prompting for one-file tweaks. The difference matters most when agents write most of the code, because a written spec is the only artifact that lets you verify the implementation is actually complete.

Why specs matter more when you run parallel coding agents

The bottleneck is the routine, not the agent

One agent waiting on you is a delay. Six agents waiting on you is a stall. The common failure mode isn't the model producing bad code, it's you pasting the next prompt, re-explaining the file structure, and noticing three terminals later that step two misunderstood step one. A spec fixes this by making the routine explicit: scope, files, acceptance criteria, done.

Specs as the handoff between agent sessions

When each session starts fresh, the spec is the only context that survives. Write it so the next agent (or the same agent on a new worktree) can pick up without you in the loop: what exists, what changes, what "complete" means. That also answers the hardest question in parallel work: how do you know the implementation is actually finished? If the acceptance criteria are in the spec, an agent or a reviewer can check the diff against them instead of asking you. We cover more workflow patterns on the Aerunit blog — working with AI coding agents.

How do you write a spec that a coding agent can execute reliably?

An executable spec has five parts: a one-paragraph scope, the exact file paths it touches, hard constraints, acceptance criteria the agent can self-check, and nothing else. Martin Fowler has argued that the hard part of AI-assisted development is writing precise enough instructions for the machine, which is exactly what most vibe-coded prompts skip (Fowler on AI-assisted coding). Leave out architecture rationale, competitor context, and future roadmap items. The agent executes; it does not deliberate.

Template 1: feature spec

Scope: add CSV export to the invoices list. Files: app/controllers/invoices_controller.rb, app/views/invoices/index.html.erb, one new test file. Constraints: no new gems, no schema changes, match existing controller patterns. Acceptance criteria: clicking "Export CSV" downloads a file whose row count matches the filtered list; test passes.

Template 2: refactor spec

Scope: extract the rate-calculation block in lib/pricing.rb into lib/pricing/rates.rb. Files: those two plus call sites listed by path. Constraints: zero behavior change, no public API changes. Acceptance criteria: full test suite passes unchanged; grep for the old block returns nothing.

Acceptance criteria that an agent can self-check

The single biggest lever in a spec is criteria phrased so the agent itself can verify them: a command that must pass, a grep that must return empty, a diff that must not touch a given path. "The implementation is actually complete?" is the question every orchestrator user asks, and vague criteria make it unanswerable — the agent finishes, you poll, you read the diff, and you still cannot tell. A criterion like "run bundle exec rspec spec/models/pricing_spec.rb and it passes with zero failures" is checkable by the agent in the same session, so it can iterate before you ever look. This is also what makes parallel runs viable: when each spec carries its own verification, you review the diff once instead of babysitting six terminals, and feedback loops like Instant feedback for coding agents with hooks — Aerunit close the gap between an agent finishing and you knowing whether it finished correctly.

How does spec-driven development work with GitHub Copilot specifically?

GitHub formalized spec-driven development in its Spec Kit workflow: you write a constitution and a spec, run a /plan step to produce an implementation plan, then /tasks breaks that plan into a checklist of discrete, ordered work items. Copilot agent mode executes against those artifacts, and each task is small enough that you can review the diff per step instead of auditing one giant change at the end.

The spec → plan → tasks flow

The separation matters because each artifact has a different failure mode. The spec captures intent and acceptance criteria; the plan captures architecture and file structure; the tasks capture sequence. If the model misunderstands the file structure, you catch it at the plan stage, before the next prompts in the queue inherit the error. With Copilot agent mode, you assign the task list to the agent, keep the spec open as the source of truth, and treat each completed task as a reviewable unit.

Adapting it to Claude Code and Cursor agents

The same three artifacts work outside GitHub's tooling. Claude Code and Cursor Cloud Agents don't ship a /plan command, so the practical adaptation is to keep spec, plan, and task list as markdown files in the repo and point the agent at them in the prompt. This is the same pattern used when you run Agentes de código en paralelo sin cuellos — Aerunit: each agent gets one task plus the shared plan, so agents stay busy without stepping on each other's worktrees. The honest limitation: Copilot's flow assumes you're in GitHub's ecosystem, and nothing in Spec Kit stops drift between spec and code, which is a separate discipline covered later.

Which spec-driven development frameworks and tools exist and how do they compare?

Spec format comparison

Each agent reads specs differently. Claude Code picks up project conventions from a CLAUDE.md file at the repo root (Anthropic documentation), Copilot leans on custom instructions plus the prompt itself, and Cursor Cloud Agents work best when the Linear issue body carries the full acceptance criteria. The table below shows what a minimal executable spec looks like in each.

AgentWhere the spec livesWhat it must contain
Claude CodeCLAUDE.md + session promptConventions, file map, done criteria
GitHub CopilotCustom instructions + promptTask, constraints, examples
Cursor Cloud AgentsLinear issue bodyScope, repos touched, review steps

Orchestration tools compared

Conductor, Devin, Factory, Agentastic, and Orgabot all attack the queue-the-next-prompt problem from different angles. Devin and Factory run managed agents; Conductor and Agentastic focus on local orchestration. Aerunit sits in the same category but is Linear-native and built around Cursor Cloud Agents specifically, keeping a fleet busy from one board across repos, as described in Changements multi-dépôts avec des agents — Aerunit.

Where Aerunit falls short

Honest limits: Aerunit assumes Linear and Cursor Cloud Agents, so Claude Code or Codex pipelines need their own glue. There is no local-first mode, and spec authoring stays in Linear rather than a dedicated spec format. If your workflow is repo-local single-agent prompting, it is overkill.

What are the best practices for keeping specs in sync with generated code?

Store specs next to the code

Keep every spec in the same repo as the code it describes, under something like /specs, and version it with git. A spec in Notion or Linear is a doc; a spec in the repo is a file the agent can read, and a diff you can review. When an agent changes an API, the PR touches both the code and the spec, so drift shows up in review instead of three weeks later.

Treat spec drift as a bug

If the shipped code no longer matches the spec, that is a defect with the same priority as a failing test. Put a line in your acceptance criteria: "spec updated to match implementation." Agents that skip it get the PR bounced. On a small team this costs one review checkbox and saves you from specs that describe a codebase that no longer exists.

Review the diff against the spec

The sync loop is: spec defines acceptance criteria, agent produces a diff, you review the diff against the criteria, then merge the spec update in the same PR. When you queue the next prompt or the next agent on the fleet, it reads the merged spec, not your memory of what changed. If you are running parallel agents across repos, a stale spec in one repo quietly poisons every downstream task that depends on it.

When is spec-driven development overkill compared to prompting directly?

Prompt directly when the task is small, the blast radius is contained, and you can review the diff in one sitting. A one-file bugfix or a copy tweak does not need acceptance criteria; writing the spec takes longer than the fix. Spec-driven development earns its cost when three things stack up: the task spans multiple files or repos, more than one agent is running in parallel, and most of the work is mechanical (migrations, renames, test scaffolding). Parallel agents especially punish vague prompts, because a misread file structure in step one poisons everything queued behind it.

A quick decision rule

If you would queue the task to a background agent rather than watch it run, write a spec. Cursor's background agents receive your task as the context they work from, so the prompt effectively is the spec (Cursor docs). If you are pasting the next prompt yourself, skip the ceremony.

What did Martin Fowler and other practitioners say about spec-driven development?

The practitioner consensus is less about specs as documents and more about specs as contracts: write down the acceptance criteria an agent must satisfy, then judge the diff against them instead of trusting the model's summary of its own work. That framing shows up across the builder posts quoted earlier in this piece, where the recurring complaint is coordination, not generation.

We built Aerunit on the same assumption: specs in Linear define "done," agents stay busy against them, and you review the diff. Where we fall short: we assume Linear and Cursor Cloud Agents specifically, so teams on other trackers or CLIs have to adapt their workflow to us, not the reverse.

FAQ

Is spec-driven development the same as test-driven development?

No, but they overlap. TDD writes failing tests before code; spec-driven development writes requirements, constraints, and acceptance criteria before prompting. Acceptance criteria in a spec often include a test command the agent must pass, so the two compose well. The spec covers scope and file paths that tests alone do not, while tests verify behavior the spec describes.

Do I need a spec for every small change an agent makes?

No. For a one-file bugfix or copy tweak you can review in one sitting, prompting directly is faster and writing the spec costs more than the fix. Write a spec when the task spans multiple files or repos, more than one agent runs in parallel, or the work is mechanical like migrations or renames. The decision rule: if you would queue it to a background agent, spec it.

Can I use spec-driven development with Linear issues instead of separate spec files?

Yes, with caveats. Cursor Cloud Agents work well when the Linear issue body carries the full acceptance criteria, and Aerunit is built around specs living in Linear. The tradeoff is drift: a spec in the repo is a file the agent reads and a diff you review, so code and spec change in the same PR. Issues in a tracker tend to go stale quietly.

How long should a spec for a coding agent be?

Short. Five parts: a one-paragraph scope, the exact file paths it touches, hard constraints, acceptance criteria the agent can self-check, and nothing else. Leave out architecture rationale, competitor context, and roadmap items, since the agent executes rather than deliberates. If the spec runs longer than a screen, it usually contains context the agent will ignore or misread anyway.

Does spec-driven development slow down solo developers?

It slows down single small tasks but speeds up anything queued or parallel. The bottleneck when running several agents is you: pasting prompts, re-explaining file structure, and noticing three terminals later that step two misunderstood step one. A spec makes the routine explicit and lets each agent self-verify against acceptance criteria, so you review diffs once instead of babysitting every session.

Aerunit

Keep the agents busy. You do the thinking.

Sign-up is open — create an account and start with pay-as-you-go credits. No subscriptions, and teams share one credit pool at no extra cost.

Create account