SKILL.md Reference

Complete reference for the SKILL.md file format, frontmatter fields, and tool permissions

File Format

A SKILL.md file has two parts: YAML frontmatter (metadata) and a markdown body (agent instructions). The frontmatter is enclosed between --- delimiters.

SKILL.md
---
name: code-review
description: Automated code review with best practices
version: 1.0.0
tags:
  - review
  - quality
allowed-tools: Read, Edit
---

# Code Review

When reviewing code, follow these guidelines...

Required Fields

FieldTypeDescription
namestringUnique identifier. Must start with a letter or number. Alphanumeric characters, spaces, hyphens, and underscores only. Max 256 characters.
descriptionstringBrief one-line summary of what the skill does. Max 4096 characters. This appears in search results and skill listings.

Optional Fields

FieldTypeDescription
versionstringSemantic version (e.g., "1.0.0"). Helps users track updates.
authorstringYour name or handle.
tagsstring[]Categorization tags for search and discovery.
agentsstring[]Compatible agents (e.g., ["claude", "cursor", "codex"]).
licensestringLicense identifier (e.g., "MIT", "Apache-2.0").
compatibilitystringCompatibility notes (e.g., language requirements). Max 500 characters.
allowed-toolsstringList of tools the skill needs. Can be a comma-separated string (e.g., "Bash, Read, Edit") or a YAML list. Declaring this helps users understand the skill's security surface area.
metadataobjectArbitrary key-value pairs for custom metadata.

Content Body

The markdown body after the frontmatter is what the AI agent reads and follows. This is where you write the instructions, examples, and guidelines.

Structure your content with clear headers:

Recommended structure
# Skill Name

Brief overview of what this skill does and when to use it.

## Guidelines

Specific rules and patterns to follow.

## Examples

### Good
```typescript
// Show the desired pattern
```

### Avoid
```typescript
// Show what NOT to do
```

## Edge Cases

Special situations and how to handle them.
Agents process markdown natively. Use code blocks, lists, and headers to organize instructions. The more structured your content, the more consistently the agent will follow it.

Declaring Tool Permissions

The allowed-tools field declares which tools your skill needs. This is important for transparency — users can see what a skill will do before installing it. The platform audit also uses this field for security scoring.

ToolRisk LevelDescription
ReadLowRead file contents. Generally safe.
EditLowModify existing files. Cannot create new files.
WriteMediumCreate or overwrite files.
BashHighRun shell commands. Most powerful and most scrutinized.
Only request tools your skill actually needs. Skills requesting Bash access receive extra scrutiny during audit and users will be more cautious about installing them.

Complete Example

testing-helper/SKILL.md
---
name: testing-helper
description: Generate comprehensive test suites following TDD best practices
version: 1.2.0
author: Jane Developer
tags:
  - testing
  - tdd
  - quality
agents:
  - claude
  - cursor
license: MIT
allowed-tools: Read, Edit, Write
---

# Testing Helper

When asked to write or improve tests, follow these guidelines.

## Structure

- Group related tests in describe/context blocks
- Use descriptive names: `test_<function>_<scenario>_<expected>`
- Follow Arrange-Act-Assert (AAA) pattern

## Coverage Priorities

1. Happy path — verify the main use case works
2. Edge cases — null, undefined, empty, boundary values
3. Error scenarios — verify error messages and types
4. Integration points — mock external dependencies

## Examples

### Good test
```typescript
describe("UserService.create", () => {
  it("returns the created user with generated ID", async () => {
    const input = { name: "Alice", email: "alice@example.com" };
    const user = await service.create(input);
    expect(user.id).toBeDefined();
    expect(user.name).toBe("Alice");
  });

  it("throws ValidationError for duplicate email", async () => {
    await service.create({ name: "A", email: "dup@test.com" });
    await expect(
      service.create({ name: "B", email: "dup@test.com" })
    ).rejects.toThrow(ValidationError);
  });
});
```

### Avoid
```typescript
// Too vague, no assertion context
test("works", async () => {
  const result = await service.create({ name: "A", email: "a@b.com" });
  expect(result).toBeTruthy();
});
```