@usearazzo/cli puts the toolkit behind one binary, usearazzo. Its one command today is validate, a thin wrapper around @usearazzo/validator: it checks an Arazzo document and prints every problem with the location that caused it. The checks, the rule codes, and their messages are the Validator’s, so its Rules section is the list of what validate can report.

Installation

npm install --global @usearazzo/cli

Or run it without installing:

npx @usearazzo/cli validate adopt-a-pet.arazzo.yaml

The package requires Node.js 20.10 or newer. It is pre-1.0: the version documented here is an alpha, and options and output may still change before the stable release.

Usage

usearazzo [options] [command]
Option Description
-V, --version Print the version number.
-h, --help Print help. usearazzo validate --help prints the help of one command.
Command Description
validate [options] <uri> Validate and lint an Arazzo document.
help [command] Print help for a command.

Running usearazzo with no command prints the help and exits with 1.

validate

usearazzo validate [options] <uri>

Here is a document whose two steps on lines 16 and 19 are both called find-pet:

arazzo: 1.0.1
info:
  title: Adopt a pet
  summary: Find a pet and adopt it.
  description: Find an available pet in the store and adopt it.
  version: 1.0.0
sourceDescriptions:
  - name: petstore
    url: ./petstore.openapi.json
    type: openapi
workflows:
  - workflowId: adopt-a-pet
    summary: Adopt a pet.
    description: Find an available pet and adopt it.
    steps:
      - stepId: find-pet
        description: Find an available pet.
        operationId: findPetsByStatus
      - stepId: find-pet
        description: Adopt the pet.
        operationId: updatePet

And here is what validate makes of it. The second range ends at line 22, column 1: the position just after the file’s last line break.

$ usearazzo validate adopt-a-pet.arazzo.yaml
adopt-a-pet.arazzo.yaml
  16:9-18:38  error  9040403  Every step must have a unique 'stepId' within a workflow.
  19:9-22:1   error  9040403  Every step must have a unique 'stepId' within a workflow.

✖ 2 problems (2 errors)

The run exits with 1, because the document has errors.

The document

<uri> is one of:

  • a path, absolute or relative to the current working directory
  • a file: URI, such as file:///home/you/adopt-a-pet.arazzo.yaml
  • an HTTP or HTTPS URL

A local file must end in .json, .yaml, or .yml. Whether it is JSON or YAML is read from the content.

The source descriptions the document names are fetched and parsed too, unless the configuration file turns that off. No rule checks them yet, so a missing or broken source description produces no problem. The Validator reference has the details.

Options

Option Default Description
-f, --format <format> stylish Output format: stylish or json.
--json   Shorthand for --format json. Wins when both are given.
-o, --output <file> stdout Write the report to a file instead. The path may not be the input document.
-c, --config <file> see below The configuration file to use, relative to the current working directory.
--json-schema-validation off Also check the document against the Arazzo JSON Schema for its version.
--max-problems <n> all Report at most n problems, a positive integer. The exit code still counts all of them.
--fail-severity <severity> error Lowest severity that fails the run: error, warning, info, or hint. See Choosing what fails.

JSON Schema validation is off by default because the rules already report most of what it finds, so turning it on mostly doubles the output. The Validator reference shows what it adds.

Stylish output

The default format prints the document’s name, one row per problem, and a summary. Problems are sorted by line, then column, then severity.

onboarding.arazzo.yaml
  16:9-18:1  warning  9050201  Step 'description' should be present and non-empty string.

⚠ 1 problem (1 warning)

Each row has four columns:

Column Example What it is
Location 16:9-18:1 Where the problem starts and ends, as line:column. Both count from 1, the way editors show them. A problem that starts and ends at the same spot prints one line:column.
Severity warning error, warning, info, or hint.
Code 9050201 Usually the rule’s numeric code, listed in the Validator’s rules. json-schema for a problem found by JSON Schema validation. Empty for a YAML or JSON syntax error, whose code is 0.
Message   What is wrong.

The summary starts with ✖ when there is at least one error and ⚠ otherwise. With --max-problems, a last line says how many were left out:

$ usearazzo validate adopt-a-pet.arazzo.yaml --max-problems 1
adopt-a-pet.arazzo.yaml
  16:9-18:38  error  9040403  Every step must have a unique 'stepId' within a workflow.

✖ 1 problem (1 error)
(showing 1 of 2 problems)

A document with no problems prints No problems found.

Output to a terminal is coloured. Piped output and output to a file are plain text.

JSON output

--json prints the problems as a JSON array of Language Server Protocol diagnostics, in the same order as the stylish rows:

$ usearazzo validate adopt-a-pet.arazzo.yaml --json --max-problems 1
[
  {
    "range": {
      "start": {
        "line": 15,
        "character": 8
      },
      "end": {
        "line": 17,
        "character": 37
      }
    },
    "message": "Every step must have a unique 'stepId' within a workflow.",
    "severity": 1,
    "code": 9040403,
    "source": "apilint",
    "data": {}
  }
]

This is exactly what validateURI returns, so the Validator reference describes every field. Two differences from the stylish format matter:

  • Lines and characters count from 0, as the protocol defines them. Line 15 here is line 16 in the stylish output.
  • Severity is a number: 1 error, 2 warning, 3 information, 4 hint.

A document with no problems prints [].

Exit codes

Code When
0 No problem at or above --fail-severity.
1 At least one problem at or above --fail-severity, or the run could not finish.

The exit code is computed from every problem, before --max-problems cuts the list, so a cap never hides a failure.

Choosing what fails

By default only errors fail a run. The onboarding document above has a warning and nothing else, so it exits with 0. Lower the threshold, and the same document fails:

$ usearazzo validate onboarding.arazzo.yaml --fail-severity warning
onboarding.arazzo.yaml
  16:9-18:1  warning  9050201  Step 'description' should be present and non-empty string.

⚠ 1 problem (1 warning)
$ echo $?
1

--fail-severity hint fails on any problem at all.

Errors

When the run cannot finish, the reason goes to stderr, prefixed with Error:, and nothing goes to stdout. The reason includes the whole chain of causes, down to the file system or HTTP error:

$ usearazzo validate https://example.com/nope.arazzo.yaml
Error: Failed to read Arazzo Document at "https://example.com/nope.arazzo.yaml": Error while reading file "https://example.com/nope.arazzo.yaml": Error downloading "https://example.com/nope.arazzo.yaml": Request failed with status code 404

The same happens when:

  • the document cannot be read
  • the configuration file cannot be read, is not valid YAML or JSON, or is not a mapping
  • --output points at the input document: Error: --output path must differ from the input file
  • the report cannot be written to the --output file

An invalid option value is caught before anything runs, and also exits with 1:

$ usearazzo validate adopt-a-pet.arazzo.yaml --max-problems 0
error: option '--max-problems <n>' argument '0' is invalid. must be a positive integer.

A problem in the document is never an error. A YAML syntax error, for example, is reported as a problem like any other.

Configuration file

A configuration file holds the validation settings, so every run, and everyone on the team, uses the same ones.

Where it is found

Without --config, usearazzo looks in the current working directory for these names, in this order, and uses the first one it finds:

  1. .usearazzo.yaml
  2. .usearazzo.yml
  3. .usearazzo.json
  4. usearazzo.yaml
  5. usearazzo.yml
  6. usearazzo.json

Parent directories are not searched. With none of them present, the defaults apply. --config points at any other file, and that file must exist.

What it holds

The file is YAML or JSON. Its one key, languageService, takes the same options as the Validator’s second argument, and they are merged over the Validator’s defaults:

languageService:
  validationContext:
    jsonSchemaValidation: true # default: false
    semanticValidation: true # default: true
    referenceValidation: true # default: true
  parseContext:
    arazzo:
      sourceDescriptionsResolution: true # fetch and parse source descriptions (default: true)

Setting semanticValidation: false turns every rule off. With JSON Schema validation off as well, validate then reports only YAML and JSON syntax errors. The Validator reference explains what each option does.

For a document you did not write, turn off everything beyond the document itself:

languageService:
  parseContext:
    fileAllowList: []
    arazzo:
      sourceDescriptionsResolution: false

An empty file means no configuration.

Precedence

Command-line flags win over the configuration file, and the configuration file wins over the Validator’s defaults. A flag only overrides when you give it: without --json-schema-validation, the file’s jsonSchemaValidation stands.

Running in CI

Nothing beyond the command is needed. A failing document fails the step through its exit code. Here is a complete GitHub Actions workflow, saved as .github/workflows/arazzo.yml:

# .github/workflows/arazzo.yml
name: Arazzo
on: [push, pull_request]
jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 22
      - name: Validate Arazzo workflows
        run: npx @usearazzo/cli validate workflows/adopt-a-pet.arazzo.yaml

To keep the report as a build artifact, write it as JSON and upload it. The validate step still fails on errors, so the upload step needs if: always() to run after a failure:

      - name: Validate Arazzo workflows
        run: npx @usearazzo/cli validate workflows/adopt-a-pet.arazzo.yaml --json -o arazzo-report.json
      - uses: actions/upload-artifact@v7
        if: always()
        with:
          name: arazzo-report
          path: arazzo-report.json

Supported versions

Both JSON and YAML are accepted for every version.