Skip to main content

SKILL.md format

Every skill is a single Markdown file with YAML frontmatter and a body. The parser at internal/skills/parser.go is the source of truth; this page documents every accepted field and the validation rules around it.

Frontmatter fields

Unknown frontmatter fields are silently ignored (log line in the importer).

Body sections

The body is plain Markdown. The bundled skills use a five-section pattern; agents do not require it but it makes review and search predictable:
  1. ## When to use — restate the trigger phrase, list one example that should fire and one near-miss that should not. The LLM relies on this far more than on the frontmatter description.
  2. ## Steps — the agent’s playbook. Concrete, ordered, action-oriented.
  3. ## Output format — what the agent should return. Be specific (JSON shape, exact phrase, table columns) — vague output sections cause the agent to drift.
  4. ## Guardrails — what the agent must NOT do. Always include at least one concrete negative.
  5. ## Verification (optional) — how a human can spot-check whether the skill produced the right thing.

What gets stripped

  • Backtick-prefixed dynamic-context blocks !\cmd“ are removed before storage. Claude Code shells out for these at load time; allowing them in a multi-tenant skill registry would be a remote-execution vector.
  • Frontmatter values that fail the slug / enum guards trigger a parser fallback (logged) rather than a hard reject — same compatibility posture as the rest of the importer.

SPDX allowlist

The license gate accepts:
Anything else (including GPL-3.0, AGPL-3.0, no-license, “Complete terms in LICENSE.txt”) is rejected unless the operator passes --unsafe-license. The raw value is preserved in the license column for audit; the canonicalised SPDX id, if any, is written to spdx_license.

Prompt-injection scanner

Every imported body runs through ScanContent (internal/skills/safety.go). Patterns it flags:
  • “ignore / disregard / forget previous / prior / earlier instructions”
  • Pseudo-tag role hijacks (<system>, <|im_start|>, new instructions: ignore …)
  • “reveal the system prompt”
  • “DAN” jailbreak markers
  • Large base64 blobs (≥ 1024 contiguous base64 chars) — used to smuggle payloads past human review.
A FLAGGED skill is still inserted into the registry (so operators can investigate) but the reason is recorded in description_quality and the UI surfaces a warning chip. Operators should review and crewship skill delete confirmed-malicious imports.

Minimum viable SKILL.md

If you’re starting from crewship skill init and want the shortest path to a working skill:
That parses, passes the SPDX gate, scans clean, and lands in the registry as scan_status=CLEAN, maturity=COMMUNITY, runtime=INSTRUCTIONS.