---
name: skill-frontmatter-schema
description: Phase A frontmatter contract for SKILL.md files indexed by minion-skills-indexer. Additive — does not break Anthropic's two-field minimum.
---

# SKILL.md Frontmatter Contract — Phase A

## Required (Anthropic minimum, unchanged)

| Key | Type | Notes |
|---|---|---|
| `name` | string | URL-safe slug, must match parent dir name |
| `description` | string | One-liner, ~150 chars, used by Level-1 progressive disclosure |

## Optional — existing

| Key | Type | Notes |
|---|---|---|
| `homepage` | string (URL) | Reference link, not consumed by gateway |
| `metadata.minion.emoji` | string | UI hint |
| `metadata.minion.requires.bins` | string[] | Required binaries on PATH |
| `metadata.minion.install` | object[] | Install recipes (brew, npm, apt, etc.) |
| `metadata.minion.primaryEnv` | string | Env var that gates the skill |

## Optional — Phase A additions (all NEW, free to omit)

| Key | Type | Used by | Notes |
|---|---|---|---|
| `category` | string | indexer, query | Single top-level bucket: `auth`, `comms`, `media`, `infra`, `data`, `dev`, `meta`, `lifestyle`. Pick the most prominent if multi-fit. |
| `tags` | string[] | query, role-library | Free-form descriptors. Examples: `["secrets","cli","apple"]`. Used for tag-based filtering. |
| `keywords` | string[] | query | Synonyms/alt-names. Helps search match user phrasings the description doesn't cover. Example for `1password`: `["op","secrets-manager","vault","keychain"]`. |
| `related` | string[] | query, indexer | Skill slugs that compose well with this one. Bidirectional discoverability. Example for `slack`: `["discord","gh-issues"]`. |
| `roles` | string[] | role-library (Phase B) | Role IDs that default-include this skill. Example: `["communications","support"]`. |

## Format rules (loader contract — do NOT violate)

1. **YAML opener `---` MUST be on line 1.** No HTML comments, prose, or whitespace before it. The loader silently skips skills with non-line-1 frontmatter.
2. **Skill dir name MUST equal `name` field.** The loader uses dir name as canonical lookup; mismatches cause shadow loads or invisible skills.
3. **Custom guidance goes AFTER closing `---`,** never inside frontmatter as comments.
4. No backups (`.bak`, `.old`) inside the skill dir — move them out.

## Example — fully specified (for backfill reference)

```yaml
---
name: 1password
description: Set up and use 1Password CLI (op). Use when installing the CLI, enabling desktop app integration, signing in, or reading/injecting/running secrets via op.
homepage: https://developer.1password.com/docs/cli/get-started/
category: auth
tags: [secrets, cli, vault]
keywords: [op, secrets-manager, vault, keychain, password-manager]
related: [1password-secrets, gh-issues]
roles: [security, devops]
metadata:
  minion:
    emoji: "🔐"
    requires:
      bins: [op]
    install:
      - id: brew
        kind: brew
        formula: 1password-cli
        bins: [op]
        label: Install 1Password CLI (brew)
---
```

## Index output

The indexer (`bin/skills-indexer.mjs`) emits `~/.minion/skills.index.json`:

```json
{
  "generated_at": "2026-05-09T...Z",
  "source_count": 6,
  "skills": [
    {
      "name": "1password",
      "source": "openclaw-extra",
      "path": "/home/bot-prd/repos/minion-ai/skills/1password/SKILL.md",
      "description": "...",
      "category": "auth",
      "tags": ["secrets","cli","vault"],
      "keywords": [...],
      "related": [...],
      "roles": [...],
      "homepage": "...",
      "metadata": { "minion": {...} }
    }
  ]
}
```

Later sources override earlier per loader merge precedence (extra → bundled → managed → personal-agents → project-agents → workspace, last wins).
