# AGENTS.md — `req`
`req` is a Rust CLI that gives LLM agents (and humans) a *managed* interface
for editing software-project requirements. The on-disk file (`project.req`)
is plain JSON so it diffs well in git, but every mutation is mediated by the
CLI, which enforces requirements best practice. **Agents must never edit the
file directly.**
This project dogfoods its own tool: the requirements you read in
`project.req` describe the very binary you're working on. Treat the file as
the source of truth for behaviour. Treat this document as the source of
truth for *how to work*.
---
## 1. Project shape
```
cli_req/
├── Cargo.toml
├── AGENTS.md ← this file
├── project.req ← managed requirements (dogfooded)
└── src/
├── main.rs dispatch only
├── cli.rs clap surface — one source of truth
├── model.rs Project / Requirement / Kind / Priority / Status / Link
├── storage.rs JSON I/O + SHA-256 integrity hash
├── validate.rs best-practice rules
├── help_text.rs `req help <section>` content
├── tui.rs dialoguer-based interactive browser
├── web.rs STUB — local web server
├── mcp.rs STUB — MCP JSON-RPC server
└── commands/ one file per subcommand
```
If you add a subcommand: add the `clap` variant in `src/cli.rs`, a module
under `src/commands/`, dispatch in `src/main.rs`, and **at least one** help
section in `src/help_text.rs`.
## 2. Cardinal rules
1. **Never read or write `project.req` outside `storage::{load, save}`.**
The file has an integrity hash. Bypassing the wrapper means stale data,
broken hashes, and silent corruption.
2. **Never relax the validator to make a test pass.** The validator IS the
product. If a rule is wrong, change the rule deliberately, update the
`best-practice` help section, and update affected requirements via the
CLI.
3. **Every mutation goes through a `Command`.** Don't add helpers that
mutate `Project` from outside `commands/`. This is what we promise.
4. **History is append-only.** Use `commands::history(action, reason)`
when you mutate a requirement. Never edit or drop existing entries.
5. **Don't widen the agent surface casually.** Agents should be able to
do everything humans can — *but only through `req <subcommand>` or the
future `req mcp`*. No fast-paths that skip validation.
6. **No new reserved top-level fields without bumping `_format`.** The
reserved keys are `_warning`, `_instructions`, `_format`, `_integrity`.
7. **New behaviour gets a REQ first, then the code.** If you're about
to add a new command, a new validator rule, or a non-trivial
behaviour change, write the requirement first via `req add ...`,
then implement, then reference the new REQ-ID from the code with a
`// REQ-NNNN:` line at the top of the relevant module. The
`req review --gate` check in CI fails any PR that adds source files
without a REQ marker — this is the rule that catches "shipped a
feature without a backing requirement". The validator can only
check what's recorded; this gate is what makes sure new behaviour
gets recorded in the first place. For bug fixes that don't change
the contract a REQ isn't required; the existing REQ for that
behaviour is the right home.
## 3. The integrity model (read this once, refer to it later)
`storage::save` writes pretty-printed JSON with four reserved fields:
```jsonc
{
"_warning": "DO NOT EDIT THIS FILE BY HAND. Managed by the `req` CLI.",
"_instructions": [ "...multi-line directions..." ],
"_format": "req-v1",
"_integrity": "sha256:<hex>",
"name": "...",
"requirements": { ... }
}
```
The hash covers everything *except* the four reserved fields, in canonical
form (sorted keys, no whitespace). Any direct edit breaks the hash; the
CLI refuses to read the file and tells the user to run
`req repair --confirm-direct-edit`.
The hash gives **integrity** (the CLI wrote this last). It does not give
**authenticity** (a trusted human approved it). For authenticity, use
signed git commits and inspect with `req audit`. See `req help audit`.
## 4. Demonstrated workflow — read this end-to-end at least once
This is how you, the agent, should work on this codebase. The same flow
applies to any project using `req`.
### 4.1 Get a green baseline
```sh
cargo build --release
./target/release/req validate # 0 errors required to ship
./target/release/req coverage --path src
```
If both are clean, you can start. If not, address findings before adding
new behaviour.
### 4.2 Read before you write
```sh
./target/release/req help # section index
./target/release/req help best-practice # the validator's contract
./target/release/req help version-control
./target/release/req help integration
./target/release/req list --tag <topic> # narrow to the area you're touching
./target/release/req show REQ-0007 # full detail with history
```
Pulling the slice you need beats reading the whole file in one go. Use
`req help all` only when you genuinely need everything.
### 4.3 Make changes managed
Adding a new requirement (non-interactive, the agent-friendly form):
```sh
./target/release/req add \
--title "Short imperative title" \
--statement "The system shall ..." \
--rationale "Why this exists" \
--kind functional \
--priority should \
--accept "Concrete, testable criterion" \
--accept "Second criterion" \
--tag <topic>
```
Updating a requirement — always include `--reason`:
```sh
./target/release/req update REQ-0015 \
--status approved \
--reason "Reviewed in 2026-05-17 sync"
```
Linking — parent for hierarchy, depends-on / verifies for trace:
```sh
./target/release/req link REQ-0026 REQ-0019 -k depends-on
```
Soft-delete (default) preserves links and history:
```sh
./target/release/req delete REQ-XXXX --reason "Superseded by REQ-YYYY"
```
### 4.4 Reference requirements from code
Drop `REQ-NNNN` markers in source comments where you implement them:
```rust
// REQ-0003: integrity hash verification
fn load(...) { ... }
```
Then `req coverage --path src` tells you which requirements have no code
references (orphans) and which markers point at non-existent or obsolete
requirements (ghosts). Aim for: every functional requirement at
`Implemented` status has at least one code reference.
### 4.5 Before you finish
```sh
cargo build --release
./target/release/req validate # must be 0 errors
./target/release/req coverage --path src
git diff project.req # human-readable, by design
```
If you touched behaviour that has a requirement, you should see a
matching `req update` in the same change. Diffs to `project.req` and
diffs to `src/` should tell the same story.
## 5. Version-control workflow
The .req file is git-tracked normal JSON. Three things change the
default workflow:
- **Pre-commit hook.** Run `req hooks install` once per clone. It writes
`.git/hooks/pre-commit` that runs `req validate` on staged .req files.
- **Merge driver.** `req hooks install` also adds
`*.req merge=req-merge` to `.gitattributes`. Activate it in your
clone with the two `git config` lines that the command prints. The
driver runs `req renumber --base %O` so merges auto-fix ID collisions.
- **Renumber after merge.** If you skipped the driver and merged by
hand, run `req renumber --base origin/main` and then
`req repair --confirm-direct-edit` if the integrity hash needs
refreshing. `req help version-control` has the full details.
## 6. Provenance / signing
We do **not** ship our own signature scheme. Authenticity comes from
signed git commits. `req audit` walks `git log --follow` on the .req
file and prints signature status (good / bad / expired / no-signature)
and signer per commit. If your project has compliance requirements:
```sh
git config commit.gpgsign true # or use SSH-signed commits
./target/release/req audit # see the trail
./target/release/req audit --json -n 500 # for tooling
```
`req help audit` documents the signature-status codes.
## 7. Conventions
- **Errors:** `anyhow::Result` at command boundaries. Print user-friendly
messages that name the next command to run, like the integrity-check
failure does.
- **Time:** `chrono::Utc::now()` everywhere; never `Local`.
- **IDs:** Allocated by `Project::allocate_id()` only. Never reuse, never
let an agent pick its own.
- **Statuses:** Draft → Proposed → Approved → Implemented → Verified.
Obsolete is the terminal sink for retired requirements.
- **clap help strings stay tight and accurate** — they're the primary UX
for humans and agents alike, and they ship with the binary.
- **`req help <section>` stays in sync** with the validator and the
command surface. Adding a rule? Document it. Adding a command? Add a
section (or extend one).
## 8. Status as of v0.1.0
- **120 tests passing** across 12 integration test files; `cargo test
--release -- --test-threads=1` is the canonical invocation. CI runs
each test binary serially to keep the concurrency suite within the
30s file-lock timeout.
- **`cargo-llvm-cov` line coverage ~58%**; validate.rs / storage.rs are
> 85%, mcp.rs and web.rs ~50%, tui.rs is intentionally 0% (dialoguer
interactive code is hard to fixture).
- **All three surfaces are at parity** (REQ-0083): CLI, MCP, TUI offer
the same agent-relevant operations. Two automated tests fail the
build if a new CLI command lands without a matching MCP tool *and*
TUI menu entry, modulo a documented humans-only exclusion list.
- **CI gates on:** `cargo fmt --check`, `cargo clippy -D warnings`,
`cargo build -D warnings`, `cargo test`, `req validate`,
`req coverage --strict --allow REQ-0051 REQ-0052 REQ-0061 REQ-0082`.
- **CI advisory:** `req doctor`, `req stale --path .`.
- **No auth/multi-user model.** `REQ_ACTOR` / `USER` / `USERNAME`
attribute history; `REQ_ACTOR_KIND` (human/agent) is the provenance
signal. Treat attribution as advisory until signed-commit policy is
added (see §6 — `req audit --gate`).
## 9. Quick reference
```sh
# project lifecycle
req init -n <name> # create project.req
req tui # interactive menu (16 actions)
req validate # rules across the project
req status # delivery_progress_pct
req export -f markdown -o reqs.md # publish
# day-to-day
req add ... # see §4.3 (also: --from-json)
req list --status draft --tag foo # Obsolete hidden by default
req show REQ-0007 # detail + history + test records
req update REQ-0007 --status approved --reason "..."
req link REQ-0008 REQ-0007 -k parent
req delete REQ-0007 --reason "..." # soft; --hard if no inbound links
req next # dependency-aware next pick
req batch path/to/changes.json # transactional multi-mutation
req import -f markdown spec.md # bulk ingest through the validator
# evidence
req test record REQ-0007 --result pass --notes "..."
req test run --promote # cargo test + record + auto-Verify
req verify REQ-0007 --by composition --cites REQ-0003 --notes "..." --promote
req verify REQ-0007 --by inspection --notes "..." --promote
req stale --only-stale # records whose linked files changed
# integration
req hooks install [--claude-code] # pre-commit + merge driver
req doctor # per-clone setup audit
req renumber --base origin/main # post-merge ID collisions
req coverage [--by-file | --unlinked-files | --remap OLD=NEW]
req coverage --strict --allow REQ-NNNN # CI gate
req diff origin/main..HEAD # per-requirement transitions
req check origin/main # incremental validate + coverage
req audit # git signature trail
req audit --gate --require-good-signature
req mcp # JSON-RPC stdio server
req mcp --init-config # write .mcp.json bootstrap
req schema [add|batch|import] # JSON Schemas for structured input
req migrate # schema migration (no-op on req-v1)
# recovery
req repair --confirm-direct-edit # after intentional hand edits
# documentation
req help # section index
req help <section> # drill in
req help <section> --install # write into AGENTS.md (this file)
req help <section> --json # structured form for tooling
req help all # everything
```
## 10. Green baseline ritual
```sh
cargo fmt --check
cargo clippy --release --locked -D warnings
cargo build --release
cargo test --release -- --test-threads=1
req validate
req coverage --path . --strict --allow REQ-0051 --allow REQ-0052 \
--allow REQ-0061 --allow REQ-0082
```
If all six commands exit 0, you have a green baseline. Make your
change, run them again, you're done. CI runs exactly these (plus
`req doctor` and `req stale` as advisory).
## req — agents
_How LLM agents should drive this tool — read this first._
```
This project uses the `req` CLI for managed requirements. As an
agent working on this project you MUST drive every requirements change
through `req` — never read or edit project.req directly.
WHEN TO REACH FOR `req`
trigger first command
--------------------------------------------------- --------------------------
user describes new behaviour the system should have req add ...
starting work on a feature req list / req show <id>
about to commit req validate
changed behaviour covered by a requirement req update <id> --reason
refactor; unsure what's load-bearing req coverage --path src
finding code with no requirement link req coverage --unlinked-files
requirement is no longer relevant req delete <id> --reason
file won't load (integrity error) req repair --confirm-direct-edit
merge brought in colliding IDs req renumber --base origin/main
QUICK COMMAND CRIB
req list # what exists
req show REQ-0007 # full detail with history
req add --title ... --statement ... # see `req add --help`
req update <id> --status implemented --reason "..."
req link <from> <to> -k parent
req validate # must be clean before ship
req coverage --path src # spec ↔ code
req help <section> # docs (overview, concepts,
# best-practice, workflow,
# integration, audit)
RULES
* Statements need a normative modal verb (shall / must / should / will)
and one obligation per requirement. The validator rejects bad input
and warns on smells — let it. Don't argue with the validator; rewrite.
* Pass --reason on every update / delete so history attributes the why.
* Drop // REQ-NNNN markers in source where you implement a requirement;
`req coverage` connects spec to code via those markers.
* Never `cat` / `read_file` project.req. The integrity hash will block
the next operation if you edit it by hand.
INSTALL THIS GUIDANCE INTO AGENTS.md
req help agents --install # idempotent; updates a managed
# block between sentinel markers.
# Use --path PATH for non-default
# locations.
MCP (Model Context Protocol)
An MCP server is built in. Two ways to use it:
* Run it: `req mcp` — speaks JSON-RPC 2.0 over stdio. Pair with an MCP
client (Claude Code, etc.).
* Bootstrap: `req mcp --init-config` — writes a .mcp.json at the repo
root so MCP-capable clients can launch the server automatically.
Once connected, call tool `req_help` with {section: 'agents'} for the
trigger table. See `req help mcp` for the full transport detail.
```
<!-- req:help:agents:end -->