{
  "openapi": "3.1.0",
  "info": {
    "title": "Skillet Registry API",
    "version": "1.0.0",
    "summary": "Read and publish agent skills on Skillet.",
    "description": "Skillet is a registry for agent skills: a skill is a `SKILL.md` file (plus optional\nscripts, references, and assets) that an AI agent loads to gain a capability.\nPublish a skill once and it syncs to every agent runtime a person uses.\n\n**When an agent should call this API**\n\n- Find an existing skill for a task before writing instructions from scratch:\n  `GET /search?q=...` or `GET /skills?q=...`.\n- Read a specific skill's instructions to perform a task: `GET /skills/{author}/{slug}`\n  then `GET /skills/{author}/{slug}/versions/{hash}/file?path=SKILL.md`.\n- Look up who publishes in a domain: `GET /discover/people` or `GET /profiles/{author}`.\n- Check what a skill is allowed to do before running it: `GET /skills/{author}/{slug}/versions/{hash}/scan`.\n\n**Auth**\n\nEvery read operation listed here is anonymous: no key, no signup, no sales call. Publishing\nand device sync use a bearer token whose class fixes its scopes (see `securitySchemes`); a\ntoken can never widen its own scope. Mint one yourself in seconds — sign in at the site and\npair a machine with the `skilletmd` CLI (`npx skilletmd`), or enable a read-only MCP link at\nSettings → Account. Scopes are also published machine-readably as RFC 9728 protected-resource\nmetadata at https://registry.skillet.md/.well-known/oauth-protected-resource, which is where the\n`WWW-Authenticate` header on a `401` points.\n\n**Rate limits**\n\nMetered responses carry the RateLimit header fields. `RateLimit-Limit` and `RateLimit-Policy`\ndescribe the policy and are always present. `RateLimit-Remaining`, `RateLimit-Reset`, and the\ncombined `RateLimit` field describe YOUR bucket, so they are sent only when the response is\nnot shared-cacheable: catalog reads sit in a CDN edge cache, where one caller's count would\nbe served to the next. Pace against `RateLimit-Policy`; read the live counter from any\nuncached response or from the `429`, which is always `no-store` and adds `Retry-After`.\n\n**Versioning and deprecation**\n\nThe version lives in the URL path (`/api/v1`). A path under that prefix never changes\nmeaning: breaking changes ship as a new prefix, and the old one keeps answering. When an\nendpoint is on its way out it answers with `Deprecation` (RFC 9745) and a\n`Link: <...>; rel=\"deprecation\"` pointing at the policy page, and a `Sunset` (RFC 8594) date\nonce one is set. Nothing is removed without that header appearing first.\n\n**Errors**\n\nFailures are always JSON with the `Error` schema below: a stable `code`, a human\n`message`, and a `docs` URL that resolves the failure. Never an HTML page.",
    "contact": {
      "name": "Skillet",
      "url": "https://skillet.md/contact"
    },
    "license": {
      "name": "Apache-2.0",
      "identifier": "Apache-2.0"
    },
    "termsOfService": "https://skillet.md/legal/terms",
    "x-onboarding": {
      "anonymous_reads": true,
      "free_tier": true,
      "self_serve_credentials": true,
      "credential_url": "https://skillet.md/docs/api#auth",
      "cli": "npx skilletmd",
      "contact_sales_required": false
    },
    "x-rate-limit-headers": {
      "limit": "RateLimit-Limit",
      "remaining": "RateLimit-Remaining",
      "reset": "RateLimit-Reset",
      "policy": "RateLimit-Policy",
      "combined": "RateLimit",
      "retry_after": "Retry-After",
      "always_present": [
        "RateLimit-Limit",
        "RateLimit-Policy"
      ],
      "uncached_only": [
        "RateLimit-Remaining",
        "RateLimit-Reset",
        "RateLimit"
      ],
      "documentation": "https://skillet.md/docs/api#rate-limits"
    },
    "x-versioning": {
      "strategy": "url-path",
      "current": "/api/v1",
      "deprecation_header": "Deprecation",
      "sunset_header": "Sunset",
      "policy_url": "https://skillet.md/docs/versioning"
    },
    "x-protected-resource-metadata": "https://registry.skillet.md/.well-known/oauth-protected-resource"
  },
  "servers": [
    {
      "url": "https://skillet.md/api/v1",
      "description": "Public read-only mirror on the canonical site origin. GET and HEAD only."
    },
    {
      "url": "https://registry.skillet.md/api/v1",
      "description": "Registry origin. Full surface, including authenticated writes."
    }
  ],
  "tags": [
    {
      "name": "skills",
      "description": "The skill catalog: search, detail, versions, and content."
    },
    {
      "name": "discovery",
      "description": "Cross-catalog search and browse feeds."
    },
    {
      "name": "people",
      "description": "Author and team profiles, and the trust graph."
    },
    {
      "name": "kits",
      "description": "Kits: named, versioned collections of skills."
    },
    {
      "name": "registry",
      "description": "Registry-wide status and enforcement records."
    }
  ],
  "externalDocs": {
    "description": "Skillet API guide, auth scopes, and MCP setup",
    "url": "https://skillet.md/docs/api"
  },
  "security": [
    {}
  ],
  "paths": {
    "/skills": {
      "get": {
        "operationId": "listSkills",
        "tags": [
          "skills"
        ],
        "summary": "List published skills",
        "description": "The public skill catalog, newest first by default. Use `q` for a substring match over name and description, or `category` to narrow to one domain. Returns only public skills for an anonymous caller.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size. Clamped server-side to 1-100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Zero-based offset into the result set.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Free-text filter over skill name and description.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "One category key, or a comma-separated list. Unknown keys are ignored rather than widening the query.",
            "schema": {
              "type": "string",
              "examples": [
                "frontend",
                "devops,backend"
              ]
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "`new` for most recently published, `alpha` for name order.",
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "alpha"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of catalog entries.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SkillListPage"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/skills/{author}/{slug}": {
      "get": {
        "operationId": "getSkill",
        "tags": [
          "skills"
        ],
        "summary": "Get one skill",
        "description": "A skill's full public record: description, category, latest version hash, the version list, scan and signature status, provenance, and token cost. Fetch this before reading skill content so you know which `hash` to request.",
        "parameters": [
          {
            "name": "author",
            "in": "path",
            "required": true,
            "description": "Owner handle, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-39 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,38}$",
              "examples": [
                "shadcn"
              ]
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Skill slug, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-63 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
              "examples": [
                "shadcn"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The skill detail record.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SkillDetail"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/skills/{author}/{slug}/manifest": {
      "get": {
        "operationId": "getSkillManifest",
        "tags": [
          "skills"
        ],
        "summary": "Get the latest version manifest",
        "description": "The per-file manifest of the latest published version: every bundle path with its size and content hash. Use it to verify a download or to decide which files are worth fetching.",
        "parameters": [
          {
            "name": "author",
            "in": "path",
            "required": true,
            "description": "Owner handle, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-39 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,38}$",
              "examples": [
                "shadcn"
              ]
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Skill slug, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-63 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
              "examples": [
                "shadcn"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The manifest for the latest published version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionManifest"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/skills/{author}/{slug}/versions/{hash}/files": {
      "get": {
        "operationId": "listSkillVersionFiles",
        "tags": [
          "skills"
        ],
        "summary": "List the files in a version",
        "description": "Every file in one published version, with size and kind. `SKILL.md` is always present; supporting `scripts/`, `references/`, and `assets/` files appear when the author bundled them.",
        "parameters": [
          {
            "name": "author",
            "in": "path",
            "required": true,
            "description": "Owner handle, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-39 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,38}$",
              "examples": [
                "shadcn"
              ]
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Skill slug, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-63 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
              "examples": [
                "shadcn"
              ]
            }
          },
          {
            "name": "hash",
            "in": "path",
            "required": true,
            "description": "Content hash of a published version, with or without the `sha256:` prefix. Read it from `latest_hash` or the `versions[]` list on the skill detail response.",
            "schema": {
              "type": "string",
              "pattern": "^(sha256:)?[a-f0-9]{64}$",
              "examples": [
                "sha256:c57e3cc8688fe5f0956c8e91ee02d1ee97fb5b0e8115e2d6ca6447c1ade69686"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The file listing for that version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionFileList"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/skills/{author}/{slug}/versions/{hash}/file": {
      "get": {
        "operationId": "getSkillVersionFile",
        "tags": [
          "skills"
        ],
        "summary": "Read one file from a version",
        "description": "The decoded text of a single bundle file. Request `path=SKILL.md` to read the instructions an agent loads. Responses carry a strong ETag; send `If-None-Match` to get a 304 instead of a re-download.",
        "parameters": [
          {
            "name": "author",
            "in": "path",
            "required": true,
            "description": "Owner handle, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-39 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,38}$",
              "examples": [
                "shadcn"
              ]
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Skill slug, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-63 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
              "examples": [
                "shadcn"
              ]
            }
          },
          {
            "name": "hash",
            "in": "path",
            "required": true,
            "description": "Content hash of a published version, with or without the `sha256:` prefix. Read it from `latest_hash` or the `versions[]` list on the skill detail response.",
            "schema": {
              "type": "string",
              "pattern": "^(sha256:)?[a-f0-9]{64}$",
              "examples": [
                "sha256:c57e3cc8688fe5f0956c8e91ee02d1ee97fb5b0e8115e2d6ca6447c1ade69686"
              ]
            }
          },
          {
            "name": "path",
            "in": "query",
            "required": true,
            "description": "Bundle-relative file path, e.g. `SKILL.md` or `references/API.md`.",
            "schema": {
              "type": "string",
              "examples": [
                "SKILL.md"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The file, decoded as text.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VersionFile"
                }
              }
            }
          },
          "304": {
            "description": "The caller already has this exact version of the file."
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/skills/{author}/{slug}/versions/{hash}/scan": {
      "get": {
        "operationId": "getSkillVersionScan",
        "tags": [
          "skills"
        ],
        "summary": "Get the harm-scan verdict for a version",
        "description": "The registry's static scan of a version: an overall verdict plus the findings behind it. Read this before running a third-party skill; `quarantined` means the registry refuses to serve the content at all.",
        "parameters": [
          {
            "name": "author",
            "in": "path",
            "required": true,
            "description": "Owner handle, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-39 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,38}$",
              "examples": [
                "shadcn"
              ]
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Skill slug, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-63 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
              "examples": [
                "shadcn"
              ]
            }
          },
          {
            "name": "hash",
            "in": "path",
            "required": true,
            "description": "Content hash of a published version, with or without the `sha256:` prefix. Read it from `latest_hash` or the `versions[]` list on the skill detail response.",
            "schema": {
              "type": "string",
              "pattern": "^(sha256:)?[a-f0-9]{64}$",
              "examples": [
                "sha256:c57e3cc8688fe5f0956c8e91ee02d1ee97fb5b0e8115e2d6ca6447c1ade69686"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The scan record for that version.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScanReport"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/skills/{author}/{slug}/kits": {
      "get": {
        "operationId": "listKitsForSkill",
        "tags": [
          "skills"
        ],
        "summary": "List the kits a skill belongs to",
        "description": "Public kits that include this skill. Useful for finding curated collections around a capability you already trust.",
        "parameters": [
          {
            "name": "author",
            "in": "path",
            "required": true,
            "description": "Owner handle, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-39 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,38}$",
              "examples": [
                "shadcn"
              ]
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Skill slug, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-63 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
              "examples": [
                "shadcn"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The kits containing this skill.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "kits": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/KitSummary"
                      }
                    }
                  },
                  "required": [
                    "kits"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/search": {
      "get": {
        "operationId": "search",
        "tags": [
          "discovery"
        ],
        "summary": "Search skills, kits, and people",
        "description": "One query across every public object type. This is the right first call for \"is there already a skill for X\" — it ranks skills, kits, authors, and teams together.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "The search query. An empty query returns no results.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "examples": [
                "code review"
              ]
            }
          },
          {
            "name": "types",
            "in": "query",
            "required": false,
            "description": "Comma-separated object types to include. Defaults to all of `skills,kits,people`.",
            "schema": {
              "type": "string",
              "examples": [
                "skills",
                "skills,people"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum results per type.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ranked results grouped by type.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResults"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/discover/kits": {
      "get": {
        "operationId": "listKits",
        "tags": [
          "kits"
        ],
        "summary": "Browse public kits",
        "description": "The public kit catalog. A kit is a named, versioned collection of skills that a person or team maintains; subscribing to one keeps every member skill current.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size. Clamped server-side to 1-100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Zero-based offset into the result set.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Free-text filter over kit name and description.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "One category key, or a comma-separated list.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "`new` for most recently published, `alpha` for name order.",
            "schema": {
              "type": "string",
              "enum": [
                "new",
                "alpha"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of public kits.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KitListPage"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/discover/people": {
      "get": {
        "operationId": "listPeople",
        "tags": [
          "people"
        ],
        "summary": "Browse authors and teams",
        "description": "Public profiles that have published at least one skill, with the categories they publish in. Use it to answer \"who is worth following for X\".",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size. Clamped server-side to 1-100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Zero-based offset into the result set.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Free-text filter over handle, display name, and bio.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "One category key, or a comma-separated list.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Ordering: `followers`, `new`, or `alpha`.",
            "schema": {
              "type": "string",
              "enum": [
                "followers",
                "new",
                "alpha"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of public profiles.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PeopleListPage"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/discover/feed": {
      "get": {
        "operationId": "listActivity",
        "tags": [
          "discovery"
        ],
        "summary": "Read the public activity feed",
        "description": "Registry-wide public activity — publishes, new kits, new profiles — newest first. Poll it to track what changed since a previous read.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size. Clamped server-side to 1-100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Zero-based offset into the result set.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of public activity events.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActivityPage"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/profiles/{author}": {
      "get": {
        "operationId": "getProfile",
        "tags": [
          "people"
        ],
        "summary": "Get an author or team profile",
        "description": "A profile's public record: display name, bio, avatar, follower counts, public adopter count, and every public skill they publish.",
        "parameters": [
          {
            "name": "author",
            "in": "path",
            "required": true,
            "description": "Owner handle, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-39 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,38}$",
              "examples": [
                "shadcn"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The profile record.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Profile"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/profiles/{author}/followers": {
      "get": {
        "operationId": "listFollowers",
        "tags": [
          "people"
        ],
        "summary": "List a profile’s followers",
        "description": "Public handles that follow this profile.",
        "parameters": [
          {
            "name": "author",
            "in": "path",
            "required": true,
            "description": "Owner handle, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-39 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,38}$",
              "examples": [
                "shadcn"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size. Clamped server-side to 1-100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Zero-based offset into the result set.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of follower handles.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HandleListPage"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/profiles/{author}/following": {
      "get": {
        "operationId": "listFollowing",
        "tags": [
          "people"
        ],
        "summary": "List who a profile follows",
        "description": "Public handles this profile follows.",
        "parameters": [
          {
            "name": "author",
            "in": "path",
            "required": true,
            "description": "Owner handle, e.g. `shadcn`. Lowercase alphanumerics and hyphens, 1-39 chars.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,38}$",
              "examples": [
                "shadcn"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size. Clamped server-side to 1-100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Zero-based offset into the result set.",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of followed handles.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HandleListPage"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/kits/by-handle/{owner}/{slug}": {
      "get": {
        "operationId": "getKitByHandle",
        "tags": [
          "kits"
        ],
        "summary": "Get a kit by owner and slug",
        "description": "One public kit and its member skills, addressed the same way its web page is (`/{owner}/kit/{slug}`).",
        "parameters": [
          {
            "name": "owner",
            "in": "path",
            "required": true,
            "description": "Handle of the person or team that owns the kit.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,38}$",
              "examples": [
                "shadcn"
              ]
            }
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Kit slug.",
            "schema": {
              "type": "string",
              "pattern": "^[a-z0-9][a-z0-9-]{0,62}$",
              "examples": [
                "kit"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The kit and its members.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Kit"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/stats": {
      "get": {
        "operationId": "getRegistryStats",
        "tags": [
          "registry"
        ],
        "summary": "Get registry-wide totals",
        "description": "Public aggregates: skill, kit, author, and device counts, plus recent publish volume. No identity is exposed.",
        "responses": {
          "200": {
            "description": "Registry totals.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RegistryStats"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/moderation": {
      "get": {
        "operationId": "listModerationActions",
        "tags": [
          "registry"
        ],
        "summary": "Read the public moderation log",
        "description": "Currently-active enforcement against skills and accounts. Published so a downstream consumer can independently check whether something it cached has since been removed.",
        "responses": {
          "200": {
            "description": "Active enforcement records.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ModerationLog"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ]
      }
    },
    "/whoami": {
      "get": {
        "operationId": "whoami",
        "tags": [
          "registry"
        ],
        "summary": "Identify the calling token",
        "description": "Resolves the bearer token to its principal and the scopes it carries. Anonymous callers get `{\"authenticated\": false}` rather than a 401, so it doubles as a cheap credential check.",
        "security": [
          {},
          {
            "bearerAuth": [
              "read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "The caller identity and granted scopes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhoAmI"
                }
              }
            }
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/sync/manifest": {
      "get": {
        "operationId": "getSyncManifest",
        "tags": [
          "registry"
        ],
        "summary": "Get the sync manifest for a paired device",
        "description": "Everything a device is entitled to hold: each skill's approved version and content hash. Requires a device or session token with the `sync` scope. Send `If-None-Match` with the previous ETag to poll cheaply.",
        "security": [
          {
            "bearerAuth": [
              "sync"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "The manifest of approved skill versions for this device.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SyncManifest"
                }
              }
            }
          },
          "304": {
            "description": "Nothing changed since the ETag the caller sent."
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, expired, or revoked token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "The token is valid but lacks the `sync` scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "callMcp",
        "tags": [
          "registry"
        ],
        "summary": "Call the hosted MCP server",
        "description": "JSON-RPC 2.0 over Streamable HTTP. Exposes the caller's kit as MCP tools (`list_skills`, `get_skill`, plus `search`/`fetch` aliases for deep-research clients). Read-only: an MCP token can never publish or sync-write. Enable the link at Settings → Account on the site, then point a client at it.",
        "security": [
          {
            "bearerAuth": [
              "read"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "description": "A JSON-RPC 2.0 request or notification.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonRpcRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The JSON-RPC response.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonRpcResponse"
                }
              }
            }
          },
          "202": {
            "description": "A JSON-RPC notification was accepted; no body."
          },
          "400": {
            "description": "The request was malformed (bad parameter, missing field).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Missing, disabled, or revoked MCP token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "No such resource, or it is not readable by this caller.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited. Retry after the window in `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "A Skillet bearer token. The class prefix fixes the scopes; a token cannot widen its own grant.\n\n| Prefix | Class | Scopes |\n| --- | --- | --- |\n| `skillet_s_` | user session | `read`, `sync`, `publish`, `claim` |\n| `skillet_d_` | paired device | `read`, `sync` |\n| `skillet_k_` | kit key | `read`, `sync` (one kit only) |\n| `skillet_m_` | hosted MCP link | `read` |\n\nRequest the narrowest class that does the job: an integration that only reads a kit should hold a kit key, not a session token.",
        "x-scopes": {
          "read": "Read public and self-owned skills, kits, and profiles.",
          "sync": "Read the sync manifest and pull approved skill content for a paired device.",
          "publish": "Publish new skill versions and change skill visibility.",
          "claim": "Claim a handle and bind an author signing key."
        },
        "x-protected-resource-metadata": "https://registry.skillet.md/.well-known/oauth-protected-resource"
      },
      "mcpLinkToken": {
        "type": "apiKey",
        "in": "path",
        "name": "token",
        "description": "The hosted MCP link embeds its `skillet_m_` token in the URL (`/mcp/{token}`) for clients that cannot set an Authorization header. Read-only, revocable by regenerating the link."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "The shape of every failure response. `code` is stable and safe to branch on; `message` is for humans; `docs` points at the page that resolves it.",
        "properties": {
          "error": {
            "type": "string",
            "description": "Short reason phrase, e.g. `Not Found`.",
            "examples": [
              "Not Found"
            ]
          },
          "code": {
            "type": "string",
            "description": "Stable machine-readable error code, e.g. `skill_not_found`.",
            "examples": [
              "skill_not_found"
            ]
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation.",
            "examples": [
              "Skill not found"
            ]
          },
          "statusCode": {
            "type": "integer",
            "description": "The HTTP status, repeated in the body."
          },
          "docs": {
            "type": "string",
            "format": "uri",
            "description": "Documentation that explains how to resolve this error."
          },
          "request_id": {
            "type": "string",
            "description": "Opaque id correlating this failure to the server log. Present on 5xx."
          }
        },
        "required": [
          "error"
        ]
      },
      "SkillSummary": {
        "type": "object",
        "description": "A catalog entry. Enough to decide whether to fetch the full skill.",
        "properties": {
          "author": {
            "type": "string",
            "description": "Owner handle.",
            "examples": [
              "shadcn"
            ]
          },
          "slug": {
            "type": "string",
            "description": "Skill slug.",
            "examples": [
              "shadcn"
            ]
          },
          "skill_id": {
            "type": "string",
            "description": "Canonical `owner:slug` identifier.",
            "examples": [
              "shadcn:shadcn"
            ]
          },
          "description": {
            "type": "string",
            "description": "What the skill does and when to use it.",
            "examples": [
              "Manages shadcn components and projects: adding, searching, fixing, and composing UI."
            ]
          },
          "visibility": {
            "type": "string",
            "enum": [
              "public",
              "private"
            ]
          },
          "latest_hash": {
            "type": "string",
            "description": "Content hash of the latest version.",
            "examples": [
              "sha256:c57e3cc8688fe5f0956c8e91ee02d1ee97fb5b0e8115e2d6ca6447c1ade69686"
            ]
          },
          "version": {
            "type": "integer",
            "description": "Monotonic version number.",
            "examples": [
              3
            ]
          },
          "version_label": {
            "type": "string",
            "description": "Semver-style display label.",
            "examples": [
              "1.2.0"
            ]
          },
          "install_count": {
            "type": "integer",
            "description": "Times this skill has been installed.",
            "examples": [
              412
            ]
          },
          "created_at": {
            "type": "integer",
            "description": "Unix seconds when first published.",
            "examples": [
              1787163766
            ]
          },
          "category": {
            "type": [
              "string",
              "null"
            ],
            "description": "Category key, e.g. `frontend`.",
            "examples": [
              "frontend"
            ]
          },
          "signatureStatus": {
            "type": "string",
            "enum": [
              "verified",
              "unverified",
              "invalid"
            ],
            "description": "Whether the latest version carries a valid author signature."
          },
          "scanStatus": {
            "type": "string",
            "enum": [
              "clean",
              "flagged",
              "quarantined",
              "pending",
              "unknown"
            ],
            "description": "Harm-scan verdict for the latest version."
          },
          "moderationStatus": {
            "type": "string",
            "description": "Active enforcement, or `none`.",
            "examples": [
              "none"
            ]
          },
          "deprecated": {
            "type": "boolean",
            "description": "The author has retired this skill."
          },
          "used_by": {
            "type": "array",
            "items": {
              "type": "string",
              "examples": [
                "gtm"
              ]
            },
            "description": "Handles of public adopters."
          },
          "used_by_count": {
            "type": "integer",
            "description": "Number of public adopters.",
            "examples": [
              12
            ]
          }
        },
        "required": [
          "author",
          "slug",
          "skill_id",
          "description",
          "visibility"
        ]
      },
      "SkillDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/SkillSummary"
          },
          {
            "type": "object",
            "properties": {
              "versions": {
                "type": "array",
                "description": "Every published version, newest first.",
                "items": {
                  "type": "object",
                  "properties": {
                    "hash": {
                      "type": "string"
                    },
                    "published_at": {
                      "type": "integer"
                    },
                    "version_label": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "hash",
                    "published_at"
                  ]
                }
              },
              "author_name": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Owner display name."
              },
              "author_avatar_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri"
              },
              "author_public_key": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Base64 Ed25519 public key the signature chains to."
              },
              "manifest_url": {
                "type": "string",
                "description": "Path to the per-file manifest for the latest version."
              },
              "is_mirror": {
                "type": "boolean",
                "description": "True when the skill mirrors an upstream repository."
              },
              "mirror_source_url": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "uri"
              },
              "mirror_license": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "SPDX identifier declared upstream."
              },
              "triggers": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Phrases the author expects to activate this skill."
              },
              "token_count": {
                "type": "integer",
                "description": "Approximate tokens the full SKILL.md costs to load."
              },
              "deprecation_message": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        ]
      },
      "SkillListPage": {
        "type": "object",
        "properties": {
          "skills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SkillSummary"
            }
          },
          "total": {
            "type": "integer",
            "description": "Total matches, ignoring pagination.",
            "examples": [
              1145
            ]
          },
          "limit": {
            "type": "integer",
            "examples": [
              50
            ]
          },
          "offset": {
            "type": "integer",
            "examples": [
              0
            ]
          }
        },
        "required": [
          "skills",
          "total",
          "limit",
          "offset"
        ]
      },
      "FileMeta": {
        "type": "object",
        "properties": {
          "path": {
            "type": "string",
            "description": "Bundle-relative path."
          },
          "size": {
            "type": "integer",
            "description": "Bytes."
          },
          "hash": {
            "type": "string",
            "description": "Content hash of this file."
          }
        },
        "required": [
          "path"
        ]
      },
      "VersionManifest": {
        "type": "object",
        "properties": {
          "schema_version": {
            "type": "integer"
          },
          "hash": {
            "type": "string",
            "description": "Content hash of the version."
          },
          "author": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "files": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FileMeta"
            }
          }
        },
        "required": [
          "hash",
          "author",
          "slug",
          "files"
        ]
      },
      "VersionFileList": {
        "type": "object",
        "properties": {
          "schema_version": {
            "type": "integer"
          },
          "hash": {
            "type": "string"
          },
          "author": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "files": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FileMeta"
            }
          }
        },
        "required": [
          "hash",
          "author",
          "slug",
          "files"
        ]
      },
      "VersionFile": {
        "type": "object",
        "properties": {
          "schema_version": {
            "type": "integer"
          },
          "hash": {
            "type": "string"
          },
          "author": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "path": {
            "type": "string"
          },
          "size": {
            "type": "integer"
          },
          "text": {
            "type": "string",
            "description": "The decoded file contents."
          }
        },
        "required": [
          "hash",
          "author",
          "slug",
          "path"
        ]
      },
      "ScanReport": {
        "type": "object",
        "properties": {
          "hash": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "clean",
              "flagged",
              "quarantined",
              "pending",
              "unknown"
            ],
            "description": "The verdict. `quarantined` content is never served."
          },
          "corpus_version": {
            "type": "integer",
            "description": "Detector corpus the verdict was produced against."
          },
          "findings": {
            "type": "array",
            "description": "Individual detector hits behind the verdict.",
            "items": {
              "type": "object",
              "properties": {
                "detector": {
                  "type": "string"
                },
                "severity": {
                  "type": "string"
                },
                "path": {
                  "type": "string"
                },
                "line": {
                  "type": "integer"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "detector",
                "severity"
              ]
            }
          }
        },
        "required": [
          "status"
        ]
      },
      "KitSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "owner": {
            "type": "string",
            "description": "Handle of the owning person or team."
          },
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "skill_count": {
            "type": "integer"
          },
          "subscriber_count": {
            "type": "integer"
          },
          "category": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "owner",
          "name"
        ]
      },
      "Kit": {
        "allOf": [
          {
            "$ref": "#/components/schemas/KitSummary"
          },
          {
            "type": "object",
            "properties": {
              "skills": {
                "type": "array",
                "description": "Member skills, in kit order.",
                "items": {
                  "$ref": "#/components/schemas/SkillSummary"
                }
              },
              "version": {
                "type": "integer",
                "description": "Published kit version."
              }
            }
          }
        ]
      },
      "KitListPage": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KitSummary"
            }
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          }
        },
        "required": [
          "items",
          "total",
          "limit",
          "offset"
        ]
      },
      "Profile": {
        "type": "object",
        "properties": {
          "handle": {
            "type": "string",
            "examples": [
              "shadcn"
            ]
          },
          "displayName": {
            "type": [
              "string",
              "null"
            ],
            "examples": [
              "shadcn/ui"
            ]
          },
          "bio": {
            "type": [
              "string",
              "null"
            ],
            "examples": [
              "Official shadcn/ui workflow."
            ]
          },
          "avatarUrl": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri"
          },
          "kind": {
            "type": "string",
            "enum": [
              "user",
              "team"
            ]
          },
          "followers": {
            "type": "integer"
          },
          "following": {
            "type": "integer"
          },
          "totalInstalls": {
            "type": "integer",
            "description": "Public adopters (kit saves plus subscriptions), not raw installs — installer identity is private."
          },
          "skills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SkillSummary"
            }
          }
        },
        "required": [
          "handle"
        ]
      },
      "PeopleListPage": {
        "type": "object",
        "properties": {
          "people": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "handle": {
                  "type": "string"
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "bio": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "avatar_url": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uri"
                },
                "followers": {
                  "type": "integer"
                },
                "public_skills": {
                  "type": "integer"
                },
                "kits": {
                  "type": "integer"
                },
                "categories": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                },
                "created_at": {
                  "type": "integer"
                }
              },
              "required": [
                "handle"
              ]
            }
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          }
        },
        "required": [
          "people"
        ]
      },
      "HandleListPage": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "handle": {
                  "type": "string"
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "avatar_url": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uri"
                }
              },
              "required": [
                "handle"
              ]
            }
          },
          "total": {
            "type": "integer"
          }
        },
        "required": [
          "items"
        ]
      },
      "SearchResults": {
        "type": "object",
        "description": "Ranked matches grouped by object type. Absent groups mean no matches.",
        "properties": {
          "skills": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SkillSummary"
            }
          },
          "kits": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KitSummary"
            }
          },
          "people": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "handle": {
                  "type": "string"
                },
                "name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "avatar_url": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "uri"
                }
              },
              "required": [
                "handle"
              ]
            }
          }
        }
      },
      "ActivityPage": {
        "type": "object",
        "properties": {
          "events": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "kind": {
                  "type": "string",
                  "description": "Event type, e.g. `skill_published`, `kit_published`."
                },
                "actor": {
                  "type": "string",
                  "description": "Handle that caused the event."
                },
                "skill_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "kit_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "created_at": {
                  "type": "integer",
                  "description": "Unix seconds."
                }
              },
              "required": [
                "kind",
                "created_at"
              ]
            }
          }
        },
        "required": [
          "events"
        ]
      },
      "RegistryStats": {
        "type": "object",
        "properties": {
          "skills": {
            "type": "integer"
          },
          "authors": {
            "type": "integer"
          },
          "kits": {
            "type": "integer"
          },
          "devices": {
            "type": "integer"
          }
        }
      },
      "ModerationLog": {
        "type": "object",
        "properties": {
          "actions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "target": {
                  "type": "string",
                  "description": "Skill id or handle acted on."
                },
                "action": {
                  "type": "string",
                  "description": "What was applied, e.g. `unlisted`."
                },
                "reason": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "created_at": {
                  "type": "integer"
                }
              },
              "required": [
                "target",
                "action"
              ]
            }
          }
        },
        "required": [
          "actions"
        ]
      },
      "WhoAmI": {
        "type": "object",
        "properties": {
          "authenticated": {
            "type": "boolean"
          },
          "handle": {
            "type": [
              "string",
              "null"
            ]
          },
          "user_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "token_class": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "session",
              "device",
              "kit",
              "mcp",
              null
            ]
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "read",
                "sync",
                "publish",
                "claim"
              ]
            },
            "description": "The scopes this token grants."
          }
        },
        "required": [
          "authenticated"
        ]
      },
      "SyncManifest": {
        "type": "object",
        "properties": {
          "skills": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "skill_id": {
                  "type": "string"
                },
                "hash": {
                  "type": "string",
                  "description": "Approved content hash to materialize."
                },
                "version_label": {
                  "type": "string"
                },
                "source": {
                  "type": "string",
                  "description": "Why this skill is in the manifest (own, kit, subscription)."
                }
              },
              "required": [
                "skill_id",
                "hash"
              ]
            }
          }
        },
        "required": [
          "skills"
        ]
      },
      "JsonRpcRequest": {
        "type": "object",
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "integer",
              "null"
            ]
          },
          "method": {
            "type": "string",
            "examples": [
              "tools/list",
              "tools/call"
            ]
          },
          "params": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "jsonrpc",
          "method"
        ]
      },
      "JsonRpcResponse": {
        "type": "object",
        "properties": {
          "jsonrpc": {
            "type": "string",
            "const": "2.0"
          },
          "id": {
            "type": [
              "string",
              "integer",
              "null"
            ]
          },
          "result": {
            "type": "object",
            "additionalProperties": true
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "integer"
              },
              "message": {
                "type": "string"
              },
              "data": {
                "type": "object",
                "additionalProperties": true
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "jsonrpc"
        ]
      }
    }
  }
}