{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://catalog.lintel.tools/schemas/claude-code/skill/latest.json",
  "title": "Claude Code Skill",
  "description": "Frontmatter schema for [Claude Code skill](https://code.claude.com/docs/en/skills) definitions (`.claude/skills/*/SKILL.md` or `.claude/skills/*.md`). Skills extend Claude with reusable knowledge, workflows, and slash commands following the [Agent Skills](https://agentskills.io) open standard. The markdown body after the `---` frontmatter becomes the skill's content, injected into Claude's context when triggered. Use `$ARGUMENTS`, `$ARGUMENTS[N]`, or `$N` for argument substitution, and `` !`command` `` for [dynamic context injection](https://code.claude.com/docs/en/skills#inject-dynamic-context). Skills are stored at `~/.claude/skills/` (personal), `.claude/skills/` (project), or `<plugin>/skills/` (plugin). When skills share the same name across levels, higher-priority locations win: enterprise > personal > project. Plugin skills use a `plugin-name:skill-name` namespace.",
  "x-lintel": {
    "source": "https://raw.githubusercontent.com/lintel-rs/catalog/master/schemas/claude-code/skill.json",
    "sourceSha256": "4ab3209299589fe431ccaa9d95678748e3087adc6892fb87868c8795dcc6f6fd",
    "fileMatch": [
      "**/skills/*/SKILL.md",
      "**/skills/*.md",
      ".claude/skills/*.md"
    ],
    "parsers": [
      "markdown"
    ],
    "catalogDescription": "Frontmatter for Claude Code skill definitions."
  },
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Display name for the skill using lowercase letters, numbers, and hyphens only (max 64 characters). This becomes the `/slash-command` name (e.g. `name: review-code` creates `/review-code`). If omitted, defaults to the directory or file name. Plugin skills are namespaced as `/plugin-name:skill-name`.",
      "pattern": "^[a-z0-9][a-z0-9-]*$",
      "maxLength": 64,
      "examples": [
        "review-code",
        "fix-issue",
        "api-conventions"
      ]
    },
    "description": {
      "type": "string",
      "description": "Describes what the skill does and when to use it. Claude uses this to decide when to automatically load the skill, so write it as a **triggering guide** — include concrete examples of user requests that should activate it (e.g. *\"Use when the user asks to review code\"*). Skill descriptions are always loaded into Claude's context so it knows they exist, but full skill content only loads when invoked. If omitted, defaults to the first paragraph of the markdown body. Note: descriptions share a context budget (2% of the context window, minimum 16KB). Override with the `SLASH_COMMAND_TOOL_CHAR_BUDGET` environment variable. Run `/context` to check for a warning about excluded skills.",
      "examples": [
        "Reviews code for quality, security, and best practices. Use when analyzing code changes or when the user asks for a review.",
        "Fix a GitHub issue by number. Use when the user provides an issue number to resolve.",
        "Coding conventions and API patterns for this project. Applied automatically when writing new code."
      ]
    },
    "argument-hint": {
      "type": "string",
      "description": "Hint shown during `/` autocomplete to indicate expected arguments. Purely cosmetic — does not enforce argument structure. Arguments are accessed via `$ARGUMENTS` (all args), `$ARGUMENTS[N]` or `$N` (positional, 0-based) in the markdown body. If `$ARGUMENTS` is not present in the content, arguments are appended as `ARGUMENTS: <value>`.",
      "examples": [
        "[issue-number]",
        "[filename] [format]",
        "[component-name]"
      ]
    },
    "model": {
      "type": "string",
      "description": "Which [Claude model](https://code.claude.com/docs/en/model-config) to use when this skill is active. If omitted, inherits from the current session.",
      "examples": [
        "sonnet",
        "opus",
        "haiku"
      ]
    },
    "allowed-tools": {
      "description": "Tools Claude can use **without asking permission** when this skill is active. Built-in tools: `Read`, `Write`, `Edit`, `Bash`, `Glob`, `Grep`, `WebFetch`, `WebSearch`, `Task`, `Skill`. Supports patterns like `Bash(git *)` to allow only specific subcommands, `Bash(npm run *)` to scope shell access, or `Skill(commit)` to allow invoking a specific skill. MCP tools use the pattern `mcp__<server>__<tool>`. If omitted, all tools are available with normal [permission prompts](https://code.claude.com/docs/en/permissions). This field only grants auto-approval — it does **not** override denials set in the user's permission settings.",
      "oneOf": [
        {
          "type": "string",
          "description": "Comma-separated list of tool names. Supports patterns like `Bash(git *)`."
        },
        {
          "type": "array",
          "items": {
            "$ref": "https://catalog.lintel.tools/schemas/claude-code/permission/latest.json"
          },
          "description": "Array of tool names."
        }
      ],
      "examples": [
        "Read, Grep, Glob, Bash",
        "Read, Edit, Bash(npm run *)",
        [
          "Read",
          "Grep",
          "Glob",
          "Bash(git *)"
        ]
      ]
    },
    "disable-model-invocation": {
      "type": "boolean",
      "description": "When `true`, prevents Claude from automatically loading this skill based on its description — the skill's description is **not** included in Claude's context, so Claude will never know it exists unless the user invokes it. The skill can only be triggered manually via its `/slash-command`. Use for manual-only workflows like `/deploy` or `/commit` where automatic triggering would be disruptive. See [control who invokes a skill](https://code.claude.com/docs/en/skills#control-who-invokes-a-skill).",
      "default": false,
      "examples": [
        true
      ]
    },
    "user-invocable": {
      "type": "boolean",
      "description": "When `false`, hides the skill from the `/` autocomplete menu so users cannot invoke it directly via slash command. The skill can still be loaded automatically by Claude based on its description. Use for background knowledge that Claude should apply silently — for example, coding conventions or project-specific patterns. Note: this only controls menu visibility, not `Skill` tool access. Use `disable-model-invocation: true` to block programmatic invocation. See [control who invokes a skill](https://code.claude.com/docs/en/skills#control-who-invokes-a-skill).",
      "default": true,
      "examples": [
        false
      ]
    },
    "context": {
      "type": "string",
      "description": "Set to `fork` to run the skill in an isolated [subagent](https://code.claude.com/docs/en/sub-agents) context instead of inline. When forked, the skill's markdown body becomes the subagent's **task prompt** (not reference material). The subagent runs in a separate conversation fork with its own context window — it does **not** have access to the main conversation history. Tool calls and output from the forked skill do not appear in the main session. Use for heavy workflows (running test suites, large refactors) where inline execution would clutter the conversation. See [run skills in a subagent](https://code.claude.com/docs/en/skills#run-skills-in-a-subagent).",
      "enum": [
        "fork"
      ],
      "examples": [
        "fork"
      ]
    },
    "agent": {
      "type": "string",
      "description": "Which subagent type to use when `context` is set to `fork`. Built-in types: `Explore` (read-only, optimized for codebase exploration using Glob, Grep, Read), `Plan` (read-only, for designing implementation plans), `general-purpose` (full-capability agent with all tools). Can also be the name of a custom agent defined in `.claude/agents/`. Ignored if `context` is not `fork`. Defaults to `general-purpose`. See [built-in subagents](https://code.claude.com/docs/en/sub-agents#built-in-subagents).",
      "examples": [
        "Explore",
        "Plan",
        "general-purpose",
        "my-custom-agent"
      ]
    },
    "hooks": {
      "$ref": "https://catalog.lintel.tools/schemas/claude-code/hooks/latest.json",
      "description": "Lifecycle [hooks](https://code.claude.com/docs/en/hooks) scoped to this skill. Hooks defined here only fire when this skill is active and are cleaned up when the skill is unloaded. Each key is an event name and its value is an array of matcher groups. See [hooks in skills and agents](https://code.claude.com/docs/en/hooks#hooks-in-skills-and-agents)."
    }
  },
  "additionalProperties": false,
  "required": [
    "name"
  ]
}
