reqfile

REQFILE DOCS

Reqfile.yaml

Requirements live in Reqfile.yaml files next to the code they govern. The format is versioned and strictly validated: every error names its file and line.

Example

Reqfile.yaml
# Requirements for this folder, checked by reqfile (https://reqfile.dev)
reqfile: 1

code:
  - id: FAIL_FAST
    ref: Shore, "Fail Fast"
    must: No silent fallbacks, no swallowed errors, no default values that hide a failure.
    why: A swallowed error is an invariant violation nobody sees.
    who: Anyone debugging production.
    checks:
      - command:
          run: ruff check --isolated --select E722,BLE001,S110 --output-format sarif
          files: "**/*.py"
          pass_files: true
          format: sarif
          fix_hint: Catch the specific expected error and handle it visibly, or let it propagate.
      - decision

  - id: DECOMPLECT
    use: acme/reqs@3f2a9c1e0b7d4c6a8e5f1b2d3c4a5e6f7a8b9c0d   # v1.2.0

Rules

  • The file is named exactly Reqfile.yaml and has a reqfile: 1 version key.
  • Requirements are listed under product (what users get), code (how the code is built) or process (how the project is run, such as its CI).
  • A block with use is a use block, taking its requirement by reference (see packages); any other block is a definition.
  • Unknown keys, missing fields and near-miss file names (reqfile.yaml, Reqfile.yml) are errors naming the file and line. A near-miss name is only an error when the file has a top-level reqfile, product, code or process key, so a CI workflow named reqfile.yml is fine.

Fields

FieldRequiredMeaning
idyesSCREAMING_SNAKE_CASE; a definition id appears once in a repository
mustyesThe promise, in one or two sentences
whyyesWhat breaks, and for whom, if it does not hold
checksyesAt least one command or decision check
whonoWho relies on it
refnoWhere the principle comes from
use—Makes the block a use block, taking a definition from elsewhere

Macro and micro

A requirement is a macro: one durable promise, in one or two sentences, that would get a bug filed if it broke six months from now. Its details are micro: tests named after the sentence they prove, in the files its checks run. Implementation decisions, such as a chunk size or a library choice, stay in specs and pull requests.

Keep each Reqfile to at most 10 product requirements; past that, merge requirements into broader promises, or split the folder into subfolders with their own Reqfiles.

Scope

Any folder can hold a Reqfile.yaml. For a file and an id, the block that applies is the one in the nearest Reqfile at or above the file's folder; blocks with that id in farther Reqfiles do not apply to it. A definition id appears once in a repository, and an id at most once in a Reqfile, so a nearer block with the same id is always a use block. Each code unit is judged at most once per id in a run.

Target files come from git (tracked and untracked, never ignored), minus .reqfile/ folders and the exclude globs of the configs above them. reqfile explain <path> shows which blocks apply to a path and where each comes from.

Settings: .reqfile/config.yaml

Any folder can hold a .reqfile/config.yaml, with or without a Reqfile.yaml next to it. Nothing is specific to the repository root: the settings of a folder come, key by key, from the nearest config in that folder or its ancestors, and each check uses the settings of its Reqfile's folder. Every key is optional, and most repositories need no config at all.

.reqfile/config.yaml
base: origin/main                      # default base of --changed (default: origin/HEAD)
exclude: ["vendor/**", "tests/fixtures/**"]   # relative to this folder

decision:                              # defaults shown
  model: "~typesafe/jev-latest"        # the latest Jev on OpenRouter
  api_key_env: OPENROUTER_API_KEY
  endpoint: https://openrouter.ai/api/v1
  concurrency: 16

exclude globs add up down the tree, so a nested config cannot re-include what a parent excluded; a config inside an excluded folder is ignored. The decision keys are described under the Jev key.

A requirement's own files

Everything a requirement needs beyond its block lives in .reqfile/<ID>/ next to its Reqfile: its scripts, its decision.yaml, and its labeled examples/. Commands reach that folder through $REQFILE_ASSETS.

layout
.reqfile/
  config.yaml                 # settings for this folder and below (optional)
  FAIL_FAST/
    decision.yaml             # what a decision check asks
    examples/                 # labeled cases, measured by reqfile eval
      bare-except/
        example.yaml
        files/...

Something missing or wrong? Open an issue ↗ · Agents: read the skill.