Starting a New Project With It
The greenfield case. There is no existing code to catch a wrong assumption, so the two guard rails carry more weight than they do anywhere else.
Greenfield looks like the easy case and is not. On an existing system the agent can read your real router, your real conventions and your real test setup, so a bad assumption gets corrected by the code itself. On an empty repository there is nothing to read, and whatever the agent assumes is whatever you wrote down — or whatever it invented.
That single fact shapes this whole page.
7.1 Day one
FIGURE A5 — Day one on a project that does not exist yet. Two terminal commands, then one file most teams leave empty — and that is the file doing the most work here.
TERMINAL $ npm install -g @fission-ai/openspec@latest
TERMINAL $ cd your-new-project && openspec initThat creates four directories and one file. Three of the directories are empty and stay empty until you archive your first change, which is correct — there is nothing to describe yet.
The file is openspec/config.yaml, and filling it in is the step people skip.
7.2 Guard rail one: context injection
# openspec/config.yaml
schema: spec-driven
context: |
Tech stack: TypeScript, React, Node, PostgreSQL
API style: RESTful, documented in docs/api.md
Testing: Jest + React Testing Library
We keep backwards compatibility for all public APIs
rules:
proposal:
- Include a rollback plan
- Identify affected teams
specs:
- Use WHEN/THEN scenarios
- Reference existing patterns before inventing new onesWhen the AI generates any artifact, that content is assembled into the prompt:
<context>
Tech stack: TypeScript, React, Node, PostgreSQL
…
</context>
<rules>
- Use WHEN/THEN scenarios
- Reference existing patterns before inventing new ones
</rules>
<template>
[the schema's own template for this artifact]
</template>context appears in every artifact. rules appear only for the artifact that names them. Context is capped at 50 KB.
FIGURE A7 — Two guard rails, because there is no code to catch a wrong guess. One tells the agent what your project is. The other refuses to let a sloppy specification through.
This is more reliable than hoping the assistant reads a separate conventions file, because it is not a hope — the text is in the prompt for every artifact, on every change, for everyone on the team.
Avoid: leaving
context:blank on a new project and correcting the agent by hand each time instead. It works, it is invisible to everyone else on the team, and it stops working the moment somebody else runs/opsx:propose.
7.3 Guard rail two: strict validation
openspec validate --strict promotes five warnings into failures:
| Condition | Without --strict | With it |
|---|---|---|
| A requirement with no SHALL or MUST | warning | fails |
A ## Purpose under 50 characters | warning | fails |
A ## Why over 1000 characters | warning | fails |
| A requirement body over 500 characters | warning | fails |
| More than 10 deltas in one change | warning | fails |
Errors fail either way: a requirement with no scenario, a change with no delta at all, a MODIFIED block that drops a scenario the specification still has, and a scenario written at three hashes rather than four.
Note — the SHALL/MUST check is a warning by default on purpose, so that specifications written in languages other than English still pass ordinary validation.
--strictis where you opt into the RFC 2119 convention. Put it in continuous integration and greenfield drift stops being possible.
7.4 What is different about greenfield in practice
Capabilities are designed, not discovered. On a brownfield change, the capability you are touching already exists and its name is obvious from the folder. On a new project you are choosing what the capabilities are, which makes the proposal's ## Capabilities section carry more weight — it decides which specification files exist at all.
Explore is still worth running, for a different reason. With no code to read, /opsx:explore is not doing archaeology. It is acting as a thinking partner: weighing options, naming trade-offs, and turning a fuzzy idea into something concrete before any artifact exists. That is a different job from the brownfield use in FIGURE A3, and it is still the best antidote to an assistant that will otherwise confidently build the wrong thing from a vague prompt.
design.md matters more, sooner. OpenSpec's own guidance is to write one when there is a new architectural pattern, a new external dependency, significant data-model work, or ambiguity worth settling before coding. On a new project most of the first few changes hit at least one of those.
7.5 How the folder gets sliced
FIGURE A6 — How the specifications folder gets sliced into domains. Three common shapes. Pick whichever makes a newcomer nod, and refine it later.
The rule for when to create a domain is the same as on a brownfield codebase, and it surprises people on a new project: create one when the first change in that area needs it, not before.
The temptation on greenfield is to design the whole taxonomy on day one, because the folder is empty and the whole system is still in your head. Resist it. A structure invented before any behaviour exists is a guess about a system that does not exist yet, and you will be renaming it inside a month. Renaming later is a RENAMED delta and an ordinary change, so getting it wrong the first time is cheap — but only if you did not build a great deal on top of the wrong shape.
Nested paths are permitted where they help: specs/identity/user-auth/spec.md is a legitimate capability path.
7.6 The escape hatch behind both rails
If the four built-in artifacts do not fit the way your team works, fork the workflow rather than fighting it:
openspec schema fork spec-driven my-flow
openspec schema validate my-flow --verboseThen edit schema.yaml — add an artifact, remove one, change a template, or rewire what depends on what. A team that wants a security review between design and tasks adds one artifact and the graph re-sorts itself.
Because templates are ordinary Markdown, editing one changes the AI's output on the very next run, with no rebuild and no reinstall.
7.7 The honest limit
For a weekend prototype you intend to throw away, this ceremony does not pay off, and that is fine. OpenSpec is designed to be lightweight but it is not free.
The test is not "is this a new project?" but "will anybody — including a future AI session — need to know why this works the way it does?" On a throwaway the answer is no. On anything you expect to still be running next year, the answer is yes, and the cheapest moment to start is before there is any code to reverse-engineer.
How is this guide?
Last updated on
Adopting It on an Existing Codebase
The brownfield case, which is the one OpenSpec was built for. You specify only what you are about to change, and the specs fill in around the work you were doing anyway.
Closing the Gap — Brownfield Toward Greenfield
Moving an existing codebase toward full spec coverage, what that can and cannot honestly mean, the six-stage path, and the one place deliberate back-filling is justified.