{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://apps.otty.sh/schemas/otty-toml-v1.json",
  "title": "Otty application manifest v1",
  "description": "One app identity plus independently versioned dotfiles and commands sections. Unknown future sections are ignored by clients.",
  "type": "object",
  "required": [
    "id",
    "name"
  ],
  "properties": {
    "id": {
      "description": "Stable identifier. Must equal the file name without the .toml extension \u2014 or, for a versioned app, the name of its directory, in every file there.",
      "type": "string",
      "pattern": "^[a-z0-9_-][a-z0-9._-]*$",
      "maxLength": 64
    },
    "name": {
      "description": "Human-facing display name, as the project spells it.",
      "type": "string",
      "minLength": 1,
      "maxLength": 128
    },
    "homepage": {
      "description": "Official project page. Used by consumers to link out and by reviewers to check the paths.",
      "type": "string",
      "pattern": "^https?://[^\\s]+$"
    },
    "description": {
      "description": "One sentence saying what the tool is, in the project's own words. Not a description of its dotfiles.",
      "type": "string",
      "minLength": 12,
      "maxLength": 160
    },
    "icon": {
      "description": "HTTPS, SimpleIcons:<slug>, or theSVG:<slug> (including existing themed variants).",
      "type": "string",
      "maxLength": 256,
      "pattern": "^(theSVG:[a-z0-9]+(-[a-z0-9]+)*(/(default|mono|light|dark|wordmark))?|SimpleIcons:[a-z0-9]+|https://[^\\s]+\\.(svg|png|jpg|jpeg|webp)([?#][^\\s]*)?)$"
    },
    "platforms": {
      "description": "Platforms the tool runs on. Omit to mean all of them.",
      "type": "array",
      "minItems": 1,
      "uniqueItems": true,
      "items": {
        "enum": [
          "macos",
          "linux",
          "windows"
        ]
      }
    },
    "since": {
      "description": "First version in this numeric window; newest is otty.toml, older windows are otty@<since>.toml.",
      "type": "string",
      "pattern": "^\\d+(\\.\\d+)*$",
      "maxLength": 32
    },
    "version_from": {
      "description": "Platform metadata used to choose a catalog window; ignored in vendor manifests.",
      "type": "object",
      "additionalProperties": false,
      "minProperties": 1,
      "properties": {
        "macos": {
          "description": "Bundle identifiers. The version is the app's Info.plist CFBundleShortVersionString.",
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "pattern": "^[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)+$",
            "maxLength": 128
          }
        },
        "windows": {
          "description": "Executable file names, as installed (Typora.exe). The version is the executable's file version.",
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "pattern": "^[^\\\\/:*?\"<>|]+\\.[Ee][Xx][Ee]$",
            "maxLength": 128
          }
        },
        "linux": {
          "description": "Distribution package names, as dpkg, pacman or rpm know them, or snap names. The version is the installed package's.",
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "pattern": "^[a-z0-9][a-z0-9+._-]*$",
            "maxLength": 128
          }
        },
        "command": {
          "description": "A command to run, program first, then its arguments (\"typora\", \"--version\"). The version is the first x.y or x.y.z in its output. Only for a CLI with no package metadata to read.",
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        }
      }
    },
    "executables": {
      "description": "Actual command basenames; bundle IDs belong in installation.macos_bundle_ids.",
      "type": "array",
      "minItems": 0,
      "uniqueItems": true,
      "items": {
        "$ref": "#/$defs/binaryName"
      }
    },
    "aliases": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^[a-z0-9_-][a-z0-9._-]*$",
        "maxLength": 64
      },
      "uniqueItems": true
    },
    "format": {
      "enum": [
        1
      ]
    },
    "installation": {
      "type": "object",
      "properties": {
        "macos_bundle_ids": {
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)+$"
          },
          "uniqueItems": true
        }
      },
      "required": [],
      "additionalProperties": false
    },
    "dotfiles": {
      "$ref": "#/$defs/dotfiles"
    },
    "commands": {
      "$ref": "#/$defs/commands"
    }
  },
  "additionalProperties": {
    "type": "object"
  },
  "$defs": {
    "path": {
      "description": "A path under the user's home, written from one of three roots. `~/` is the home directory literally, for a file a tool hard-codes there. `%VAR%/` names an environment variable, for a location only a variable can name. `[name]/` is a named base directory, after Electron's app.getPath(name): one spelling standing for every platform's version of one location. The named roots come in pairs, because a CLI either follows its platform's convention or follows the XDG spec everywhere, and which one it does is a fact about that tool: [appData] is ~/Library/Application Support on macOS while [configHome] is ~/.config there; [dataHome] is ~/Library/Application Support while [xdgData] is ~/.local/share; [cacheHome] is ~/Library/Caches while [xdgCache] is ~/.cache. On Linux each pair is the same XDG directory. [preferences] is ~/Library/Preferences and macOS-only. Forward slashes only, no .. segments; the consumer resolves the root itself.",
      "type": "string",
      "minLength": 3,
      "maxLength": 256,
      "allOf": [
        {
          "pattern": "^(~|\\[(appData|configHome|dataHome|xdgData|cacheHome|xdgCache|preferences)\\]|%[A-Za-z_][A-Za-z0-9_]*%)/"
        },
        {
          "not": {
            "pattern": "\\\\"
          }
        },
        {
          "not": {
            "pattern": "(^|/)\\.\\.(/|$)"
          }
        },
        {
          "not": {
            "pattern": "//"
          }
        }
      ]
    },
    "concretePath": {
      "description": "A path with no glob characters, so a parser can open exactly one file. A leading [name] root is not a glob and is allowed; square brackets anywhere after it are.",
      "allOf": [
        {
          "$ref": "#/$defs/path"
        },
        {
          "pattern": "^(~|\\[(appData|configHome|dataHome|xdgData|cacheHome|xdgCache|preferences)\\]|%[A-Za-z_][A-Za-z0-9_]*%)/[^*?\\[\\]]*[^*?\\[\\]/]$"
        }
      ]
    },
    "binaryName": {
      "type": "string",
      "minLength": 1,
      "maxLength": 64,
      "pattern": "^[A-Za-z0-9._+-]+$"
    },
    "rule": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "file",
        "match"
      ],
      "properties": {
        "file": {
          "description": "The file the rule applies to, or every platform spelling of it when paths lists more than one. Each must be covered by paths \u2014 or, for an except_key_path rule and the secret_paths beside it, be a file in secret. A rule binds only to the paths it names, so a file listed in paths and left out here is a file the rule does not reach.",
          "oneOf": [
            {
              "$ref": "#/$defs/concretePath"
            },
            {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": {
                "$ref": "#/$defs/concretePath"
              }
            }
          ]
        },
        "match": {
          "$ref": "#/$defs/match"
        },
        "format": {
          "description": "Which parser reads these files. Required for a key_path rule whose file names do not end in .toml, .yml, .yaml or .json, or do not all agree \u2014 ~/.kube/config is YAML and ~/.config/op/config is JSON, and nothing in the name says so. Meaningless for a prefix rule.",
          "enum": [
            "toml",
            "yaml",
            "json"
          ]
        },
        "scope": {
          "description": "What a machine_lines rule means for the line it holds back, and how far the value travels. `platform` \u2014 the value is decided by the kind of machine, not the machine itself: a Homebrew prefix, a CA bundle path, an SDK location. Stored per machine class, keyed by OS *and* architecture, since /opt/homebrew and /usr/local are both macOS, and carried to another machine of the same class. `backup` \u2014 the value belongs to one device but is worth keeping: stored so the user can see it and restore that device, never applied to another. `local` (the default) \u2014 not worth keeping at all: an install UUID, a telemetry id, a value rewritten on every run. Meaningless on a secret_paths rule, where the value never travels as content either way.",
          "enum": [
            "platform",
            "backup",
            "local"
          ]
        }
      }
    },
    "match": {
      "description": "Exactly one of prefix (line oriented formats), key_path or except_key_path (TOML / YAML / JSON).",
      "type": "object",
      "additionalProperties": false,
      "oneOf": [
        {
          "required": [
            "prefix"
          ]
        },
        {
          "required": [
            "key_path"
          ]
        },
        {
          "required": [
            "except_key_path"
          ]
        }
      ],
      "properties": {
        "prefix": {
          "description": "Lines that start with one of these once leading whitespace is stripped.",
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          }
        },
        "key_path": {
          "description": "Dotted key paths. `*` matches any array element or any key at that level. A literal dot inside one key is written `\\.` \u2014 some tools use dotted names as single keys (Joplin's \"api.token\", Ionic's \"tokens.user\"), and without the escape no rule could name the credential in those files.",
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "pattern": "^(?:\\\\.|[^.\\\\])+(?:\\.(?:\\\\.|[^.\\\\])+)*$"
          }
        },
        "except_key_path": {
          "description": "key_path read the other way round, machine_lines only: everything in the file *except* these keys stays behind. For a file the tool mostly fills with its own caches and counters, where the settings worth carrying are a short list and what is not grows with every release. A listed key travels with everything below it; a key_path or secret_paths rule on the same file still holds back what it names inside one. A list only partly listed stays behind whole.",
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "pattern": "^(?:\\\\.|[^.\\\\])+(?:\\.(?:\\\\.|[^.\\\\])+)*$"
          }
        }
      }
    },
    "fieldId": {
      "type": "string",
      "pattern": "^[a-z0-9_]+$"
    },
    "choice": {
      "type": "object",
      "properties": {
        "value": {
          "type": [
            "string",
            "number",
            "boolean"
          ]
        },
        "label": {
          "type": "string"
        },
        "description": {
          "type": "string"
        }
      },
      "required": [
        "value"
      ],
      "additionalProperties": false
    },
    "validation": {
      "type": "object",
      "properties": {
        "min": {
          "type": "number"
        },
        "max": {
          "type": "number"
        },
        "min_length": {
          "type": "integer",
          "minimum": 0
        },
        "max_length": {
          "type": "integer",
          "minimum": 0
        },
        "forbid_chars": {
          "type": "string"
        }
      },
      "required": [],
      "additionalProperties": false
    },
    "pathField": {
      "type": "object",
      "properties": {
        "kind": {
          "enum": [
            "file",
            "directory",
            "any"
          ]
        },
        "role": {
          "enum": [
            "input",
            "output",
            "unknown"
          ]
        },
        "must_exist": {
          "type": "boolean"
        },
        "standard_stream": {
          "type": "boolean",
          "description": "With commands.features standard_streams, exact - denotes native stdin/stdout; ./- stays a file."
        },
        "trailing_slash": {
          "enum": [
            "preserve",
            "meaningful"
          ]
        },
        "transforms": {
          "type": "array",
          "items": {
            "enum": [
              "dot_slash_if_dash",
              "dot_slash_if_colon"
            ]
          }
        }
      },
      "required": [],
      "allOf": [
        {
          "if": {
            "required": [
              "standard_stream"
            ]
          },
          "then": {
            "required": [
              "kind",
              "role"
            ],
            "properties": {
              "kind": {
                "const": "file"
              },
              "role": {
                "enum": [
                  "input",
                  "output"
                ]
              }
            }
          }
        }
      ],
      "additionalProperties": false
    },
    "condition": {
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "field": {
              "$ref": "#/$defs/fieldId"
            },
            "op": {
              "const": "variant_is"
            },
            "value": {
              "type": "string"
            }
          },
          "required": [
            "field",
            "op",
            "value"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "field": {
              "$ref": "#/$defs/fieldId"
            },
            "op": {
              "enum": [
                "is_set"
              ]
            }
          },
          "required": [
            "field",
            "op"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "field": {
              "$ref": "#/$defs/fieldId"
            },
            "op": {
              "enum": [
                "equals"
              ]
            },
            "value": {
              "type": [
                "string",
                "number",
                "boolean"
              ]
            }
          },
          "required": [
            "field",
            "op",
            "value"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "field": {
              "$ref": "#/$defs/fieldId"
            },
            "op": {
              "enum": [
                "in",
                "extension_in"
              ]
            },
            "values": {
              "type": "array",
              "items": {
                "type": [
                  "string",
                  "number",
                  "boolean"
                ]
              }
            }
          },
          "required": [
            "field",
            "op",
            "values"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "task": {
              "type": "string"
            }
          },
          "required": [
            "task"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "all": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/condition"
              },
              "minItems": 1
            }
          },
          "required": [
            "all"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "any": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/condition"
              },
              "minItems": 1
            }
          },
          "required": [
            "any"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "not": {
              "$ref": "#/$defs/condition"
            }
          },
          "required": [
            "not"
          ],
          "additionalProperties": false
        }
      ]
    },
    "part": {
      "type": "object",
      "properties": {
        "id": {
          "$ref": "#/$defs/fieldId"
        },
        "type": {
          "enum": [
            "boolean",
            "count",
            "string",
            "integer",
            "number",
            "enum",
            "path",
            "url"
          ]
        },
        "label": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "provider": {
          "type": "string"
        },
        "choices": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/choice"
          }
        },
        "suggestions": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/choice"
          }
        },
        "validation": {
          "$ref": "#/$defs/validation"
        },
        "path": {
          "$ref": "#/$defs/pathField"
        }
      },
      "required": [
        "id",
        "type"
      ],
      "additionalProperties": false
    },
    "variant": {
      "type": "object",
      "properties": {
        "id": {
          "$ref": "#/$defs/fieldId"
        },
        "label": {
          "type": "string"
        },
        "format": {
          "type": "string"
        },
        "parts": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/part"
          },
          "minItems": 1
        }
      },
      "required": [
        "id",
        "format",
        "parts"
      ],
      "additionalProperties": false
    },
    "field": {
      "type": "object",
      "properties": {
        "id": {
          "$ref": "#/$defs/fieldId"
        },
        "type": {
          "enum": [
            "boolean",
            "count",
            "string",
            "integer",
            "number",
            "enum",
            "path",
            "url"
          ]
        },
        "label": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "provider": {
          "type": "string"
        },
        "choices": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/choice"
          }
        },
        "suggestions": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/choice"
          }
        },
        "validation": {
          "$ref": "#/$defs/validation"
        },
        "path": {
          "$ref": "#/$defs/pathField"
        },
        "option": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "minItems": 1,
          "uniqueItems": true
        },
        "position": {
          "type": "integer",
          "minimum": 0
        },
        "fixed": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "minItems": 1
        },
        "from": {
          "type": "string"
        },
        "arity": {
          "enum": [
            0,
            1
          ]
        },
        "value_optional": {
          "type": "boolean",
          "description": "With optional_values, arity 1 admits bare null or an explicit closed value."
        },
        "value_style": {
          "enum": [
            "separate",
            "equals"
          ]
        },
        "false_option": {
          "type": "string"
        },
        "min": {
          "type": "integer",
          "minimum": 0
        },
        "max": {
          "type": "integer",
          "minimum": 1
        },
        "multiple": {
          "type": "boolean"
        },
        "observed_default": {
          "type": [
            "string",
            "number",
            "boolean"
          ]
        },
        "visible_when": {
          "$ref": "#/$defs/condition"
        },
        "enabled_when": {
          "$ref": "#/$defs/condition"
        },
        "effect": {
          "enum": [
            "normal",
            "overwrite",
            "delete",
            "exec"
          ]
        },
        "sensitive": {
          "type": "boolean"
        },
        "features": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "sources": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "minItems": 1
        },
        "variant": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/variant"
          },
          "minItems": 1
        },
        "hidden": {
          "type": "boolean"
        },
        "extensions": {
          "type": "object"
        }
      },
      "required": [
        "id"
      ],
      "additionalProperties": false,
      "oneOf": [
        {
          "required": [
            "option"
          ],
          "not": {
            "anyOf": [
              {
                "required": [
                  "position"
                ]
              },
              {
                "required": [
                  "fixed"
                ]
              },
              {
                "required": [
                  "from"
                ]
              }
            ]
          }
        },
        {
          "required": [
            "position"
          ],
          "not": {
            "anyOf": [
              {
                "required": [
                  "option"
                ]
              },
              {
                "required": [
                  "fixed"
                ]
              },
              {
                "required": [
                  "from"
                ]
              }
            ]
          }
        },
        {
          "required": [
            "fixed"
          ],
          "not": {
            "anyOf": [
              {
                "required": [
                  "option"
                ]
              },
              {
                "required": [
                  "position"
                ]
              },
              {
                "required": [
                  "from"
                ]
              }
            ]
          }
        },
        {
          "required": [
            "from"
          ],
          "not": {
            "anyOf": [
              {
                "required": [
                  "option"
                ]
              },
              {
                "required": [
                  "position"
                ]
              },
              {
                "required": [
                  "fixed"
                ]
              }
            ]
          }
        }
      ],
      "allOf": [
        {
          "if": {
            "required": [
              "fixed"
            ]
          },
          "then": {
            "not": {
              "anyOf": [
                {
                  "required": [
                    "type"
                  ]
                },
                {
                  "required": [
                    "variant"
                  ]
                }
              ]
            }
          }
        },
        {
          "if": {
            "not": {
              "anyOf": [
                {
                  "required": [
                    "fixed"
                  ]
                },
                {
                  "required": [
                    "from"
                  ]
                },
                {
                  "required": [
                    "variant"
                  ]
                }
              ]
            }
          },
          "then": {
            "required": [
              "type"
            ]
          }
        },
        {
          "if": {
            "not": {
              "required": [
                "from"
              ]
            }
          },
          "then": {
            "required": [
              "sources"
            ]
          }
        }
      ]
    },
    "constraint": {
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "kind": {
              "enum": [
                "requires"
              ]
            },
            "when": {
              "$ref": "#/$defs/condition"
            },
            "field": {
              "$ref": "#/$defs/fieldId"
            },
            "message": {
              "type": "string"
            }
          },
          "required": [
            "kind",
            "field"
          ],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "kind": {
              "enum": [
                "at_most_one",
                "exactly_one"
              ]
            },
            "fields": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/fieldId"
              },
              "minItems": 1
            },
            "message": {
              "type": "string"
            },
            "when": {
              "$ref": "#/$defs/condition"
            }
          },
          "required": [
            "kind",
            "fields"
          ],
          "additionalProperties": false
        }
      ]
    },
    "task": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "pattern": "^[a-z0-9_-]+$"
        },
        "label": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "set": {
          "type": "object",
          "additionalProperties": {
            "type": "array",
            "items": {
              "oneOf": [
                {
                  "type": [
                    "string",
                    "number",
                    "boolean",
                    "null"
                  ]
                },
                {
                  "type": "object",
                  "properties": {
                    "variant": {
                      "$ref": "#/$defs/fieldId"
                    },
                    "parts": {
                      "type": "object",
                      "additionalProperties": {
                        "type": [
                          "string",
                          "number",
                          "boolean"
                        ]
                      }
                    }
                  },
                  "required": [
                    "variant",
                    "parts"
                  ],
                  "additionalProperties": false
                }
              ]
            }
          }
        },
        "lock": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "fields": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "required": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "required": [
        "id",
        "label"
      ],
      "additionalProperties": false
    },
    "commandNode": {
      "type": "object",
      "properties": {
        "format": {
          "enum": [
            1
          ]
        },
        "label": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "quality": {
          "enum": [
            "curated",
            "structured",
            "completion",
            "help",
            "ai-draft"
          ]
        },
        "base": {
          "type": "string",
          "pattern": "^fig:.+"
        },
        "required_capabilities": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "features": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "extensions": {
          "type": "object"
        },
        "parser": {
          "type": "object",
          "properties": {
            "end_of_options": {
              "enum": [
                "--",
                ""
              ]
            },
            "interleave": {
              "enum": [
                "permute",
                "posix"
              ]
            },
            "long_equals": {
              "type": "boolean"
            },
            "short_attached": {
              "type": "boolean"
            },
            "short_bundles": {
              "type": "boolean"
            }
          },
          "required": [],
          "additionalProperties": false
        },
        "source": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "kind": {
                "type": "string"
              },
              "revision": {
                "type": "string"
              },
              "url": {
                "type": "string"
              },
              "license": {
                "type": "string"
              },
              "evidence": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "kind"
            ],
            "additionalProperties": false
          }
        },
        "field": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/field"
          }
        },
        "constraint": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/constraint"
          }
        },
        "task": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/task"
          }
        },
        "group": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "label": {
                "type": "string"
              },
              "fields": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "visible_when": {
                "$ref": "#/$defs/condition"
              }
            },
            "required": [
              "id",
              "fields"
            ],
            "additionalProperties": false
          }
        },
        "path": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "minItems": 1
        }
      },
      "required": [
        "path"
      ],
      "additionalProperties": false
    },
    "commands": {
      "type": "object",
      "properties": {
        "format": {
          "enum": [
            1
          ]
        },
        "label": {
          "type": "string"
        },
        "description": {
          "type": "string"
        },
        "quality": {
          "enum": [
            "curated",
            "structured",
            "completion",
            "help",
            "ai-draft"
          ]
        },
        "base": {
          "type": "string",
          "pattern": "^fig:.+"
        },
        "required_capabilities": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "features": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "extensions": {
          "type": "object"
        },
        "parser": {
          "type": "object",
          "properties": {
            "end_of_options": {
              "enum": [
                "--",
                ""
              ]
            },
            "interleave": {
              "enum": [
                "permute",
                "posix"
              ]
            },
            "long_equals": {
              "type": "boolean"
            },
            "short_attached": {
              "type": "boolean"
            },
            "short_bundles": {
              "type": "boolean"
            }
          },
          "required": [],
          "additionalProperties": false
        },
        "source": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "kind": {
                "type": "string"
              },
              "revision": {
                "type": "string"
              },
              "url": {
                "type": "string"
              },
              "license": {
                "type": "string"
              },
              "evidence": {
                "type": "string"
              }
            },
            "required": [
              "id",
              "kind"
            ],
            "additionalProperties": false
          }
        },
        "field": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/field"
          }
        },
        "constraint": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/constraint"
          }
        },
        "task": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/task"
          }
        },
        "group": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "label": {
                "type": "string"
              },
              "fields": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "visible_when": {
                "$ref": "#/$defs/condition"
              }
            },
            "required": [
              "id",
              "fields"
            ],
            "additionalProperties": false
          }
        },
        "subcommand": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/commandNode"
          }
        }
      },
      "required": [],
      "additionalProperties": false
    },
    "dotfiles": {
      "type": "object",
      "properties": {
        "paths": {
          "description": "Config files and directories to sync as ordinary content. Directories end with a slash. Globs allowed. May be empty: a tool whose only user-level file is a credential is written with an empty paths and a non-empty secret, which records that the credential is where its config would be rather than leaving the tool out of the catalog. At least one of paths and secret must be non-empty.",
          "type": "array",
          "minItems": 0,
          "uniqueItems": true,
          "items": {
            "$ref": "#/$defs/path"
          }
        },
        "exclude": {
          "description": "Paths that must never sync, typically carving state out of a directory listed in paths. Entries may be globs: `*` and `?` match within one path segment and stop at `/`, `**` crosses directories (`a/**/b` also matches `a/b`), and a trailing `/` names a directory and everything below it. Never list the four default carve-outs \u2014 `.git/`, `node_modules/`, `__pycache__/` and `.venv/` inside a directory in paths: every consumer skips those names at any depth below a synced directory without being told, unless paths names something at or inside one explicitly, in which case the explicit entry wins.",
          "type": "array",
          "uniqueItems": true,
          "items": {
            "$ref": "#/$defs/path"
          }
        },
        "secret": {
          "description": "Whole-file secrets: the file is a credential end to end. Never synced as plaintext content \u2014 a consumer that syncs it at all does so through its own secret store, under a separate key. A path here must not also appear in paths.",
          "type": "array",
          "uniqueItems": true,
          "items": {
            "$ref": "#/$defs/path"
          }
        },
        "side_effect": {
          "description": "True when a live process may be reading the file, so a consumer should wait for a quiet moment before writing it. Defaults to true.",
          "type": "boolean"
        },
        "self_sync": {
          "description": "True when the tool syncs these files itself \u2014 VS Code's Settings Sync, a browser signed into an account, a dotfile manager whose whole job this is. Two mechanisms writing one file fight each other, and the tool wins: it holds the file open and rewrites it from its own copy. A consumer should leave these alone by default and ask before taking them over. Defaults to false.",
          "type": "boolean"
        },
        "machine_lines": {
          "description": "Parts of a synced file that belong to one machine and stay behind on it. A rule matching except_key_path may also name a file in secret: only the keys it lists then sync, and the rest of the file \u2014 the credential with it \u2014 never leaves the machine.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/rule"
          }
        },
        "secret_paths": {
          "description": "Secret fields inside an otherwise syncable file. Extracted into the consumer's secret store.",
          "type": "array",
          "items": {
            "$ref": "#/$defs/rule"
          }
        },
        "format": {
          "enum": [
            1
          ]
        }
      },
      "required": [
        "paths"
      ],
      "additionalProperties": false
    }
  }
}
