# Skill Template

Complete SKILL.md template with all required sections.

## YAML Frontmatter

```yaml
---
name: skill-slug-name                   # REQUIRED — must match directory name exactly
description: |                           # REQUIRED — 1024 char max
  [WHAT it does — 1-2 sentences]. [WHEN to use it — trigger phrases users
  would actually say]. Use when user says "[phrase 1]", "[phrase 2]", or
  "[phrase 3]". Keep the scope specific enough that adjacent skills do not
  accidentally match.
# Optional top-level fields:
# allowed-tools: [Read, Write, Bash, Grep, Glob]
# compatibility: "Requires Python 3.10+, network access for API calls"
# user-invocable: false
# agent: golang-general-engineer
# model: sonnet
routing:                                 # REQUIRED — must be a mapping
  triggers:                              # REQUIRED — non-empty list
    - keyword1
    - keyword2
  pairs_with:                            # Optional — MUST be under routing:, never top-level
    - related-skill
  complexity: Simple | Medium | Medium-Complex | Complex
  category: language | infrastructure | review | meta | content | voice | code-quality | analysis | testing | process | meta-tooling | git-workflow | frontend | research | security | decision-support | documentation | kubernetes | video-creation | image-generation | kotlin | php | swift | github  # REQUIRED
  # force_route: true                    # Optional — only for skills that must bypass scoring
---
```

**Description Formula**: `[WHAT] + [WHEN] + [capabilities] + [clear scope boundary when needed]`

**Max length**: 1024 characters (Anthropic enforced limit)

### Common Mistakes (Invalid Frontmatter)

These patterns cause validation failures and silent routing breakage:

```yaml
# WRONG: pairs_with at top level (must be under routing:)
---
name: my-skill
description: "Does something."
pairs_with:                    # ERROR — this belongs under routing:
  - other-skill
routing:
  triggers: [my skill]
  category: engineering
---

# WRONG: force_routing instead of force_route
---
name: my-skill
description: "Does something."
routing:
  triggers: [my skill]
  category: engineering
  force_routing: true          # ERROR — use force_route, not force_routing
---

# WRONG: missing routing: wrapper
---
name: my-skill
description: "Does something."
triggers:                      # ERROR — triggers must be under routing:
  - my skill
category: engineering          # ERROR — category must be under routing:
---
```

Validate after writing: `python3 scripts/validate-skill-frontmatter.py skills/<name>/SKILL.md`

**Triggering note**: Claude tends to "undertrigger" skills — not invoking them when they'd be helpful. To combat this, make descriptions slightly assertive. Instead of just stating what the skill does, explicitly list trigger contexts. Example: "Make sure to use this skill whenever the user mentions X, Y, or Z, even if they don't explicitly ask for it."

**Good descriptions**:
```yaml
# Specific with trigger phrases
description: |
  Analyzes Figma design files and generates developer handoff documentation.
  Use when user uploads .fig files, asks for "design specs", "component
  documentation", or "design-to-code handoff".

# Clear scope without wasted prohibition text
description: |
  Advanced data analysis for CSV files. Use for statistical modeling,
  regression, clustering, and significance testing on tabular data.
```

**Bad descriptions**:
```yaml
# Too vague — won't trigger
description: Helps with projects.

# Missing triggers — Claude can't determine when to load
description: Creates sophisticated multi-page documentation systems.

# Too broad — will overtrigger on everything
description: Processes documents.
```

### Verifying Description Triggering

After writing a description, mentally test it against 3-5 prompts:
- 2-3 prompts that **should** trigger the skill (including indirect/casual phrasing)
- 2-3 prompts that **should not** trigger (near-misses from adjacent domains)

If the description wouldn't clearly match the should-trigger prompts, it's too vague. If it would match the should-not-trigger prompts, tighten the scope language.

For important skills, consider creating a small eval set:
```json
[
  {"query": "realistic user prompt here", "should_trigger": true},
  {"query": "similar but wrong domain prompt", "should_trigger": false}
]
```
Use realistic prompts with detail (file paths, context, casual phrasing) — not abstract one-liners. Test edge cases where the skill competes with adjacent skills.

## Audience Awareness

Consider who will use the skill. Claude Code users range from experienced engineers to people new to terminals. Adjust terminology accordingly:

| Audience Signal | Approach |
|-----------------|----------|
| User writes code, uses CLI fluently | Technical terms fine (assertions, JSON schemas, middleware) |
| User follows tutorials, asks about basics | Briefly define technical terms on first use |
| No clear signal | Default to clear language, define terms that aren't universally known |

In skill instructions, explain jargon if the skill might serve a broad audience. For domain-specific skills (go-patterns, kubernetes-helm), assume domain competence.

## File Structure

```
.claude/skills/[skill-name]/
├── SKILL.md           # Manifest (YAML + instructions) - REQUIRED, exact case
├── SPEC.md            # Optional: contract for complex/high-impact skills
├── EVAL.md            # Optional: repeatable behavior/routing eval cases
├── scripts/           # Deterministic operations
│   ├── main.py       # Primary script
│   └── validate.py   # Testing/validation
├── references/        # Static context (anti-rot)
│   └── examples.md   # Usage examples
└── assets/            # Templates, fonts, icons used in output
    └── template.md   # Output templates
```

### Critical Naming Rules

| Rule | Correct | Incorrect |
|------|---------|-----------|
| SKILL.md must be exact (case-sensitive) | `SKILL.md` | `SKILL.MD`, `skill.md`, `Skill.md` |
| Folder name: kebab-case only | `deploy-pipeline` | `Deploy Pipeline`, `deploy_pipeline`, `DeployPipeline` |
| Name field must match folder | `name: deploy-pipeline` | Mismatched name/folder |
| No README.md inside skill folder | All docs in `SKILL.md` or `references/` | `README.md` inside skill folder |

### Optional Maintenance Artifacts

Create `SPEC.md` and `EVAL.md` for Complex skills, security-sensitive skills,
router-facing skills, PR/release workflows, and skills expected to be iterated
over time. Skip them for small one-purpose skills where the SKILL.md and tests
already express the contract.

`SPEC.md` should contain:
- Purpose and scope
- Non-goals and boundaries
- Required inputs and outputs
- Invariants the skill must preserve
- Dependencies on scripts, agents, references, hooks, or external tools
- Success criteria

`EVAL.md` should contain:
- Should-trigger and should-not-trigger prompts
- Representative execution prompts
- Expected behavior or output properties
- Known failure modes
- Deterministic checks or reviewer rubric

`SPEC.md` and `EVAL.md` are maintenance context, not runtime context. Do not add
ordinary execution instructions that tell the model to read them. They are loaded
when creating, evaluating, redesigning, or modifying the skill.

Do not create `SOURCES.md` as a standard artifact. Provenance belongs in docs,
ADRs, citations, or research artifacts when it matters; it should not become
default component context.

### Security Rules

| Rule | Reason |
|------|--------|
| **No XML angle brackets (`<` `>`) in frontmatter** | Frontmatter appears in Claude's system prompt; could inject instructions |
| **No "claude" or "anthropic" in skill name** | Reserved namespace |
| **No code execution in YAML** | Safe YAML parsing enforced |
| **No secrets in frontmatter or SKILL.md** | Skills are shared; secrets go in environment variables |

### Bundled Agents (Optional)

For Complex+ skills that spawn subagents with specialized roles, agent prompts can be bundled inside the skill:

```
skill-name/
├── SKILL.md
├── agents/          # Purpose-built agent prompts for this skill
│   ├── grader.md    # Evaluates outputs against criteria
│   └── analyzer.md  # Post-hoc analysis of results
├── scripts/
└── references/
```

**When to bundle agents vs use repo-level agents:**

| Scenario | Approach |
|----------|----------|
| Agent is only used by this skill | Bundle in `agents/` — keeps skill self-contained |
| Agent is shared across skills | Keep in repo `agents/` directory — avoid duplication |
| Agent needs routing metadata | Keep in repo `agents/` — routing requires top-level registration |

Bundled agents are referenced from SKILL.md: "Spawn a subagent using the prompt in `agents/grader.md`". They don't appear in the routing system — they're internal to the skill's workflow.

## Instructions Section

Constraints belong **inline** within the workflow step where they apply, not in a
separate `## Operator Context` block. If a constraint matters during Phase 2, put
it in Phase 2 — not in a preamble 200 lines above where the model encounters it.
Explain the reasoning alongside each constraint (see "Motivation over Mandate" below).

```markdown
## Instructions

### Overview

[2-3 sentences: what this skill does and how it works end-to-end]

### Phase 1: [First Phase Name]

[What to do here — goal and actions]

Run: `python3 ~/.claude/scripts/main.py --input {input_file}`
Expect: [Specific output format]

Gate: [Condition that must be true before moving to Phase 2]
— because [reason the gate exists]

### Phase 2: [Second Phase Name]

[What to do here]

Constraint: [Domain-specific rule that applies HERE]
— because [why this matters in this context]

> If SKILL.md exceeds 500 lines: extract detailed content to `references/`
> and add a one-liner here: "See `references/X.md` for the full [checklist/rubric/template]."

### Phase 3: [Output Phase]

[Produce the output artifact]

## Error Handling

**Error: "[Error message]"**
- Cause: [Why it happens]
- Solution: [How to fix]

## Reference Files
- `references/examples.md`: [Purpose — loaded only when this skill executes]
- `references/checklist.md`: [Phase 2 checklist — deep content extracted from SKILL.md]
```

### Best Practices for Instructions

| Rule | Why |
|------|-----|
| **Be specific and actionable** | `Run python scripts/validate.py --input {file}` beats "validate the data" |
| **Put critical instructions at the top** | Use `## Critical` or `## Important` headers |
| **Use bullet points and numbered lists** | Structured content is followed more reliably than paragraphs |
| **Use code over language for validation** | Code is deterministic; language interpretation isn't |
| **Reference bundled resources clearly** | "Before writing queries, consult `references/api-patterns.md`" |
| **Include error handling** | Common errors with cause/solution format |
| **Repeat key points if needed** | Critical instructions may need reinforcement |
| **Explain the why, not just the what** | See "Motivation over Mandate" below |

### Motivation over Mandate

LLMs follow instructions better when they understand the reasoning behind them. For every constraint or rule in a skill, prefer explaining **why** it matters alongside the directive.

**Yellow flag**: Pair every capitalized imperative (ALWAYS, MUST) with reasoning. The model generalizes better to edge cases when it understands the "because" behind a rule.

| Pattern | Less Effective | More Effective |
|---------|---------------|----------------|
| Constraint | `Remove console.log before shipping` | `Remove console.log before shipping — it blocks the event loop on high-throughput paths and leaks internal state to browser devtools` |
| Requirement | `ALWAYS validate inputs before processing` | `Validate inputs before processing because malformed data at this boundary propagates silently through 3 downstream services` |
| Gate | `MUST pass lint before committing` | `Pass lint before committing — the CI will reject it anyway, and fixing lint after commit creates noisy fix-lint commits in the PR` |

This doesn't mean abandoning imperative constraints — gates, anti-rationalization tables, and blocker criteria still serve an important purpose as safety nets. The principle is: **explain the why AND enforce the gate**. Motivation makes the model follow willingly; gates catch the cases where it doesn't.

Think of it as two layers:
1. **Motivation** (soft): Explain why something matters so the model internalizes the intent
2. **Gate** (hard): Verify the outcome so failures are caught regardless of intent

## Shared Patterns Integration

All skills should reference appropriate shared patterns:

```markdown
## References

This skill uses these shared patterns:
- [Anti-Rationalization](../shared-patterns/anti-rationalization-core.md) - Prevents shortcut rationalizations
- [Verification Checklist](../shared-patterns/verification-checklist.md) - Pre-completion checks
- [Gate Enforcement](../shared-patterns/gate-enforcement.md) - Phase transitions (for workflow skills)

### Domain-Specific Anti-Rationalization

See [anti-rationalization-core.md](../shared-patterns/anti-rationalization-core.md) for universal patterns.

Additional for this skill:

| Rationalization Attempt | Why It's Wrong | Required Action |
|------------------------|----------------|-----------------|
| [domain-specific-1] | [reason] | [action] |
| [domain-specific-2] | [reason] | [action] |
```

**Pattern Selection Guide:**

| Skill Type | Include These Patterns |
|------------|----------------------|
| Implementation | anti-rationalization-core, verification-checklist, gate-enforcement |
| Review/Analysis | anti-rationalization-core, anti-rationalization-review, severity-classification |
| Testing | anti-rationalization-core, anti-rationalization-testing |
| Security | anti-rationalization-core, anti-rationalization-security |
| Workflow | gate-enforcement, pressure-resistance, execution-report-format |

## Preferred Patterns Section (Medium+)

For skills with significant complexity, include 3-6 failure modes.

**Pairing rule (mandatory):** Every pattern block must include a "Do instead" counterpart that shows the correct approach. A bare negative ("don't do X") encodes no actionable knowledge. The positive counterpart is the actual learning. If a genuine absolute prohibition has no correct alternative (e.g., "never commit secrets"), annotate it with `<!-- no-pair-required: absolute prohibition, no safe alternative -->` to pass structural validation.

Validation gate: `python3 scripts/validate-references.py --check-do-framing` rejects failure mode blocks without a paired "Do instead" or `<!-- no-pair-required: ... -->` annotation.

```markdown
### Pattern 1: [Pattern Name]

**What it looks like:**
[Example of misuse]

**Why wrong:** [Consequence]

**Do instead:** [Correct approach — this field is mandatory]
```
