Skip to main content
This page is a quick intro to the feature.yaml standard for writing plain-language specs. Be sure to read our spec-driven development guide as well.

What is a feature spec?

A feature spec defines what your feature should do and what the acceptance criteria are. It easy to read and write, but is written in YAML format so that it is also machine-readable. Here is a minimal example:
feature:
  name: user-authentication

components:
  LOGIN:
    requirements:
      1: Shows an email and password input
      2: Includes a "Forgot Password" link
      3: On success, navigates to the team overview

constraints:
   AUTH:
      1: Does not leak information about existence or absence of a user's email

Basic Structure

As shown above, the feature spec has three main sections:
  1. feature: Metadata about the feature, such as its name, version, product and description.
  2. components: Functional requirements, organized into component groups.
  3. constraints: Cross-cutting or plumbing requirements (like performance, authorization, data privacy)
You can add detail to any requirement using sub-requirements (up to 1 level of depth):
components:
  MAP:
    requirements:
      1: Clicking a property opens the details panel
      1-1: Highlights the selected property on the map
      1-2: Sends an analytics event

Cross-Referencing

If one requirement relates to another, you can reference it using its complete ID (known as the ACID) like my-feature.COMPONENT.1-1.
requirements:
  1: Opens the Property Details Panel (see property-map.PANEL.1)
  1-1: Zooms to the property on the map, similar to property-map.MAP.4

Handling Deprecated Requirements

Instead of deleting requirements (which loses history), you should mark them with flags so the context is preserved for the future:
requirements:
  1-1:
    deprecated: true
    requirement: Shows a tutorial on first load
    note: Removed due to negative user feedback
  1-2:
    skipped: true
    requirement: Shows location search box
    note: Blocked by geolocation service issue #1234
  1-3:
    replaced_by: ["property-map.MAP.1-4", "property-map.MAP.1-5"]
    requirement: Fly to searched location
    note: Replaced by better UX

Adding Notes

You can also attach context notes directly to requirements. There are two ways to add notes.
requirements:
  # Concise syntax
  1-1: Opens the details panel
  1-1-note: "Customer request, see #1234"

  # Verbose syntax
  1-2:
    requirement: Hides exact location for sensitive properties
    note: Privacy requirement from security team

That’s really all there is to it. This format balances simplicity and flexibility. You can be as precise or vague as you want, as long as your requirements are testable and acceptable. Writing in a .yaml rather has a few obvious benefits, like machine readability, consistency, and generation of predictable & stable IDs. If you want to quickly teach an LLM how to write a feature.yaml, we have formalized the official feature.yaml spec in a feature.yaml specification!
If you are looking for a detailed, formal specification of the feature.yaml format, please see the feature.yaml spec (a spec-for-the-spec!)