# lint

Source: https://apigenie.pl/docs/reference/cli/lint

Detects stylistic and structural issues in OpenAPI, Swagger 2.0 and AsyncAPI
documents, Protobuf (`.proto`) files and GraphQL schemas, improving their quality.

## Usage

```sh
apigenie lint [OPTIONS] FILES
```

## Description

The OpenAPI linter helps developers and teams create high-quality, consistent,
and well-structured schemas. It achieves this by validating schemas against a
set of configurable **lint rules**.

### Lint Rules

Each rule in the linter focuses on a specific aspect of an OpenAPI schema.
Here are some examples:

- `operation-description-defined`: Ensures that all operations have
  meaningful descriptions.
- `operation-success-response`: Ensures that all operations define a success
  response (e.g. `201 Created`).
- `paths-max-count` and `paths-max-depth`: Limit API complexity
  by checking the number of path items and depth (e.g. a number of segments)
  or URLs.

Each rule can have a **severity level** assigned, indicating its importance.
Possible values for severity are `error`, `warning` and `hint` (also written
`info`). All of them show up in the linter output, but only errors prevent the
linter check from succeeding; hints are suggestions, which don't count as
warnings either. A rule may report a hint where its advice can't be followed yet,
such as [schema-format-deprecated](/docs/linter/openapi/rules/schema-format-deprecated)
in OpenAPI 3.0 documents.

Some rules may accept options that adjust how they evaluate the schema.

The API Genie linter currently offers 53 built-in rules for OpenAPI, with
over 20 additional rules under active development.

### AsyncAPI documents

The linter also checks AsyncAPI 3.x documents; a file is treated as AsyncAPI
when its root object has an `asyncapi` field. AsyncAPI documents have their own
set of 31 built-in rules, ported from the OpenAPI ones where they make sense
(for example `contact-defined`, `license-defined`, `operation-tags-defined` or
`unused-shared-component`), plus AsyncAPI-specific ones such as
`channel-parameters-defined`, `channel-addresses-unique` and `server-hosts`.
They come in the same `recommended`, `strict` and `all` rulesets, and support
custom rules, JavaScript functions, `x-apigenie-lint-disable` and `--fix` just
like OpenAPI documents. OpenAPI and AsyncAPI files can be linted in a single
run; see [lint.asyncapi](#lintasyncapi) for their configuration.

### Swagger 2.0 documents

The linter also checks Swagger 2.0 documents; a file is treated as Swagger
when its root object has a `swagger` field. Swagger documents have their own
set of 46 built-in rules, ported from the OpenAPI ones where they make sense
(for example `operation-id-unique`, `parameters-unique`,
`path-parameters-defined` or `unused-shared-component`), plus Swagger-specific
ones: `host-defined`, `schemes-secure`, `media-types-defined` and
`swagger-validation`, which reports the violations of the Swagger 2.0
specification that span several objects (undefined security schemes,
unresolved references, several body parameters and so on). They come in the
same `recommended`, `strict` and `all` rulesets, and support custom rules
(whose `formats` is `oas2`), JavaScript functions, `x-apigenie-lint-disable`
and `--fix` just like OpenAPI documents. See [lint.swagger](#lintswagger) for
their configuration.

### GraphQL documents

The linter also checks GraphQL schemas and operations: files with the
`.graphql`, `.graphqls` or `.gql` extension. GraphQL documents have their own
set of 87 built-in rules: the type system and operation rules of the GraphQL
specification, naming conventions, descriptions, deprecations, schema design
(root types, mutation inputs and payloads, unreachable types, identifiers),
the Relay connection conventions, ordering and spelling. Operations are also
checked against a schema: unknown fields, types and arguments, required
arguments, deprecated fields and selection depth. They come in the
`recommended`, `strict`, `all` and `relay` rulesets. A
`# apigenie-lint-disable rule-a, rule-b` comment disables rules for a
definition and everything nested in it. `--fix` does not change GraphQL files.
See [lint.graphql](#lintgraphql) for their configuration.

### Rulesets

To simplify configuration and provide more flexibility, rules can be combined
into **rulesets**. A ruleset is a named group of rules with assigned severity
levels and options.

### Disabling certain rules

There might be situations where you want to temporarily disable a rule for a
specific part of  a schema. This might be due to a legacy issue, ongoing
development, or a specific API decision. To do this, annotate parts of your
OpenAPI schema with the `x-apigenie-lint-disable` extension. The value of this
extension must be a list of rule names you want to disable.

Rules can be disabled on any schema object, including `OpenAPI` object itself.
Disabling a rule on specific schema object applies to that object and its
descendants within the schema hierarchy.

For example, in the snippet below, the
[contact-defined](/docs/linter/openapi/rules/contact-defined) rule is disabled on
the `Info` schema object. However, it will also be enforced on the nested
`Contact` object because `Contact` is a descendant of `Info` within the schema
structure.

```yaml
info:
  x-apigenie-lint-disable:
    - contact-defined
```

A couple of final remarks:

- Disable rules as close to the problematic point in the schema as possible.
- Disabling linter rules should be an exception, not the rule.

### Custom rules

Besides the built-in rules, you can define your own rules in the `lint`
section of the configuration file. A custom rule is data, in the format used
by [Spectral](https://docs.stoplight.io/docs/spectral): it selects parts of the
document with a JSONPath expression and checks each of them with a
**function**.

```yaml
version: "1.0"
commands:
  lint:
    extends: [recommended]
    rules:
      operation-summary:
        description: Operations must have a summary
        message: "{{property}} is missing at {{path}}"
        severity: error
        given: "$.paths[*][get,put,post,delete,patch]"
        then:
          field: summary
          function: truthy
```

A rule definition accepts these properties:

| Property      | Description |
| ------------- | ----------- |
| `given`       | JSONPath expression, or a list of them, selecting the values to check. Required. |
| `then`        | What to check: an object or a list of objects with `function`, optional `functionOptions` and optional `field`. Required. |
| `field`       | Narrows each selected value: a member path (`summary`, `a.b[0]`), `@key` to check member names, or a JSONPath expression relative to the value (`$.properties[*]`). |
| `message`     | Message template; see below. Defaults to `description`, then to the function's message. |
| `description` | Human-readable description of the rule. |
| `severity`    | `error`, `warn` (default), `info`, `hint` or `off`. `info` and `hint` are reported as hints. |
| `resolved`    | Whether the rule sees the document with local `$ref`s followed. Defaults to `true`. |
| `formats`     | Restricts the rule to document formats: `oas2` (Swagger 2.0 documents), `oas3`, `oas3_0`, `oas3_1`, `oas3_2`, or, for AsyncAPI documents, `aas3` and `aas3_0`, `aas3_1`, ... |

Messages may use `{{error}}` (the function's message), `{{description}}`,
`{{path}}` (JSON pointer of the problem), `{{property}}` (the last path
segment) and `{{value}}`. Issues are reported where the offending value is
defined, even when it is reached through a `$ref`. Custom rules honour
`x-apigenie-lint-disable` like built-in ones. A custom rule can be switched off
or have its severity changed later in the configuration (`my-rule: off`), but
it cannot reuse the name of a built-in rule.

#### JSONPath

`given` and `field` expressions follow
[RFC 9535](https://www.rfc-editor.org/rfc/rfc9535) with the extensions Spectral
rulesets commonly use:

- member unions without quotes: `$.paths[*][get,put]`;
- `~` at the end selects member names: `$.paths[*]~`;
- filters written as JavaScript expressions:
  `$..[?(@.type === 'object' && !@.properties)]`, with `@property`, `@parent`,
  `@parentProperty`, `@path` and `$`, and the string and array methods
  `match`, `test`, `startsWith`, `endsWith`, `includes`, `indexOf`,
  `toLowerCase`, `toUpperCase`, `trim` and `length`.

Script expressions such as `[(@.length-1)]` and Spectral aliases (`#Name`)
are not supported.

#### Core functions

| Function | Options | Checks that the value... |
| -------- | ------- | ------------------------ |
| `truthy`, `falsy` | none | is (not) truthy in the JavaScript sense |
| `defined`, `undefined` | none | exists / does not exist |
| `enumeration` | `values` | is one of the listed values |
| `length` | `min`, `max` | has a length (string, array, object keys, number) within bounds |
| `pattern` | `match`, `notMatch` | (does not) match a JavaScript regular expression; `/re/flags` is accepted |
| `casing` | `type` (`flat`, `camel`, `pascal`, `kebab`, `cobol`, `snake`, `macro`), `disallowDigits`, `separator.char`, `separator.allowLeading` | follows a naming convention |
| `alphabetical` | `keyedBy` | lists keys or items in alphabetical order |
| `or`, `xor` | `properties` | has at least one / exactly one of the listed members |
| `schema` | `schema`, `dialect`, `allErrors` | is valid against a JSON Schema (draft 4 to 2020-12) |
| `typedEnum` | none | has `enum` values matching its `type` |
| `unreferencedReusableObject` | `reusableObjectsLocation` | has only members referenced somewhere in the document |

#### JavaScript functions

When the core functions are not enough, write a function in JavaScript. List
it under `functions`; API Genie loads `<name>.js` from the `functions`
directory next to the configuration file (change it with `functionsDir`).

```yaml
commands:
  lint:
    functions: [operationIdPrefix]
    rules:
      operation-id-prefix:
        given: "$.paths[*][*].operationId"
        then:
          function: operationIdPrefix
          functionOptions: { prefix: api }
```

A function is an ES module whose default export receives the value, the
options and a context, and returns a list of problems. The contract is the
one of Spectral custom functions, so most of them work unchanged:

```js
// functions/operationIdPrefix.js
import { createRulesetFunction } from '@stoplight/spectral-core';
import { casing } from '@stoplight/spectral-functions';

export default createRulesetFunction(
  {
    input: { type: 'string' },
    options: {
      type: 'object',
      properties: { prefix: { type: 'string' } },
      required: ['prefix'],
    },
  },
  (input, options, context) => {
    if (!input.startsWith(options.prefix)) {
      return [{ message: `must start with "${options.prefix}"` }];
    }
    return casing(input, { type: 'camel' }, context);
  },
);
```

- `createRulesetFunction` validates `functionOptions` when the configuration
  is loaded and skips values that do not match `input`.
- A result may carry a `path` (an array of keys and indexes) to point at a
  more specific location than `context.path`.
- `context` provides `path`, `rule` (`name`, `severity`, `resolved`),
  `document` (`formats`, `data`) and `documentInventory` (`resolved`,
  `unresolved`).
- Functions may be `async`.
- A function that throws is reported as an issue of its rule.

Functions run in a sandbox: they can import other modules from the functions
directory and the two built-in `@stoplight` modules, but have no access to the
file system, network, processes or timers. Each call must finish within 5
seconds. Custom JavaScript functions are not available in the WebAssembly
build.

### Autofixing

Some issues found by the `apigenie lint` command can be automatically fixed.
To do this, run the command with the `--fix` option. The fixed files keep their
comments, unless `--strip-comments` is given.

### Formatting results

Apart from rules, API Genie linter allows to customize the way it displays
results. It ships with several built-in **formatters**, described below,
in subsections.

Formatters differ in the way they present data, but all of them sort issues by:

1. The line in the input OpenAPI schema file where they were found
2. Severity level: warnings are displayed before errors.

**Note**: If you used [ESLint](https://eslint.org) you may notice that the list
of formatters API Genie provides is close to that of ESLint. This is by no
coincidence, as both tools aim to be usable in many different environments.

#### checkstyle

Outputs results in the [Checkstyle](https://checkstyle.sourceforge.io) format.

```xml
<?xml version="1.0" encoding="utf-8"?>
<checkstyle version="4.3">
    <file name="/apigenie/data/openapi.yaml">
        <error line="2" column="2" severity="error" message="Info summary is missing or empty" source="info-defined"/>
        <error line="12" column="4" severity="warning" message="Tag &apos;Articles&apos; has no meaningful description defined" source="tag-description-defined"/>
        <error line="13" column="4" severity="warning" message="Tag &apos;Comments&apos; has no meaningful description defined" source="tag-description-defined"/>
        <error line="14" column="4" severity="warning" message="Tag &apos;Favorites&apos; has no meaningful description defined" source="tag-description-defined"/>
        <error line="15" column="4" severity="warning" message="Tag &apos;Profile&apos; has no meaningful description defined" source="tag-description-defined"/>
    </file>
</checkstyle>
```

#### compact

Mimicks the default output of JSHint.

```
/apigenie/data/openapi.yaml: line 2, col 2, Error - Info summary is missing or empty. (info-defined)
/apigenie/data/openapi.yaml: line 12, col 4, Warning - Tag 'Articles' has no meaningful description defined. (tag-description-defined)
/apigenie/data/openapi.yaml: line 13, col 4, Warning - Tag 'Comments' has no meaningful description defined. (tag-description-defined)
/apigenie/data/openapi.yaml: line 14, col 4, Warning - Tag 'Favorites' has no meaningful description defined. (tag-description-defined)
/apigenie/data/openapi.yaml: line 15, col 4, Warning - Tag 'Profile' has no meaningful description defined. (tag-description-defined)
```

#### html

Prints results as a single HTML file. Issues are displayed in a table, every
issue takes one table row.

```html
<!DOCTYPE html>
<html>
<body>
  <section id="overview">
    <h1>API Genie Report</h1>
    <ul>
      <li>Total: 224</li>
      <li>Errors: 32</li>
      <li>Warnings: 192</li>
    </ul>
  </section>
  <section id="issues">
    <table>
      <caption>/apigenie/data/openapi.yaml</caption>
      <tr>
        <td class="pos">2:2</td>
        <td class="error">Error</td>
        <td>Info summary is missing or empty</td>
        <td>
          <a href="https://apigenie.pl/docs/linter/openapi/rules/info-defined">info-defined</a>
        </td>
      </tr>
      <tr>
        <td class="pos">12:4</td>
        <td class="warning">Warning</td>
        <td>Tag 'Articles' has no meaningful description defined</td>
        <td>
          <a href="https://apigenie.pl/docs/linter/openapi/rules/tag-description-defined">tag-description-defined</a>
        </td>
      </tr>
    </table>
</body>
</html>
```

#### json

Outputs lint results in JSON file. This format is useful if you want to process
linter result programmatically. `results` has one item per file with issues;
`formatVersion` is the version of the format, which changes only when a member is
removed or changes meaning (see [Compatibility](/docs/reference/cli/compatibility)).
Its JSON Schema is
[apigenie-lint-report.json](https://apigenie.pl/schemas/apigenie-lint-report.json).

```json5
{
  "formatVersion": 1,
  "results": [
    {
      "filePath": "/apigenie/data/openapi.yaml",
      "messages": [
        {
          "column": 2,
          "line": 2,
          "message": "Info summary is missing or empty",
          "ruleId": "info-defined",
          "severity": "error"
        },
        {
          "column": 4,
          "line": 12,
          "message": "Tag 'Articles' has no meaningful description defined",
          "ruleId": "tag-description-defined",
          "severity": "warning"
        },
        ... more issues ...
      ]
    }
  ]
}
```

API Genie 0.9 and earlier wrote the bare `results` array.

#### junit

Outputs results to format compatible with the
[JUnit Jenkins plugin](https://plugins.jenkins.io/junit/).

```xml
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
  <testsuite package="apigenie" time="0" tests="224" errors="224" name="/apigenie/data/openapi.yaml">
    <testcase time="0" name="apigenie.info-defined" classname="apigenie.info-defined">
      <failure message="Info summary is missing or empty"><![CDATA[line 2, col 2, Error - Info summary is missing or empty. (info-defined)]]></failure>
    </testcase>
    <testcase time="0" name="apigenie.tag-description-defined" classname="apigenie.tag-description-defined">
      <failure message="Tag &apos;Articles&apos; has no meaningful description defined"><![CDATA[line 12, col 4, Warning - Tag 'Articles' has no meaningful description defined. (tag-description-defined)]]></failure>
    </testcase>
    <testcase time="0" name="apigenie.tag-description-defined" classname="apigenie.tag-description-defined">
      <failure message="Tag &apos;Comments&apos; has no meaningful description defined"><![CDATA[line 13, col 4, Warning - Tag 'Comments' has no meaningful description defined. (tag-description-defined)]]></failure>
    </testcase>
  </testsuite>
</testsuites>
```

#### sarif

Outputs results in [SARIF 2.1.0](https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html),
the format of GitHub code scanning and other static analysis dashboards. Files below
the current directory are given relative to it (`%SRCROOT%`), so that code scanning
finds them in the repository. A result whose JSON pointer is known has it as a
logical location and in a fingerprint, which lets code scanning keep tracking the
issue when lines move.

```json5
{
  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
  "version": "2.1.0",
  "runs": [
    {
      "tool": {
        "driver": {
          "name": "apigenie",
          "informationUri": "https://apigenie.pl",
          "rules": [
            {
              "id": "info-defined",
              "helpUri": "https://apigenie.pl/docs/linter/openapi/rules/info-defined"
            },
            ... more rules ...
          ]
        }
      },
      "originalUriBaseIds": {
        "%SRCROOT%": { "uri": "file:///apigenie/" }
      },
      "results": [
        {
          "ruleId": "info-defined",
          "ruleIndex": 0,
          "level": "error",
          "message": { "text": "Info summary is missing or empty" },
          "locations": [
            {
              "physicalLocation": {
                "artifactLocation": { "uri": "data/openapi.yaml", "uriBaseId": "%SRCROOT%" },
                "region": { "startLine": 2, "startColumn": 2 }
              },
              "logicalLocations": [
                { "fullyQualifiedName": "#/info", "kind": "member" }
              ]
            }
          ],
          "partialFingerprints": {
            "apigenieLocation/v1": "info-defined|data/openapi.yaml|#/info"
          }
        },
        ... more issues ...
      ]
    }
  ]
}
```

#### stylish

This is the default formatter. It presents result as table, with values being
highligted in different colors.

```sh
  764:6   warning  Unused shared component                                              unused-shared-component
  769:12  warning  Object schema does not define constraints restricting its size       schema-constraints
  769:12  error    Object schema does not disable additional properties                 schema-no-additional-properties
  777:6   warning  Unused shared component                                              unused-shared-component
  781:8   error    Schema with integer type does not define proper format               schema-format-defined
  781:8   warning  Integer schema does not define constraints restricting its range     schema-constraints
  785:6   warning  Unused shared component                                              unused-shared-component
  789:8   error    Schema with integer type does not define proper format               schema-format-defined
  789:8   warning  Integer schema does not define constraints restricting its range     schema-constraints
  795:6   warning  Unused shared component                                              unused-shared-component

  224 issues (32 errors, 192 warnings)
  0 errors, 6 warnings are potentially auto-fixable
```

#### tap

Outputs results to the [Test Anything Protocol (TAP)](https://testanything.org)
specification format.

```yaml
TAP version 14
1..1
not ok - /apigenie/data/openapi.yaml
  ---
  errorCount: 32
  issues:
    - column: 2
      line: 2
      message: Info summary is missing or empty
      ruleId: info-defined
      severity: error
    - column: 4
      line: 12
      message: Tag 'Articles' has no meaningful description defined
      ruleId: tag-description-defined
      severity: warning
    - column: 4
      line: 13
      message: Tag 'Comments' has no meaningful description defined
      ruleId: tag-description-defined
      severity: warning
```

#### unix

Outputs results to a format similar to many commands in UNIX-like systems.
If you use `grep` or `awk`, this format may be best for you.

```
/apigenie/data/openapi.yaml:2:2: Info summary is missing or empty. [Error/info-defined]
/apigenie/data/openapi.yaml:12:4: Tag 'Articles' has no meaningful description defined. [Warning/tag-description-defined]
/apigenie/data/openapi.yaml:13:4: Tag 'Comments' has no meaningful description defined. [Warning/tag-description-defined]
/apigenie/data/openapi.yaml:14:4: Tag 'Favorites' has no meaningful description defined. [Warning/tag-description-defined]
/apigenie/data/openapi.yaml:15:4: Tag 'Profile' has no meaningful description defined. [Warning/tag-description-defined]
/apigenie/data/openapi.yaml:16:4: Tag 'Tags' has no meaningful description defined. [Warning/tag-description-defined]
```

#### visualstudio

Outputs results to format compatible with the integrated terminal of the
Visual Studio IDE.

```
/apigenie/data/openapi.yaml(2,2): error info-defined : Info summary is missing or empty.
/apigenie/data/openapi.yaml(12,4): warning tag-description-defined : Tag 'Articles' has no meaningful description defined.
/apigenie/data/openapi.yaml(13,4): warning tag-description-defined : Tag 'Comments' has no meaningful description defined.
/apigenie/data/openapi.yaml(14,4): warning tag-description-defined : Tag 'Favorites' has no meaningful description defined.
/apigenie/data/openapi.yaml(15,4): warning tag-description-defined : Tag 'Profile' has no meaningful description defined.
/apigenie/data/openapi.yaml(16,4): warning tag-description-defined : Tag 'Tags' has no meaningful description defined.
```

## Options

### --config FILE

Optional path to the configuration file. If not specified, the default
configuration is used. For details, see the [configuration](#configuration)
section.

### --fix

If possible, automatically fixes problems it finds. Modified file is written
under the same name as the original. The exit status reflects the issues that
remain after the fixes. The YAML comments of the fixed OpenAPI, Swagger and
AsyncAPI documents are kept with the values they belong to; those of values a
fix removes go with them. Protobuf files are fixed by editing their text, which
keeps everything outside the edited declarations.

### --strip-comments

With `--fix`, drops the YAML comments of the OpenAPI, Swagger and AsyncAPI
documents it rewrites, instead of keeping them. Files without fixes are not
rewritten.

### --formatter NAME

Sets the formatter to display the linter result. Supported formatter names are:

- `checkstyle`
- `compact`
- `html`
- `json`
- `junit`
- `sarif`
- `stylish` - the default formatter
- `tap`
- `unix`
- `visualstudio`

### --graphql-schema FILE

A GraphQL schema file that the operations and fragments of the linted GraphQL
files are checked against. Can be repeated for a schema split across files.
When given, it replaces the files of the [schema](#lintgraphql) option of the
configuration; relative paths resolve against the current directory. With
`--watch`, the schema files are watched too.

```sh
apigenie lint --graphql-schema schema.graphql queries/*.graphql
```

## Exit status

The command exits with 0 when no issue of severity `error` is reported, even if
warnings or hints are, and with 1 when at least one is. With `--fix`, only the issues
that remain after the fixes count. It exits with 2 when the configuration or an
input file can't be read or parsed, or an input is not a document of its
specification. With `--watch` the command keeps running and never exits on
issues. See the [exit statuses](/docs/reference/cli/overview#exit-status) shared by the three binaries.

## Configuration

The linter stores its configuration under the `#/commands/linter` key in the
configuration file. See the [global configuration](/docs/reference/cli/configuration)
section to understand how this file is structured.

The linter configuration allows to apply rulesets, enable or disable certain
rules, modify rule severity levels, or modify rules' options.

**Example**: a minimal confiration illustrating all possible variants
of configuring rules.

```yaml
version: '1.0'
commands:
  lint:
    extends:
      - recommended
      # ... more rulesets to extend from ...
    rules:
      info-defined: off
      paths-max-count:
        - error
        - 30
      schema-datetime-suffix:
        - error
        - At
      tags-unique: error
      # ... more rules ...
```

If the configuration file is not specified, linter uses the default
configuration:

```yaml
version: '1.0'
commands:
  lint:
    extends:
      - recommended
```

### lint.extends

This block lists rulesets whose configuration will be used and combined
to create the final set of rules, rule severity levels and options.

The value of this block, if present, must be an array of
[supported ruleset names](/docs/linter/openapi). Linter will read all
rulesets' configurations, in the order they are listed. If two rulesets
contain the same rule, linter uses the configuration from the ruleset that
was specified later in the list.

### lint.rules

These are overrides to the rules' configurations from rulesets.

If present, value of this block must be a map. Keys of the map must be valid
rule names, and values can be either strings or two-element arrays.

For valid rule names see the [rule index](/docs/linter/openapi) page.

### lint.rules.RULE_ID

Such blocks configure a rule named `RULE_ID`. Each block may be a string or a
two-element array.

- **String**: If it a string, and must be one of:
  - `off` - to disable rule
  - `warning` - to set rule severity to warning
  - `error` - to set rule severity to error
- **Array**: If it is an array, it must contain two elements:
  - The first element must be a valid rule severity (either `warning` or
    `error`).
  - The second element is rule-specific value, containing rule's options.

See the documentation of each rule to find what options it accepts.

**Examples**

- Disables the `info-defined` rule:

```yaml
version: '1.0'
commands:
  lint:
    rules:
      info-defined: off
```

- configure the
  [`paths-max-count`](/docs/linter/openapi/rules/paths-max-count) rule to issue
  an error when the number of path items is larger than 30. If the number is
  below or equal to 30, the rule does not produce an error or warning.

```yaml
version: '1.0'
commands:
  lint:
    rules:
      paths-max-count:
        - error
        - 30
```

### lint.asyncapi

The configuration of the linter for AsyncAPI documents. It accepts the same
keys as the `lint` block itself (`extends`, `rules`, `functions` and
`functionsDir`), with rule names of the AsyncAPI rules. The OpenAPI settings
of the `lint` block do not apply to AsyncAPI documents; without this block,
AsyncAPI documents are linted with the `recommended` ruleset.

```yaml
version: '1.0'
commands:
  lint:
    extends: [recommended]
    asyncapi:
      extends: [strict]
      rules:
        parameter-naming: [warning, camel]
        server-hosts: off
```

### lint.swagger

The configuration of the linter for Swagger 2.0 documents. It accepts the same
keys as the `lint` block itself (`extends`, `rules`, `functions` and
`functionsDir`), with rule names of the Swagger rules. The OpenAPI settings of
the `lint` block do not apply to Swagger documents; without this block,
Swagger documents are linted with the `recommended` ruleset.

```yaml
version: '1.0'
commands:
  lint:
    extends: [recommended]
    swagger:
      extends: [strict]
      rules:
        schemes-secure: [error, { upgradeInsecure: true }]
        swagger-validation: [error, { checks: [unresolved-reference, security-scheme-defined] }]
        paths-sorted: off
```

### lint.graphql

The configuration of the linter for GraphQL documents. It accepts `extends`,
`rules`, `self_contained` (whether each document holds every type and fragment
it references, so that references to missing ones are reported) and `schema`
(a path, or a list of paths, of the schema files operations are checked
against; relative paths resolve against the directory of the configuration
file; [--graphql-schema](#graphql-schema-file) replaces them). Without `schema`, operations are checked against the type system of
their own document. Without this block, GraphQL documents are linted with the
`recommended` ruleset.

```yaml
version: '1.0'
commands:
  lint:
    graphql:
      extends: [recommended, relay]
      schema: schema.graphql
      rules:
        field-description-defined: warning
        selection-set-depth: [error, { maxDepth: 5 }]
        no-deprecated: off
```

## See Also

- [Rule index](/docs/linter/openapi) lists all available rules.
- [Ruleset index](/docs/linter/openapi) lists all available rulesets.
