{"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"lint-asyncapi-with-redocly-cli","__idx":0},"children":["Lint AsyncAPI with Redocly CLI"]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Experimental AsyncAPI support"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This feature is at an early stage, please use with caution and send us lots of feedback!"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In addition to providing lint functionality for multiple OpenAPI formats, Redocly CLI also has support for AsyncAPI."," ","Redocly CLI supports the following linting approaches with AsyncAPI documents:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["AsyncAPI document validation, including full binding validation for ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"#supported-protocols"},"children":["supported protocols"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Supported versions:",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"Link","attributes":{"href":"https://www.asyncapi.com/docs/reference/specification/v3.0.0"},"children":["AsyncAPI 3.0"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"Link","attributes":{"href":"https://v2.asyncapi.com/docs/reference/specification/v2.6.0"},"children":["AsyncAPI 2.6"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["earlier versions in the 2.x family may also validate successfully"]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Built-in rules for checking common standards requirements (see the ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"#asyncapi-rules"},"children":["list of AsyncAPI rules"]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"Link","attributes":{"href":"/docs/cli/v1/rules/configurable-rules"},"children":["Configurable rules"]}," so that you can build your own rules following common patterns"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"Link","attributes":{"href":"/docs/cli/v1/custom-plugins"},"children":["Custom plugins"]}," for advanced users that need additional functionality"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"lint-an-existing-asyncapi-file","__idx":1},"children":["Lint an existing AsyncAPI file"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Redocly CLI takes its settings from a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redocly.yaml"]}," configuration file. Below"," ","is an example of a simple configuration file for validating an AsyncAPI file is"," ","in the expected format:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"rules:\n  spec: error\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The empty ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["extends"]}," element instructs Redocly CLI not to use any existing"," ","rulesets, but to emit an error if the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["spec"]}," rule finds any problem. This rule"," ","checks that the document structure matches what is expected by the AsyncAPI"," ","specification."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["With this configuration file, and your AsyncAPI description file (or use one of the ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"https://github.com/asyncapi/spec/tree/master/examples"},"children":["existing examples"]},"), run the linting command:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"sh","header":{"controls":{"copy":{}}},"source":"redocly lint asyncapi.yaml\n","lang":"sh"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The output describes any structural problems with the document, or reports that it is valid."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"asyncapi-rules","__idx":2},"children":["AsyncAPI rules"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To expand the linting checks for an AsyncAPI description, start by enabling"," ","some of the built-in rules. The currently-supported rules are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["info-contact"]},": the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Info"]}," section must contain a valid ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Contact"]}," field."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["operation-operationId"]},": every operation must have a valid ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["operationId"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["channels-kebab-case"]},": channel address should be ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["kebab-case"]}," (lowercase with hyphens)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["no-channel-trailing-slash"]},": channel names must not have trailing slashes in their address."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tag-description"]},": all tags require a description."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["tags-alphabetical"]},": tags should be listed in the AsyncAPI file in alphabetical order."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["We expect the list to expand over time, so keep checking back - and let us know"," ","if you have any requests by ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"https://github.com/Redocly/redocly-cli/issues"},"children":["opening an issue on the GitHub"," ","repo"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To use a rule in your own linting setup, add the rule name to the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["rules"]}," ","configuration section, and declare the severity level (either ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["error"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["warn"]}," ","or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["off"]},"). Here's an example of a rules block where a missing contact section"," ","causes a warning, and a tag without a description triggers an error:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"rules:\n  info-contact: warn\n  tag-description: error\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Pick and mix the available rules until you have the setup that fits your situation."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"configurable-rule-example","__idx":3},"children":["Configurable rule example"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Redocly CLI also offers ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"/docs/cli/v1/rules/configurable-rules"},"children":["configurable rules"]}," ","that allow you to set assertions about the API description being linted, and"," ","this functionality works just as well for AsyncAPI as for OpenAPI. The"," ","following example shows a configurable rule that emits a warning if the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["title"]}," ","field is not present in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["info"]}," block:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"rules:\n  rule/info-title:\n    subject:\n      type: Info\n      property: title\n    assertions:\n      defined: true\n    severity: warn\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["With the extensive configurable rules options available, there are many"," ","opportunities to make sure that your AsyncAPI spec conforms with expectations"," ","(we'd also love to see what you're building, it helps us know how things are"," ","going!)."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Custom plugins"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For those users with advanced requirements and JavaScript skills, the ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"/docs/cli/v1/custom-plugins"},"children":["custom"," ","plugins"]}," feature offers some extension points if you need"," ","them."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"supported-protocols","__idx":4},"children":["Supported protocols"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["AsyncAPI supports an ever-expanding list of protocols, here's the list of what's currently supported:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["http"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ws"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["kafka"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["anypointmq"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["amqp"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["amqp1"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mqtt"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mqtt5"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["nats"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["jms"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sns"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["solace"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sqs"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["stomp"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redis"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["mercure"]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If you're using other protocols, you can still use Redocly CLI to lint an"," ","AsyncAPI description, but the details of those protocol bindings aren't"," ","validated and no problems are reported in those areas. The bindings listed"," ","above should all work as expected, however please ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"https://github.com/Redocly/redocly-cli/issues"},"children":["open an"," ","issue"]}," if you see something that"," ","doesn't look right. It's an extensive standard and we don't use all these"," ","technologies ourselves, so your input is genuinely welcome."]}]},"frontmatter":{"seo":{"title":"Lint AsyncAPI with Redocly CLI","description":"Unlock powerful linting capabilities for AsyncAPI documents. Use the Redocly CLI to enforce basic validation, configure rules, or even build custom plugins for AsyncAPI."}},"tagList":["admonition"],"title":"Lint AsyncAPI with Redocly CLI","lastModified":"2025-05-28T16:01:32.000Z"}