Questions about reqmd, grouped by topic: what it is, how to use it, and how it fits your workflow.

What is reqmd?#

What does reqmd do?

reqmd is a command-line tool for writing, linking, and checking requirements and verification measures in plain Markdown. You write each requirement as a heading, a small YAML block, and some prose. reqmd checks every cross-reference — broken links, missing coverage, circular dependencies, stale version pins — and tells you what's wrong. It also exports to HTML, CSV, and graph formats.

The key idea: your spec lives in text files, in Git, next to your code (or in its own repo). The validation runs in milliseconds. No database, no server, no lock-in.

What can I use reqmd for?

Any project where you need to write requirements and trace them to each other, to tests, and to reviews:

  • Spec-first development — write the requirement, then the test, then the code, all in one pull request.
  • Higher-level specification — stakeholder needs, system requirements, software design, and test specs traced across a V-model. The spec does not need to live next to the code; it can be a standalone repo for requirements and traceability at any level.
  • Verification and validation tracking — load test results from CI (CTRF JSON) and manual review results (Markdown), and get verdict badges showing which measures pass, fail, or are still missing.
  • CI-gated traceability — every pull request that touches a spec runs reqmd check and gets a pass/fail answer.
  • Live reviewreqmd serve gives you a live-reloading HTML preview while you edit.
Does reqmd only handle requirements, or also verification measures?

Both. reqmd treats verification measures — tests, reviews, inspections, analyses, demonstrations — as first-class objects. A test specification is a requirement with a verify attribute. A test result is loaded as a pseudo-requirement with an outcome (pass/fail/skipped/inconclusive) that traces back to the measure it verifies.

This means the full traceability chain is: stakeholder need → system requirement → software requirement → test specification → test result. Every link is checked. If an approved measure has no result, reqmd warns (missing-verdict). If the latest result is a fail, reqmd errors (failing-verdict).

Does the spec need to live next to the code?

No. reqmd works on any directory of Markdown files. Many teams keep the spec in the same Git repository as the code so that spec changes and code changes land in the same pull request. But a standalone requirements repository works just as well — point reqmd check at whatever directory contains your spec tree.

For higher-level requirement specification and traceability (stakeholder needs, system architecture, supplier specs), a separate repo is often the better choice. The spec is reviewed by people who don't work in the codebase — product managers, QA, safety engineers — and a dedicated repo with its own review cycle keeps things clean.

How is reqmd different from a wiki or a Google Doc?

A wiki stores text. reqmd stores text and checks it. In a wiki, a broken trace link is a human problem — someone has to notice it. In reqmd, a broken link is a CI failure — the tool catches it on every commit. You also get structured export (HTML with trace navigation, CSV, graph), version pinning, status lifecycle, and verification result tracking. None of that exists in a wiki.

How is reqmd different from OpenFastTrace?

Both are static-spec tools with a strong emphasis on bidirectional traceability. The differences:

  • Data format. reqmd is Markdown-only with a YAML block; OFT uses its own .xml formats.
  • Runtime. reqmd is a single Go binary; OFT is a Java project.
  • Verification. reqmd has first-class CTRF ingestion and outcome-gated checks (missing-verdict, failing-verdict); OFT treats verification as separate artifacts.
  • Fit. OFT is a stronger fit for traditional spec-by-spec coverage analysis; reqmd is a stronger fit for git-native, text-first, CI-driven workflows.

Both are good tools. Pick by your team's existing workflow.

How is reqmd different from Jama / Polarion / DOORS?

Those are database-backed requirements-management suites. They've been the default in regulated industries for 20 years, and they solve a real problem — managed workflows, audit trails, role-based access. But they come with structural problems that get worse as your team gets more agile:

  • Slow. Every interaction is a web UI round-trip. A spec review that takes 10 minutes in a Git diff takes an hour in DOORS.
  • Disconnected from the code. The spec is in a database; the code is in Git. There is no native connection. When a developer renames a function, the spec doesn't know.
  • No real branching. "Baselines" are snapshots, not branches. You can't git checkout -b, try a change, and merge it. Two teams working on the spec simultaneously means lock-then-edit.
  • No submodules. A multi-team spec is one monolithic database. You can't split it into per-team repos and compose them.
  • Not CI-native. Running "does the spec validate?" in CI requires a REST API call, authentication, and a custom script. With reqmd it's reqmd check spec/ — one binary, 16 ms, exit code 0/1/2.
  • Not developer-friendly. Developers don't open DOORS. They open their editor. If the spec is in a database, the developer never reads it, and the spec drifts from the code.
  • Vendor lock-in. Your spec is in a proprietary database schema. Exporting it is a project. With reqmd, your data is plain text — diffable, portable, yours.

Pick reqmd when you want the spec to live where the developers work — in Git, next to the code, with branching, submodules, CI, and pull-request review as the natural workflow. Pick an RM suite when you specifically need named approvers with electronic signatures and a regulated audit trail that an auditor reads from the tool. Some teams use both: reqmd for the engineering spec, the RM suite as the system of record. See the compare page for the full side-by-side.

How it works#

How does the GitHub review workflow work?

reqmd is designed for Git-based review. The spec lives in a Git repository (either next to the code or in a dedicated repo). Every change to a requirement, a trace link, a schema, or a verification result is a commit. Here's the typical workflow:

  1. Author. Open a branch. Edit the .md files — add a requirement, update a trace link, change a status. Commit and push.
  2. Check locally. Run reqmd check spec/ before pushing. If it exits non-zero, fix the issues.
  3. Open a pull request. The diff shows exactly what changed: the requirement text, the trace link, the schema. Reviewers see the same diff they'd see for a code change.
  4. CI runs the check. A GitHub Action (or GitLab CI job) runs reqmd check --json spec/ on the PR. If it fails, the PR is blocked. The JSON output can be posted as a comment or an annotation.
  5. Review. Reviewers read the diff, check the trace links, run reqmd serve spec/ for a live preview if they want to see the rendered spec with links resolved.
  6. Merge. Once the check passes and the review is approved, merge. The spec is now consistent — no broken links, no missing coverage, no stale version pins.

The key advantage over a database-backed RM tool: the review happens in the same pull request interface the team already uses for code. The diff is the review artifact. The check is the gate. No separate tool, no separate login, no separate review state to track.

How does the trace check work?

reqmd builds a trace graph from every trace: link in every requirement, then checks it in one pass:

  • Broken references — a trace: pointing to an ID that doesn't exist anywhere.
  • Missing coverage — a requirement with requires-trace-from that no downstream requirement traces to.
  • Circular dependencies — a chain of traces that loops back to itself.
  • Version pin staleness — a downstream pinned to SYS-001~3 but the upstream is now version 5.
  • Missing verdicts — an approved measure with no verification result.
  • Failing verdicts — the latest result for a measure is fail.

Broken references, cycles, and failing verdicts are errors (exit code 1). Missing coverage and missing verdicts are warnings (exit code 0, but shown in the output).

How does the status lifecycle work?

Every requirement has a status: draft (work in progress) or approved (signed off). Only approved requirements count as coverage providers — a draft requirement can be referenced by a trace but does not satisfy a requires-trace-from expectation.

Requirements can also carry a disposition: implemented (actively developed), deferred (parked, with a reason), or rejected (not doing it, with a reason). When a document directory sets mandatory-disposition: true, every requirement must have a disposition.

How do I load verification results?

Two formats, both loaded with the --results flag (repeatable):

  • CTRF JSON — from automated test runs. The x-reqmd.id field in each test maps it to a requirement ID. reqmd reads the pass/fail/skipped verdict and the timestamp.
  • Manual results (Markdown) — for reviews, inspections, analyses. Each result is a Markdown file with an attr block carrying outcome, verifier, verified-at, and a trace back to the measure it verifies.

reqmd synthesizes one pseudo-requirement per result and runs two new checks: missing-verdict (approved measure, no result) and failing-verdict (latest result is fail). The HTML export shows color-coded verdict badges on every measure card.

Is there a web UI?

There is no separate web UI; the HTML export is the web UI. Run reqmd serve spec/ for a live-reloading preview, or reqmd export html spec/ -o docs/ and host the resulting docs/ directory as a static site.

The HTML export includes card-based layout, upstream/downstream trace links, a document chain tab strip for V-model navigation, status filters, theme toggle, and (with --results) color-coded verdict badges on measure cards.

Does reqmd work without Git?

Yes, for everything except baseline diff. The spec tree is plain files; no Git required to validate, list, or export. baseline diff is the one command that calls git archive to read a tagged snapshot — every other command operates on whatever directory you point it at.

How do I use git submodules for configuration management?

Configuration management — the discipline of controlling, versioning, and composing a multi-team spec across component boundaries — is a core systems engineering practice. In reqmd, it's built on Git submodules. Each team owns their own requirements repo as a git submodule, and a top-level repo assembles them into a single tree that reqmd check validates as a whole.

A typical layout:

spec-monorepo/
  stakeholder/        ← submodule: git@github.com:team/stakeholder-spec.git
  system/             ← submodule: git@github.com:team/system-spec.git
  software/           ← submodule: git@github.com:team/software-spec.git
  tests/              ← submodule: git@github.com:team/test-spec.git

Each submodule is a normal reqmd document directory with its own schema.yaml. The top-level repo just holds the submodule references — no spec content of its own. When a team updates their spec, they push to their repo and the top-level repo bumps the submodule pin.

Cross-repo trace links work out of the box. A requirement in system/ can trace to a requirement in stakeholder/ by ID — reqmd resolves it across the submodule boundary because all submodules are on disk under the top-level directory. Use qualified references (document-id/ID) if two submodules share ID prefixes.

The baseline is the submodule pins. When you need to compare two baselines, reqmd baseline diff v1.0 v2.0 reads the submodule pins at each tag and reports what changed — added, removed, and modified requirements across all submodules, plus which submodule pins were updated. No separate configuration management tool needed; git is the tool.

Review workflow works the same as a single repo. A PR that bumps a submodule pin shows the exact diff of the submodule's spec changes. Reviewers see what changed, CI runs reqmd check on the assembled tree, and the merge updates the baseline.

How do I link requirements down to the actual code?

Use the companion reqmd-import tool. It walks your Go or Python source code with a tree-sitter grammar and writes per-package .md requirements into your spec tree. Every function, type, and method gets a requirement ID in the same namespace as your spec.

The extracted code requirements are marked external: true and live in an imported/ sub-tree. They don't need upstream traces (they're not authored by hand), but they do trace to the real implementation. The result: the same reqmd check that catches a broken spec reference also catches a broken implementation reference — if a function is renamed or deleted, the trace from the spec to that function becomes a broken reference.

The full traceability chain becomes: stakeholder need → system requirement → software requirement → test specification → test result → code implementation. Every link is a plain-text reference that reqmd validates mechanically.

reqmd-import is a separate Go module with its own release cadence. It supports Go and Python today; Rust and Zig are reserved for future work.

Schema & data#

What does a schema.yaml file look like?

Each document directory has a schema.yaml that defines the required attributes, their types, and reqmd-specific options. A minimal example:

$schema: "https://json-schema.org/draft/2020-12/schema"
$id: "my-requirements"
title: "My Requirements"
type: object
required:
  - priority
properties:
  priority:
    type: string
    enum: [Critical, High, Medium, Low]
additionalProperties: false

x-reqmd: level: system-requirements document-id: system id-prefix: SYS- upstream: level: stakeholder-needs sources: - ../01-stakeholder/

See the cheat sheet for the full list of x-reqmd options and all commands.

Can I use JSON instead of YAML for the schema?

No, the format is fixed to YAML. The schema.yaml filename and the YAML dialect are hard-coded. You can hand-author the file in JSON-compatible YAML and it will round-trip fine; extensions like x-reqmd work the same.

Why YAML? The data is small (a few hundred lines per directory at most), human-authored, and benefits from comments.

What about Excel or Word import?

Not built in. The recommended path is reqmd init with a custom preset and a one-time script that produces the Markdown files. For ongoing imports, write a small script that walks the Excel/Word file and emits one Markdown file per requirement.

The reqmd-import source-code extraction tool is the closest existing project — it extracts requirement IDs from Go and Python source via tree-sitter.

Does reqmd work with my issue tracker (Jira, GitHub Issues, Linear)?

No native integration. The common pattern is to put the issue-tracker key in a custom attribute (e.g. jira: PROJ-123) and search via reqmd ls --json or reqmd stats --json. The issue tracker is a downstream consumer of the spec, not a source.

How does the trace check handle cycles?

reqmd check reports a cycle as an error (with the cycle path) and exits non-zero. There is no auto-resolution; cycles are a modeling problem to fix in the source.

What about ReqIF?

Not supported yet. The data model is compatible; the importer is what's missing. A future reqmd-import reqif subcommand is the most likely path.

CI & performance#

Can I run reqmd in CI without a database?

Yes, no database, no daemon, no state. Each check is self-contained. Pin the version in CI. The recommended CI invocation:

- run: go install github.com/dVoo/reqmd/cmd/reqmd@
- run: reqmd check --json requirements/ > report.json
- run: reqmd check requirements/ --results ci-artifacts/

Use --json for programmatic parsing, plain output for human review.

Does reqmd scale to my 50,000-requirement spec?

Yes. Based on the measured linear scaling (~50 req/ms on 12 cores), 50,000 requirements would take ~2.5 seconds for check. Even 720,000 requirements finish in under 10 seconds. The bottleneck is file I/O, not the graph. See the benchmarks page for the full numbers.

What do the check / warning / error symbols mean?

Three severity levels:

  • — passes schema validation and all required trace checks.
  • — passes schema validation but has a warning (broken reference, untraced, missing verdict). Warnings do not affect the exit code.
  • — fails schema validation or has an error (cycle, missing required attribute, failing verdict). Errors exit non-zero.

Only errors affect the exit code. Warnings are informational.

What's the deal with the ladybug build tag?

reqmd export graph writes a LadybugDB database for Cypher queries. It pulls in a Cgo dependency, so it's gated behind a build tag:

go build -tags ladybug -o reqmd ./cmd/reqmd

Without the tag, export graph is not built. The rest of the CLI works exactly the same.

Still have questions?#

  • Read the Quickstart — most “how do I…” questions are answered there.
  • Read the Cheat sheet — full command overview and schema reference.
  • Read the Use cases page for what reqmd does and what it doesn’t.
  • See the Compare page for how reqmd stacks up against other tools.
  • Open an issue on GitHub.