# RFC-0008: Skill Authoring Standard
> **Version:** 0.2.1 | **Status:** normative | **Phase:** test
---
## 1. Summary
### [RFC-0008:C-OVERVIEW] Overview (Informative) <a id="rfc-0008c-overview"></a>
This RFC defines the skill authoring standard as a set of configurable lint rules that `skc lint` applies to skill directories.
**Design:**
- Each rule has a unique identifier (SKLxxx)
- Rules are grouped by category (frontmatter, structure, links, files)
- Rules produce diagnostic output per [RFC-0005](../rfc/RFC-0005.md)
- Rules will be configurable in a future version (see [RFC-0008:C-EXTENSIONS](../rfc/RFC-0008.md#rfc-0008c-extensions))
**Rule categories:**
- **SKL1xx**: Frontmatter validation rules
- **SKL2xx**: Structure and content rules
- **SKL3xx**: Link validation rules
- **SKL4xx**: File organization rules
**Relationship to other RFCs:**
- [RFC-0001](../rfc/RFC-0001.md) defines compilation requirements; this RFC extends with quality validation
- [RFC-0005](../rfc/RFC-0005.md) defines diagnostic output format; rules map to diagnostic codes
*Since: v0.1.0*
---
## 2. Specification
### [RFC-0008:C-REGISTRY] Rule Registry (Normative) <a id="rfc-0008c-registry"></a>
This clause defines all lint rules. Each rule has an ID, name, default severity, and description.
## Frontmatter Definition
SKILL.md frontmatter is a YAML block delimited by `---` lines:
- The file MUST begin with a line containing exactly `---`
- The frontmatter ends at the next line containing exactly `---`
- Content between the delimiters is parsed as YAML
Frontmatter validation is handled by rule **SKL100**.
## Rule Summary
| SKL001 | skip-compiled | n/a | Meta |
| SKL100 | frontmatter-valid | error | Frontmatter |
| SKL101 | name-required | error | Frontmatter |
| SKL102 | name-format | error | Frontmatter |
| SKL103 | name-length | error | Frontmatter |
| SKL104 | name-match-dir | warning | Frontmatter |
| SKL105 | description-required | error | Frontmatter |
| SKL106 | description-nonempty | error | Frontmatter |
| SKL107 | description-length | warning | Frontmatter |
| SKL108 | description-triggers | warning | Frontmatter |
| SKL109 | frontmatter-known | warning | Frontmatter |
| SKL201 | skill-size | warning | Structure |
| SKL202 | heading-h1 | warning | Structure |
| SKL203 | heading-match-name | warning | Structure |
| SKL204 | heading-first-h1 | warning | Structure |
| SKL205 | heading-hierarchy | warning | Structure |
| SKL301 | link-file-exists | error | Links |
| SKL302 | link-anchor-exists | warning | Links |
| SKL303 | link-no-escape | error | Links |
| SKL401 | no-orphans | warning | Files |
---
## Meta Rules (SKL0xx)
### SKL001: skip-compiled
Skip linting for compiled skills (detected by `.skillc-meta/manifest.json`).
**Default behavior:** enabled (compiled skills are skipped)
When a compiled skill is detected and this rule is enabled:
1. The linter prints: `info: skipping compiled skill '<name>'`
2. Exits with code 0 (success)
When `--force` is used, this rule is disabled and:
1. The linter emits: `warning[W300]: SKL001 skip-compiled: linting compiled skill; results may not be meaningful`
2. Applies all other rules normally
**Configurability:** Unlike other rules, SKL001 is controlled by `--force`, not by rule configuration. Future versions MAY allow disabling it via config.
**Rationale:** Compiled skills are derived artifacts. Their generated stub differs from source content.
---
## Frontmatter Rules (SKL1xx)
### SKL100: frontmatter-valid
SKILL.md MUST have valid frontmatter delimiters and parseable YAML.
**Default severity:** error
**Requirements:**
- File MUST begin with a line containing exactly `---`
- A second `---` line MUST appear to close the frontmatter
- Content between delimiters MUST be valid YAML
**Error messages:**
- Missing opening delimiter: `missing frontmatter: file does not start with ---`
- Missing closing delimiter: `missing frontmatter: no closing --- found`
- YAML parse error: `invalid frontmatter YAML: <parse-error>`
### SKL101: name-required
The `name` field MUST be present in SKILL.md frontmatter.
**Default severity:** error
### SKL102: name-format
The `name` field MUST contain only lowercase ASCII letters (`a-z`), digits (`0-9`), and hyphens (`-`). It MUST NOT start or end with a hyphen.
**Default severity:** error
**Valid:** `my-skill`, `skill123`, `a`
**Invalid:** `My-Skill` (uppercase), `-skill` (leading hyphen), `skill_name` (underscore)
### SKL103: name-length
The `name` field MUST be 1-64 characters in length.
**Default severity:** error
### SKL104: name-match-dir
The `name` field SHOULD match the skill directory name.
**Default severity:** warning
### SKL105: description-required
The `description` field MUST be present in SKILL.md frontmatter.
**Default severity:** error
### SKL106: description-nonempty
The `description` field MUST NOT be empty or whitespace-only.
**Default severity:** error
### SKL107: description-length
The `description` field SHOULD be at most 1024 characters.
**Default severity:** warning
### SKL108: description-triggers
The `description` field SHOULD include activation triggers.
**Default severity:** warning
**Detection:** The rule checks for presence of any of these English patterns (case-insensitive):
- `use when`
- `when to use`
- `use for`
- `triggers on`
- `triggers:`
- `activate when`
**Note:** This rule is designed for English-language skills. Non-English skills may disable this rule via configuration (future).
### SKL109: frontmatter-known
Frontmatter fields SHOULD be from the known set.
**Default severity:** warning
**Known fields:**
- `name` (required)
- `description` (required)
- `allowed-tools` (optional, implementation-defined behavior)
Unknown fields trigger a warning. This helps catch typos and misunderstandings of the schema.
**Note on `allowed-tools`:** This field is recognized by some agent implementations to restrict available tools. Its format and semantics are implementation-defined. Future versions MAY add validation rules for this field.
---
## Structure Rules (SKL2xx)
### SKL201: skill-size
SKILL.md SHOULD be at most 500 lines.
**Default severity:** warning
### SKL202: heading-h1
SKILL.md SHOULD contain at least one H1 (`#`) heading.
**Default severity:** warning
### SKL203: heading-match-name
The first H1 heading in SKILL.md SHOULD match or contain the skill name.
**Default severity:** warning
**Matching:** Case-insensitive comparison. The heading may contain additional text (e.g., heading "My Skill Guide" matches name "my-skill" if "my-skill" appears as a substring after normalizing hyphens to spaces).
### SKL204: heading-first-h1
The first heading in each markdown file SHOULD be an H1 (`#`).
**Default severity:** warning
**Scope:** Applies to all `.md` files in the skill directory.
**Rationale:** The first heading establishes the document title. Starting with H2 or lower suggests missing context.
*Since: v0.2.0*
### SKL205: heading-hierarchy
Headings SHOULD NOT skip levels when going deeper.
**Default severity:** warning
**Scope:** Applies to all `.md` files in the skill directory.
**Requirements:**
- When increasing heading depth, levels MUST NOT be skipped (H2→H4 is invalid; H2→H3 is valid)
- Decreasing depth is always allowed (H3→H2, H4→H1 are valid)
**Examples:**
- Valid: `# Title` → `## Section` → `### Subsection` → `## Another Section`
- Invalid: `# Title` → `### Subsection` (skipped H2)
- Invalid: `## Section` → `#### Deep` (skipped H3)
**Rationale:** Skipped heading levels break document outline semantics and can cause accessibility issues.
*Since: v0.2.0*
---
## Link Rules (SKL3xx)
### SKL301: link-file-exists
Internal markdown file links MUST resolve to existing files within the skill directory.
**Default severity:** error
**Scope:** Relative links like `[text](path/to/file.md)`. Absolute paths and external URLs are not checked.
### SKL302: link-anchor-exists
Internal markdown anchor links SHOULD resolve to existing headings.
**Default severity:** warning
**Anchor normalization:** GitHub-style slugging for ASCII:
1. Convert to lowercase
2. Remove characters except `a-z`, `0-9`, spaces, hyphens
3. Replace spaces with hyphens
4. Collapse consecutive hyphens
Non-ASCII characters are removed. For duplicate headings, anchors are suffixed: `#heading`, `#heading-1`.
### SKL303: link-no-escape
Links MUST NOT escape the skill root directory via `..` traversal.
**Default severity:** error
---
## File Rules (SKL4xx)
### SKL401: no-orphans
Markdown files in the skill directory SHOULD be reachable from SKILL.md via link traversal.
**Default severity:** warning
**Definition:** A file is orphaned if it is not SKILL.md and is not reachable via links starting from SKILL.md (transitive closure).
**Exceptions:** Not considered orphaned:
- Files in hidden directories (starting with `.`)
- Common non-content files: `LICENSE.md`, `CHANGELOG.md`, `CONTRIBUTING.md`, `README.md`
*Since: v0.1.0*
### [RFC-0008:C-SCOPE] Lint Scope (Normative) <a id="rfc-0008c-scope"></a>
This clause defines what files the linter scans.
## File Scanning
The linter scans all `.md` files in the skill directory, excluding:
- Files in directories starting with `.` (e.g., `.git/`, `.skillc-meta/`, `.github/`)
- Files whose names start with `.`
This is consistent with [RFC-0001](../rfc/RFC-0001.md) compilation behavior.
## Compiled Skill Detection
Compiled skill handling is defined by rule **SKL001** in [RFC-0008:C-REGISTRY](../rfc/RFC-0008.md#rfc-0008c-registry).
Detection: A skill is **compiled** if `.skillc-meta/manifest.json` exists.
## SKILL.md Requirement
The linter requires `SKILL.md` to exist. If missing, the linter exits with E010 per [RFC-0005:C-CODES](../rfc/RFC-0005.md#rfc-0005c-codes).
## Frontmatter Requirement
Frontmatter validation is handled by rule **SKL100** in [RFC-0008:C-REGISTRY](../rfc/RFC-0008.md#rfc-0008c-registry). Invalid frontmatter produces E300 (lint error), not E010.
*Since: v0.1.0*
### [RFC-0008:C-DIAGNOSTICS] Diagnostic Output (Normative) <a id="rfc-0008c-diagnostics"></a>
This clause defines how lint rules produce diagnostic output.
## Output Format
All lint diagnostics use the format defined in [RFC-0005:C-CODES](../rfc/RFC-0005.md#rfc-0005c-codes):
```
<severity>[<code>]: <rule-id> <rule-name>: <message>
```
**Components:**
- `<severity>`: `error` or `warning`
- `<code>`: `E300` for errors, `W300` for warnings
- `<rule-id>`: The rule identifier (e.g., `SKL102`)
- `<rule-name>`: The rule name (e.g., `name-format`)
- `<message>`: Human-readable description of the violation
**Examples:**
```
error[E300]: SKL102 name-format: name 'My-Skill' contains uppercase characters
error[E300]: SKL301 link-file-exists: link target not found: 'references/missing.md'
warning[W300]: SKL104 name-match-dir: name 'foo' does not match directory 'bar'
warning[W300]: SKL401 no-orphans: orphaned file: 'old-notes.md'
```
## Rule Severity Mapping
Each rule has a default severity (error or warning) defined in [RFC-0008:C-REGISTRY](../rfc/RFC-0008.md#rfc-0008c-registry).
| error | E300 |
| warning | W300 |
## Exit Behavior
- If any rule with error severity is violated: exit with status 1
- If only warning-severity rules are violated: exit with status 0
- If no violations: exit with status 0
## Machine-Readable Output
Future versions MAY support structured output formats (JSON, SARIF) for tooling integration. See [RFC-0008:C-EXTENSIONS](../rfc/RFC-0008.md#rfc-0008c-extensions).
*Since: v0.1.0*
### [RFC-0008:C-REFERENCE-FRONTMATTER] Reference File Frontmatter (Informative) <a id="rfc-0008c-reference-frontmatter"></a>
Non-SKILL.md markdown files (reference documents) MAY contain optional YAML frontmatter.
## Frontmatter Format
Reference files MAY begin with a YAML frontmatter block:
```yaml
---
description: "Brief description of this reference document"
---
# Reference Title
Content here...
```
## Supported Fields
| `description` | No | Brief description displayed in compiled stub |
## Field Constraints
**description:**
- Optional (no lint warning if absent)
- Should be ≤120 characters for optimal display
- Longer descriptions are truncated with `…` in the stub
- Used by the compiler per [RFC-0001:C-SECTIONS](../rfc/RFC-0001.md#rfc-0001c-sections)
## Differences from SKILL.md Frontmatter
Reference file frontmatter differs from SKILL.md frontmatter:
| Required | Yes | No |
| `name` field | Required | Not used |
| `description` field | Required | Optional |
| Linting | Full validation | No validation |
## Example
A reference file `references/clap-patterns.md`:
```markdown
---
description: "Advanced clap argument parsing patterns"
---
# Clap Patterns
## Value Enums
...
```
This description appears in the compiled stub:
```
- References
- Clap Patterns — Advanced clap argument parsing patterns
```
*Since: v0.2.0*
---
## 3. Extensions
### [RFC-0008:C-EXTENSIONS] Future Extensions (Informative) <a id="rfc-0008c-extensions"></a>
This clause describes planned future extensions. These are NOT part of v0.2.0.
## Configurable Rules (Future)
A future version MAY support rule configuration via `.skilllint.toml`:
```toml
# Example future configuration (not implemented)
[rules]
SKL107 = "off" # Disable description length check
SKL201 = { max-lines = 300 } # Custom threshold
SKL108 = "error" # Upgrade warning to error
```
**Design considerations:**
- Configuration file location: skill root or global `~/.config/skillc/`
- Per-rule enable/disable
- Severity override (error ↔ warning ↔ off)
- Rule-specific parameters (thresholds, patterns)
## Inline Directives (Future)
A future version MAY support inline directives to suppress warnings:
```markdown
[large content here]
```
Or single-line suppression:
```markdown
[very long line] <!-- skilllint-disable-line SKL... -->
```
## Structured Output (Future)
A future version MAY support machine-readable output:
- `--format=json` — JSON array of violations
- `--format=sarif` — SARIF format for IDE integration
## Additional Rules (Future)
Potential future rules:
- SKL110: `allowed-tools-known` — warn on unrecognized tool names
- SKL206: `code-block-language` — code blocks should have language tags
- SKL207: `line-length` — lines should not exceed threshold
**Note:** These extensions are documented for planning. They are out of scope for v0.2.0.
*Since: v0.1.0*
---
## Changelog
### v0.2.1 (2026-01-31)
Add C-REFERENCE-FRONTMATTER for optional description in reference files
### v0.2.0 (2026-01-31)
Normalize SKL204, SKL205
### v0.1.0 (2026-01-30)
Initial release