Skip to main content

Spec Validator API

The Spec Validator validates rendered SKILL.md files against the agentskills.io specification. It ensures generated skills conform to the required format and metadata standards.

Validation Rules

The validator checks:
  • Name: kebab-case, max 64 chars, matches ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$
  • Description: max 1024 chars, required
  • allowed-tools: must be a YAML list (not comma-separated string)
  • version: must be present (warning if missing)
  • Frontmatter: valid YAML between --- delimiters

Functions

validateSkillMd

Validate a SKILL.md file content against the agentskills.io spec.
function validateSkillMd(content: string): SpecValidationResult
content
string
required
The full SKILL.md file content including frontmatter
Returns: SpecValidationResult with any violations found

Example

import { validateSkillMd } from "auto-skill/core/spec-validator";
import fs from "node:fs";

const skillContent = fs.readFileSync("my-skill.md", "utf-8");
const result = validateSkillMd(skillContent);

if (result.isValid) {
  console.log("✓ Skill is valid");
} else {
  console.log("✗ Validation failed:");
  for (const error of result.errors) {
    console.log(`  ${error.field}: ${error.message}`);
  }
}

if (result.warnings.length > 0) {
  console.log("Warnings:");
  for (const warning of result.warnings) {
    console.log(`  ${warning.field}: ${warning.message}`);
  }
}

extractFrontmatter

Extract and parse YAML frontmatter from SKILL.md content.
function extractFrontmatter(
  content: string
): Record<string, unknown> | null
content
string
required
The full SKILL.md file content
Returns: Record<string, unknown> | null - Parsed frontmatter object or null if not found/invalid

Example

import { extractFrontmatter } from "auto-skill/core/spec-validator";

const skill = `---
name: my-skill
description: Does something useful
version: 1.0.0
allowed-tools:
  - Read
  - Write
---

# My Skill

Skill content here...`;

const fm = extractFrontmatter(skill);
console.log(fm?.name); // "my-skill"
console.log(fm?.version); // "1.0.0"
console.log(fm?.["allowed-tools"]); // ["Read", "Write"]

Classes

SpecValidationResult

Result of spec validation. Collects violations (errors and warnings) found during validation.
class SpecValidationResult {
  violations: SpecViolation[];
  
  get isValid(): boolean;
  get errors(): SpecViolation[];
  get warnings(): SpecViolation[];
  
  addError(field: string, message: string): void;
  addWarning(field: string, message: string): void;
}

Properties

violations
SpecViolation[]
required
All violations (errors and warnings) found during validation
isValid
boolean
required
True if no error-level violations exist (read-only getter)
errors
SpecViolation[]
required
All error-level violations (read-only getter)
warnings
SpecViolation[]
required
All warning-level violations (read-only getter)

Methods

addError
(field: string, message: string) => void
required
Add an error-level violation
addWarning
(field: string, message: string) => void
required
Add a warning-level violation

Example

import { SpecValidationResult } from "auto-skill/core/spec-validator";

const result = new SpecValidationResult();

result.addError("name", "Name exceeds 64 chars");
result.addWarning("version", "Missing 'version' field");

console.log(result.isValid); // false (has errors)
console.log(result.errors.length); // 1
console.log(result.warnings.length); // 1

Types

SpecViolation

A single spec violation.
interface SpecViolation {
  field: string;
  message: string;
  severity: "error" | "warning";
}
field
string
required
The frontmatter field that violated the spec (e.g., “name”, “description”, “allowed-tools”)
message
string
required
Human-readable description of the violation
severity
'error' | 'warning'
required
Violation severity. Errors prevent skill activation, warnings are informational.

Constants

MAX_DESCRIPTION_LENGTH

Maximum description length per agentskills.io spec.
const MAX_DESCRIPTION_LENGTH: number = 1024

Validation Examples

Valid Skill

---
name: debug-test-failure
description: Analyze test failures and suggest fixes
version: 1.0.0
allowed-tools:
  - Read
  - Grep
  - Bash
---

# Debug Test Failure

When tests fail, this skill helps identify the root cause...
Result: isValid = true, no violations

Invalid Name

---
name: Debug_Test_Failure
description: Analyze test failures
---
Result: isValid = false Error: name: Name 'Debug_Test_Failure' does not match spec regex ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$

Missing Description

---
name: debug-test
---
Result: isValid = false Error: description: Missing required field 'description'

Invalid allowed-tools

---
name: debug-test
description: Debug tests
allowed-tools: Read, Grep, Bash
---
Result: isValid = false Error: `allowed-tools: Must be a YAML list, not a comma-separated string. Use: allowed-tools:
  • Tool1
  • Tool2`

Missing Version (Warning)

---
name: debug-test
description: Debug tests
---
Result: isValid = true (warnings don’t fail validation) Warning: version: Missing 'version' field (recommended by spec)

Description Too Long

---
name: debug-test
description: <1025+ character description>
---
Result: isValid = false Error: description: Description exceeds 1024 chars (got 1025)

Common Violations

ViolationSeverityHow to Fix
Missing frontmatterErrorAdd --- delimiters at start of file
Invalid YAMLErrorCheck YAML syntax (indentation, quotes)
Missing nameErrorAdd name: skill-name to frontmatter
Invalid name formatErrorUse lowercase kebab-case (a-z, 0-9, hyphens)
Name too longErrorKeep name under 64 characters
Missing descriptionErrorAdd description: ... to frontmatter
Description too longErrorKeep description under 1024 characters
allowed-tools as stringErrorUse YAML list syntax, not comma-separated
Missing versionWarningAdd version: 1.0.0 (recommended)

Integration

The Spec Validator is automatically used by Auto-Skill’s skill generator:
import { validateSkillMd } from "auto-skill/core/spec-validator";
import { safeWrite } from "auto-skill/core/path-security";

function generateSkill(content: string, outputPath: string): void {
  // Validate before writing
  const validation = validateSkillMd(content);
  
  if (!validation.isValid) {
    throw new Error(
      `Invalid skill: ${validation.errors.map(e => e.message).join(", ")}`
    );
  }
  
  // Write validated skill
  safeWrite(content, outputPath, "/allowed/skills/dir");
}

Build docs developers (and LLMs) love