In this tutorial, you'll specify a tiny command-line script, write validators that check it, and implement it until every requirement is satisfied. Along the way, you'll render the spec as a document and read a slice.
You'll need a Unix-like shell (macOS or Linux) and about 15 minutes. To set up SLCR in an existing project instead, see the Quickstart.
1. Install slcrLink to this section
Install the CLI with Homebrew:
brew install wack/tap/slcrFor other ways to install, see Installation.
Check that it worked:
$ slcr version
v0.1.02. Create a projectLink to this section
Make a directory for the project and create a specification in it:
$ mkdir greeter && cd greeter
$ slcr init SPEC.slcr.yaml --title Greeter
SPEC.slcr.yaml: created specification greeter
SLCR.toml: created project manifestslcr init created two files. SLCR.toml marks the project's root and
lists its specifications. SPEC.slcr.yaml is the specification, named
greeter after the directory. It has a root section and an empty glossary.
3. Write requirementsLink to this section
Open SPEC.slcr.yaml and replace its contents with:
$schema: https://slcr.dev/reference/schemas/spec/v1.schema.json
formatVersion: "1"
spec:
name: greeter
root:
kind: section
id: SEC-001
title: Greeter
body: A command-line script, `greet.sh`, that greets a person by name.
children:
- kind: requirement
id: REQ-001
title: Greets a person
body: The script MUST greet the person it is given.
modality: MUST
refinement: AND
children:
- kind: requirement
id: REQ-002
title: Prints a greeting
body: Given a name, the script MUST print `Hello, <name>!`.
modality: MUST
refines: [REQ-001]
acceptanceCriteria:
- kind: acceptanceCriterion
id: AC-001
title: Greets Ada
body: Running the script with `Ada` prints exactly `Hello, Ada!`.
- kind: requirement
id: REQ-003
title: Rejects a missing name
body: Given no name, the script MUST exit with a non-zero status.
modality: MUST
refines: [REQ-001]
acceptanceCriteria:
- kind: acceptanceCriterion
id: AC-002
title: Fails without arguments
body: Running the script with no arguments exits with a non-zero status.
glossary:
kind: section
id: SEC-002
title: GlossaryThis spec has one top-level requirement, REQ-001, made of two parts.
REQ-002 and REQ-003 each list REQ-001 in refines, and REQ-001
combines them with AND, so it's satisfied only when both are. Each part has
an acceptance criterion describing what "done" looks like.
Check that the spec is well formed:
$ slcr vet
SLCR.toml: ok
SPEC.slcr.yaml: ok4. Render the specLink to this section
Generate a readable document from the spec. Commands that read one
specification, such as render and slice, read SPEC.slcr.toml unless you
name a file, so name the YAML file:
$ slcr render SPEC.slcr.yaml
SPEC.md: rendered greeterOpen SPEC.md. It reads like a conventional requirements document, with
numbered headings and the acceptance criteria under each requirement. This
is the version people read. The YAML file stays the source: to change the
document, you edit the spec and render again.
5. Read a sliceLink to this section
A slice is the part of the spec that one requirement needs. Print the slice
for REQ-002:
$ slcr slice REQ-002 SPEC.slcr.yamlThe output includes the Greeter section's background, the parent
requirement, and REQ-002 with its acceptance criterion. It doesn't include
REQ-003, which is a separate task. This is the context an agent would
receive to implement REQ-002.
6. Declare a toolLink to this section
Validators run tools that the project declares. For this tutorial, you'll
declare sh, so validators can run short shell scripts.
Create tools/sh.toml:
formatVersion = "1"
name = "sh"
version = "1.0.0"
[validator.schema]
type = "object"
required = ["script"]
additionalProperties = false
properties.script = { type = "string", minLength = 1 }
[invoke]
argv = ["sh", "-c", "{with.script}"]
cwd = "project"This descriptor says that each validator provides a script, which runs
with sh -c from the project root. Declare it:
$ slcr tools add tools/sh.toml
SLCR.toml: added tool sh 1.0.0SLCR.toml now lists the tool with a pin, a hash of the descriptor's exact
contents.
7. Write validatorsLink to this section
Create .validators.slcr.toml in the project root, with one validator for
each acceptance criterion:
formatVersion = "1"
[[validator]]
requirement = "greeter/REQ-002"
criterion = "AC-001"
tool = "sh"
with = { script = 'test "$(sh greet.sh Ada)" = "Hello, Ada!"' }
[[validator]]
requirement = "greeter/REQ-003"
criterion = "AC-002"
tool = "sh"
with = { script = "test -f greet.sh && ! sh greet.sh" }Each validator names its requirement with the spec's name, greeter. The
second one checks that greet.sh exists before checking that it fails.
Without that, it would pass right now, because running a missing script
also fails, and the validator would prove nothing.
8. Watch the check failLink to this section
greet.sh doesn't exist yet, so both validators should fail:
$ slcr check
.validators.slcr.toml validator 1 (greeter/REQ-002 AC-001, sh): red (exit 1)
.validators.slcr.toml validator 2 (greeter/REQ-003 AC-002, sh): red (exit 1)
greeter: 0 satisfied, 3 unsatisfied, 0 unknownBoth parts are unsatisfied, so REQ-001 is too. Because all three are
MUST requirements, each one is a violation, and check fails. The details
of each violation follow on stderr, after the lines shown here.
Seeing every validator fail first confirms that each can tell the difference.
9. Implement the scriptLink to this section
Create greet.sh:
#!/bin/sh
if [ -z "$1" ]; then
echo "usage: greet.sh NAME" >&2
exit 1
fi
echo "Hello, $1!"Run the check again:
$ slcr check
.validators.slcr.toml validator 1 (greeter/REQ-002 AC-001, sh): green
.validators.slcr.toml validator 2 (greeter/REQ-003 AC-002, sh): green
greeter: 3 satisfied, 0 unsatisfied, 0 unknownBoth validators pass, so both parts are satisfied, and their AND satisfies
REQ-001.
What you've builtLink to this section
You now have a project where:
- the spec states what the script must do, in a form tools can work with
SPEC.mdpresents the same requirements as a document for people- each requirement can be sliced into the context needed to implement it
- validators check each requirement, and
slcr checkreports whether the code meets the spec
Next stepsLink to this section
- Set up SLCR in your own project with the Quickstart.
- Learn the ideas behind what you just did in Specifications, Links and satisfaction, Slices, and Validators.
- Write requirements for a real project with Writing requirements, or convert an existing document with Migrating existing documents.
- Use your project's test runner as a tool with Add a validator tool.
- Check every change automatically with Run SLCR in CI.
- Let a coding agent work this way with the agent skill.