{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "github.com/bcdxn/opencli/blob/1.0.0-alpha.9/spec.schema.json",
  "title": "OpenCLI Specification",
  "description": "Describe a command line interface application",
  "type": "object",
  "properties": {
    "opencliVersion": {
      "type": "string",
      "description": "This property MUST be the exact version number of the OpenCLI Specification that this OpenCLI Document uses. The opencli field SHOULD be used by tooling to interpret the OpenCLI Document. This field is not related to the CLI `info.version` string.",
      "enum": ["1.0.0-alpha.9"]
    },
    "info": {
      "$ref": "#/$defs/InfoObject"
    },
    "install": {
      "type": "array",
      "description": "The installation methods available for the CLI.",
      "items": {
        "$ref": "#/$defs/InstallMethodItemObject"
      }
    },
    "global": {
      "$ref": "#/$defs/GlobalObject"
    },
    "commands": {
      "type": "object",
      "description": "The commands available for the CLI. Each key should contain the full command starting with the CLI binary name (e.g.: `$.info.binary`)",
      "patternProperties": {
        "^.*$": {
          "$ref": "#/$defs/CommandItemObject"
        }
      }
    }
  },
  "patternProperties": {
    "^x-": {}
  },
  "required": ["opencliVersion", "info"],
  "additionalProperties": false,
  "$defs": {
    "InfoObject": {
      "type": "object",
      "description": "Provides metadata about the CLI. This metadata is used for generating help output and documentation.",
      "properties": {
        "title": {
          "type": "string",
          "description": "The title of the CLI. This will appear in generated help output and documentation."
        },
        "summary": {
          "type": "string",
          "description": "A short summary of the CLI. This will appear in generated help output and documentation in addition to the description. [Markdown](https://spec.commonmark.org) may be used for rich text representation."
        },
        "description": {
          "type": "string",
          "description": "A longer description of the CLI. This will appear in generated help output and documentation in addition to the summary. [Markdown](https://spec.commonmark.org) may be used for rich text representation."
        },
        "license": {
          "$ref": "#/$defs/LicenseObject"
        },
        "contact": {
          "$ref": "#/$defs/ContactObject"
        },
        "binary": {
          "type": "string",
          "description": "The name of the CLI binary. This is the name that will be used to invoke the CLI from the command line."
        },
        "version": {
          "type": "string",
          "description": "The version of the OpenCLI Document which typically corresponds to the release version of your CLI."
        }
      },
      "required": ["title", "binary", "version"],
      "additionalProperties": false
    },
    "LicenseObject": {
      "type": "object",
      "description": "Describes the license used by the CLI.",
      "properties": {
        "name": {
          "type": "string",
          "description": "The name of the license used by the CLI."
        },
        "spdxId": {
          "type": "string",
          "description": "The [SPDX identifier](https://spdx.org/licenses/) of the license used by the CLI."
        },
        "url": {
          "type": "string",
          "format": "uri",
          "description": "A URL to the license used by the CLI."
        }
      },
      "required": ["name"],
      "additionalProperties": false
    },
    "ContactObject": {
      "type": "object",
      "description": "Contact information for the CLI.",
      "properties": {
        "name": {
          "type": "string",
          "description": "The name of the contact person/organization."
        },
        "email": {
          "type": "string",
          "format": "email",
          "description": "The email address of the contact person/organization."
        },
        "url": {
          "type": "string",
          "format": "uri",
          "description": "A URL pointing to the contact information."
        }
      },
      "anyOf": [
        {
          "required": ["name"]
        },
        {
          "required": ["email"]
        },
        {
          "required": ["url"]
        }
      ],
      "additionalProperties": false
    },
    "InstallMethodItemObject": {
      "type": "object",
      "description": "An installation method for the CLI.",
      "properties": {
        "name": {
          "type": "string",
          "description": "The name of the installation method.",
          "examples": ["homebrew", "apt", "chocolatey", "binary", "source"]
        },
        "command": {
          "type": "string",
          "description": "The command to install the CLI."
        },
        "url": {
          "type": "string",
          "format": "uri",
          "description": "A URL pointing to the binary or source code."
        },
        "description": {
          "type": "string",
          "description": "The description for the installation method. [Markdown](https://spec.commonmark.org) may be used for rich text representation."
        }
      },
      "anyOf": [
        {
          "required": ["name", "command"]
        },
        {
          "required": ["name", "url"]
        }
      ],
      "additionalProperties": false
    },
    "GlobalObject": {
      "type": "object",
      "description": "properties that apply to all commands",
      "properties": {
        "exitCodes": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ExitCodeObject"
          }
        },
        "config": {
          "type": "object",
          "description": "An object where each property key is a supported file format and each property value is the path to a config file of that format; the defined paths are the expected locations of those config iles. Once defined, `alternativeSourced` referenced elsewhere in the OpenCLI Spec Document ca use the `$FILE` type.",
          "properties": {
            "json": {
              "type": "string"
            },
            "toml": {
              "type": "string"
            },
            "yaml": {
              "type": "string"
            }
          },
          "additionalProperties": false,
          "minProperties": 1
        },
        "flags": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/FlagItemObject"
          }
        }
      }
    },
    "CommandItemObject": {
      "type": "object",
      "description": "Describes a command for the CLI.",
      "properties": {
        "summary": {
          "type": "string",
          "description": "A short summary of the command. This will appear in generated help output and documentation in addition to the description. [Markdown](https://spec.commonmark.org) may be used for rich text representation."
        },
        "description": {
          "type": "string",
          "description": "A longer description of the command. This will appear in generated help output and documentation in addition to the summary. [Markdown](https://spec.commonmark.org) may be used for rich text representation."
        },
        "aliases": {
          "type": "array",
          "description": "Alternative names for a given command, e.g. `list` could be aliases with a shorter version like `ls`",
          "items": {
            "type": "string"
          }
        },
        "args": {
          "type": "array",
          "description": "The positional arguments available for the command. The order in which the arguments are defined is the order in which they should be provided to the command.",
          "items": {
            "$ref": "#/$defs/ArgumentItemObject"
          }
        },
        "flags": {
          "type": "array",
          "description": "The flags available for the command. Flags can be provided in any order.",
          "items": {
            "$ref": "#/$defs/FlagItemObject"
          }
        },
        "hidden": {
          "type": "boolean",
          "description": "Determines if the command is hidden from generated help output and documentation.",
          "default": false
        },
        "group": {
          "type": "boolean",
          "description": "If true, then the command it is a logical grouping of subcommands and is not an executable as a stand-alone command.",
          "default": false
        },
        "exitCodes": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/ExitCodeObject"
          }
        }
      },
      "additionalProperties": false
    },
    "ArgumentItemObject": {
      "type": "object",
      "description": "A positional argument for a command.",
      "properties": {
        "name": {
          "type": "string",
          "description": "The name of the argument."
        },
        "type": {
          "description": "The type of the argument. Codegen tools MAY use this field to coerce argument types before passing them to the command handler implementations.",
          "$ref": "#/$defs/Type"
        },
        "variadic": {
          "type": "boolean",
          "description": "Indicates if the the argument value is variadic. Multiple values for variadic argumuments can be supplied. A variadic argument must be the last argument declared and only one variadic argument may be declared.",
          "default": false
        },
        "minItems": {
          "type": "integer",
          "description": "The minimum number of items the variadic argument must receive. Only applicable when variadic is true.",
          "minimum": 0
        },
        "maxItems": {
          "type": "integer",
          "description": "The maximum number of items the variadic argument may receive. Only applicable when variadic is true.",
          "minimum": 0
        },
        "choices": {
          "type": "array",
          "description": "The enumerated choices available for the argument. Codegen tools MAY enforce this enumeration before passing them to the command handler implementations. This will appear in generated help output and documentation. [Markdown](https://spec.commonmark.org) may be used for rich text representation.",
          "items": {
            "type": "object",
            "properties": {
              "value": {
                "type": ["string", "number", "integer", "boolean"],
                "description": "The value of the choice."
              },
              "description": {
                "type": "string",
                "description": "A description of the choice. This will appear in generated documentation"
              }
            },
            "required": ["value"],
            "additionalProperties": false
          }
        },
        "summary": {
          "type": "string",
          "description": "A short summary of the argument. This will appear in generated help output and documentation in addition to the description. [Markdown](https://spec.commonmark.org) may be used for rich text representation."
        },
        "description": {
          "type": "string",
          "description": "A description of the argument. This will appear in generated help output and documentation in addition to the summary. [Markdown](https://spec.commonmark.org) may be used for rich text representation."
        },
        "required": {
          "type": "boolean",
          "description": "Determines if the argument is mandatory. If required arguments are not supplied, the command will exit in error.",
          "default": false
        }
      },
      "required": ["name"],
      "additionalProperties": false
    },
    "FlagItemObject": {
      "type": "object",
      "description": "A flag for a command.",
      "properties": {
        "name": {
          "type": "string",
          "description": "The name of the flag."
        },
        "aliases": {
          "type": "array",
          "description": "The single character short flag.",
          "items": {
            "type": "string"
          }
        },
        "type": {
          "description": "The type of the flag. Codegen tools WILL use this field to coerce flag types before passing them to the command handler implementations.",
          "$ref": "#/$defs/Type"
        },
        "variadic": {
          "type": "boolean",
          "description": "Indicates if the the flag value is variadic. Variadic flags can be supplied multiple times. e.g.: `--flag value --flag value_two --flag value_three`",
          "default": false
        },
        "minItems": {
          "type": "integer",
          "description": "The minimum number of items the variadic flag must receive. Only applicable when variadic is true.",
          "minimum": 0
        },
        "maxItems": {
          "type": "integer",
          "description": "The maximum number of items the variadic flag may receive. Only applicable when variadic is true.",
          "minimum": 0
        },
        "choices": {
          "type": "array",
          "description": "The enumerated choices available for the flag. If the flag is not one of the choices, the command will exit in error.",
          "items": {
            "type": "object",
            "properties": {
              "value": {
                "type": ["string", "number", "integer", "boolean"],
                "description": "The value of the choice."
              },
              "description": {
                "type": "string",
                "description": "A description of the choice. This will appear in generated documentation"
              }
            },
            "required": ["value"],
            "additionalProperties": false
          }
        },
        "hint": {
          "type": "string",
          "description": "A hint to the user about the value of the flag. This will appear in generated help output and documentation."
        },
        "summary": {
          "type": "string",
          "description": "A short summary of the flag. This will appear in generated help output and documentation in addition to the description. [Markdown](https://spec.commonmark.org) may be used for rich text representation."
        },
        "description": {
          "type": "string",
          "description": "A description of the flag. This will appear in generated help output and documentation in addition to the summary. [Markdown](https://spec.commonmark.org) may be used for rich text representation."
        },
        "required": {
          "type": "boolean",
          "description": "Determines if the flag is mandatory. If required flags are not supplied, the command will exit in error.",
          "default": false
        },
        "default": {
          "description": "default is the default value the flag will take if it is not provided in the command line. It can be a constant or it can be sourced from the environment or a file. If sourced, resolution will be attempted from each source in the order it is defined, stopping once a value is found or the sources have been exhausted.",
          "oneOf": [
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "integer"
            },
            {
              "type": "boolean"
            }
          ]
        },
        "alternativeSources": {
          "description": "The possible sources of the default value; order is important as it determines the order of resolution.",
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "type": {
                "description": "The name of the source; it can be `$ENV` indicating the property is sourced from an environment variable OR $FILE, indicating the property is sourced from a config file defined in the global.configFiles section of the document.",
                "type": "string",
                "enum": ["$ENV", "$FILE"]
              },
              "property": {
                "description": "The variable name within the environment or JSON path to the property in the config file.",
                "type": "string"
              }
            },
            "required": ["type", "property"],
            "additionalProperties": false
          },
          "minItems": 1
        },
        "hidden": {
          "type": "boolean",
          "description": "Determines if the flag is hidden from generated help output and documentation.",
          "default": false
        }
      },
      "required": ["name", "type"],
      "additionalProperties": false
    },
    "ExitCodeObject": {
      "type": "object",
      "properties": {
        "code": {
          "type": "integer",
          "description": "The literal code that is returned by the CLI"
        },
        "status": {
          "type": "string",
          "description": "The enumerated exit code categories.",
          "enum": [
            "BAD_USER_INPUT_ERROR",
            "UNAUTHENTICATED_ERROR",
            "UNAUTHORIZED_ERROR",
            "CANCELED_ERROR",
            "INTERNAL_CLI_ERROR",
            "NOT_IMPLEMENTED_ERROR",
            "OK"
          ]
        },
        "summary": {
          "type": "string"
        },
        "description": {
          "type": "string"
        }
      },
      "required": ["code", "status", "summary"],
      "additionalProperties": false
    },
    "Type": {
      "type": "string",
      "enum": ["string", "number", "integer", "boolean"],
      "default": "string"
    }
  }
}
