{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://wimhaanstra.github.io/noodge/schema/v1/noodge.schema.json",
  "$defs": {
    "Command": {
      "properties": {
        "description": {
          "type": "string",
          "description": "Description explains what the command does. This is the long-form text\nshown in the TUI's right-hand pane, so it can run to several paragraphs."
        },
        "params": {
          "items": {
            "$ref": "#/$defs/Param"
          },
          "type": "array",
          "description": "Params are the parameters this command accepts. They are validated and\ntype-coerced before any step runs, then substituted into the steps."
        },
        "steps": {
          "items": {
            "$ref": "#/$defs/Step"
          },
          "type": "array",
          "description": "Steps are run in order, each as its own process. The command stops at\nthe first step that exits non-zero and reports that exit code. A step\nmay itself be a parallel group, for running several services together."
        },
        "output": {
          "type": "string",
          "description": "Output describes what the command produces: what it writes to stdout,\nwhat files it leaves behind, what a reader should expect to see. It is\ndocumentation only and noodge never verifies it."
        },
        "env": {
          "additionalProperties": {
            "type": "string"
          },
          "type": "object",
          "description": "Env is set for this command's steps, merged over the file-level env."
        },
        "cwd": {
          "type": "string",
          "description": "Cwd is the working directory for this command's steps, relative to the\ndirectory holding the noodge.yaml. Defaults to that directory."
        },
        "aliases": {
          "items": {
            "type": "string"
          },
          "type": "array",
          "description": "Aliases are alternative names this command can be invoked by."
        },
        "hidden": {
          "type": "boolean",
          "description": "Hidden keeps the command out of the TUI list and out of tab completion.\nIt remains runnable by name. Use it for internal or CI-only commands."
        },
        "confirm": {
          "$ref": "#/$defs/Confirm",
          "description": "Confirm asks the user to confirm before this command runs. Write true for\na default prompt, or a string to use as the prompt itself. Omit it, or\nwrite false, to run without asking. Use it for destructive or\nirreversible commands. Confirmation is skipped by --yes and by --dry-run,\nand without a terminal to ask at the command refuses unless --yes is given."
        },
        "shell": {
          "type": "string",
          "description": "Shell overrides the interpreter for this command's string steps."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "steps"
      ],
      "description": "Command is one runnable, documented entry in a noodge.yaml."
    },
    "Commands": {
      "additionalProperties": {
        "$ref": "#/$defs/Command"
      },
      "type": "object",
      "description": "The runnable commands, keyed by the name you type after `noodge`."
    },
    "Confirm": {
      "oneOf": [
        {
          "type": "boolean"
        },
        {
          "type": "string"
        }
      ],
      "title": "Confirm",
      "description": "Ask before the command runs. true asks with a default prompt; a string asks with that prompt. Omitted or false runs without asking. Meant for destructive or irreversible commands."
    },
    "Group": {
      "properties": {
        "prefix": {
          "type": "string",
          "description": "Prefix is the family this describes: the part of a command name before\nits first colon. For \"dev:api\" and \"dev:worker\" the prefix is \"dev\"."
        },
        "title": {
          "type": "string",
          "description": "Title is the heading shown above the family in the browser. Defaults to\nthe prefix itself when omitted."
        },
        "description": {
          "type": "string",
          "description": "Description is the line or two shown when the family's heading is\nhighlighted. Use it for what the banner comments in a long file would\nhave said."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "prefix"
      ],
      "description": "Group documents a family of commands in the browser: every command whose name begins with Prefix followed by a colon, plus a command named exactly Prefix."
    },
    "Param": {
      "properties": {
        "name": {
          "type": "string",
          "description": "Name is the template variable this parameter fills. A step referring to\n{{host}} or {{flag host}} is referring to the parameter named \"host\"."
        },
        "flag": {
          "type": "string",
          "description": "Flag is how the parameter is typed on the noodge command line, written\nin full including the leading dashes, for example \"--host\". It must use\ntwo dashes; single-dash long flags cannot be expressed.\n\nThis is independent of how the flag reaches the wrapped tool. A step is\nfree to write \"-host {{host}}\" or \"/p:Host={{host}}\" instead."
        },
        "short": {
          "type": "string",
          "description": "Short is an optional single-character shorthand, written with one dash,\nfor example \"-c\"."
        },
        "type": {
          "type": "string",
          "description": "Type is the value's type. Defaults to string."
        },
        "description": {
          "type": "string",
          "description": "Description explains what the parameter controls. Shown beside the\nfield in the TUI and in the command's help text."
        },
        "required": {
          "type": "boolean",
          "description": "Required refuses to run the command unless the parameter is given."
        },
        "default": {
          "description": "Default is used when the parameter is not supplied. A parameter with a\ndefault is never unset, so {{flag x}} always expands for it."
        },
        "values": {
          "items": {
            "type": "string"
          },
          "type": "array",
          "description": "Values is the list of allowed values for an enum parameter. It also\nsupplies the candidates for tab completion."
        },
        "pattern": {
          "type": "string",
          "description": "Pattern is an optional regular expression the value must match. It is\nchecked before the value is substituted into any step."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "name",
        "flag"
      ],
      "description": "Param is one parameter a command accepts."
    },
    "Step": {
      "oneOf": [
        {
          "type": "string"
        },
        {
          "items": {
            "type": "string"
          },
          "type": "array",
          "minItems": 1
        },
        {
          "properties": {
            "parallel": {
              "additionalProperties": {
                "$ref": "#/$defs/Step"
              },
              "type": "object",
              "minProperties": 1,
              "description": "Things to start at once, keyed by a name that labels their output. The group ends when one fails or all of them finish."
            },
            "prefix": {
              "type": "boolean",
              "description": "Label each output line with the entry it came from. On by default. Labelling requires capturing the output through a pipe, which makes most programs turn their colours off; set this to false to let them write straight to the terminal instead."
            }
          },
          "additionalProperties": false,
          "type": "object",
          "required": [
            "parallel"
          ]
        }
      ],
      "title": "Step",
      "description": "One entry in the sequence. A string is run through a shell; a list of arguments is executed directly with no shell; a parallel group starts its entries at once."
    }
  },
  "properties": {
    "version": {
      "type": "integer",
      "description": "Version is the config format version. Currently always 1."
    },
    "name": {
      "type": "string",
      "description": "Name is a human-readable name for the project, shown in the TUI header."
    },
    "shell": {
      "type": "string",
      "description": "Shell overrides the interpreter used to run string steps. Defaults to\n\"cmd /c\" on Windows and \"sh -c\" everywhere else. A per-command shell\ntakes precedence over this."
    },
    "env": {
      "additionalProperties": {
        "type": "string"
      },
      "type": "object",
      "description": "Env is applied to every command in this file. A command's own env is\nmerged over the top, so a command can override a single variable\nwithout restating the rest."
    },
    "groups": {
      "items": {
        "$ref": "#/$defs/Group"
      },
      "type": "array",
      "description": "Groups give the command families a heading and a short description in the\nbrowser. A command belongs to the family named by the part of its name\nbefore the first colon, so \"dev:api\" and \"dev:worker\" are both in the\n\"dev\" family. Declaring a family here is optional — families are shown\neither way, headed by the bare prefix; this only adds a readable title\nand a line of explanation."
    },
    "commands": {
      "$ref": "#/$defs/Commands",
      "description": "Commands are the runnable commands, kept in the order they appear in\nthe file so the TUI can list them the way they were written."
    }
  },
  "additionalProperties": false,
  "type": "object",
  "required": [
    "version",
    "commands"
  ],
  "title": "noodge.yaml",
  "description": "Configuration for noodge, a documented, discoverable task runner."
}
