Guide for creating effective opencode skills...
Create opencode skills that extend agent capabilities with specialized knowledge and workflows.
| Scope | Path |
|---|---|
| Project | .opencode/skill/<name>/SKILL.md |
| Global | ~/.config/opencode/skill/<name>/SKILL.md |
our-api-patterns, project-deploy)pdf-editor, commit-helper)For project paths, OpenCode walks up from cwd to git worktree root.
skill-name/
├── SKILL.md # Required - frontmatter + instructions
├── scripts/ # Optional - executable code (Python/Bash)
├── references/ # Optional - docs loaded on-demand
└── assets/ # Optional - templates, images, fonts
---
name: skill-name
description: [Self-contained workflow summary — see guidelines below]
---
# Instructions here (markdown body)
Name: Short, hyphen-case identifier. Should be descriptive but concise (max 64 chars).
Description: Agent sees this + the name before loading. Must be self-contained with:
CRITICAL: The description field is the primary trigger mechanism.
Skills are SOPs/workflows, NOT agents. DO NOT use role descriptions like "You are a..." or "[Role] expert."
Before loading, the agent sees only the name and description in <available_skills>:
<available_skills>
<skill>
<name>skill-name</name>
<description>...</description>
</skill>
</available_skills>
The description must be self-contained — agents won't load a skill just to "see what it does."
Name + description should work together:
typescript-advanced)Description pattern (LLM-optimized):
---
name: skill-name
description: |-
[Action verb/capabilities]. Use for [specific cases]. Use proactively when [contexts].
Examples:
- user: "query" → action
- user: "query" → action
---
Dense, machine-parseable, specific. Avoid prose.
CRITICAL YAML SYNTAX: Multi-line descriptions with examples MUST use literal block scalar (|-). The hyphen strips the trailing newline. Do NOT use plain YAML with unquoted colons or lists:
# ❌ WRONG - breaks YAML parsing
description: Handle plugins. Examples:
- user: "..." → action
# ✅ CORRECT - use |- for multi-line
description: |-
Handle plugins.
Examples:
- user: "..." → action
Example:
---
name: typescript-advanced
description: |-
Handle TypeScript 5.9 advanced typing, generics, strict configs, type errors, migrations,
erasable syntax compliance, and test writing. Use proactively for complex generics,
conditional types, utility types, TS compiler config, or test authoring.
Examples:
- user: "Create a type-safe event emitter" → implement with generics and mapped types
- user: "Migrate to strict TypeScript" → add discriminated unions, exhaustive checks
- user: "Build typed API client from OpenAPI" → generate request/response types with inference
- user: "Write unit tests" → create strict, typed tests with realistic fixtures
---
Requirements:
user: "..." → ... examples|- literal block scalar for multi-line descriptions (plain YAML with lists/colons breaks parsing)Reduce redundancy: Don't repeat description content in SKILL.md body.
| Directory | Purpose | When to use |
|---|---|---|
scripts/ |
Reusable Python/Bash code | Same code rewritten repeatedly |
references/ |
Docs, schemas, API specs | Info agent needs while working |
assets/ |
Templates, images, fonts | Files used in output (not loaded) |
MUST NOT include: README.md, CHANGELOG.md, INSTALLATION_GUIDE.md, or other auxiliary docs. Skills contain only what the agent needs to do the job.
The context window is shared. Only add info the agent doesn't already have.
| Freedom Level | Format | Use When |
|---|---|---|
| High | Text instructions | Multiple valid approaches |
| Medium | Pseudocode/parameterized scripts | Preferred pattern exists |
| Low | Specific scripts | Fragile ops, consistency critical |
Metadata (name + description) - Always loaded (~100 words)
description is the PRIMARY discovery mechanismSKILL.md body - Loaded when skill triggers
Bundled resources - Loaded on-demand by agent
references/Keep core workflow in SKILL.md. Move variant-specific details to references/.
Example structure:
cloud-deploy/
├── SKILL.md (workflow + provider selection)
└── references/
├── aws.md
├── gcp.md
└── azure.md
Agent loads only the relevant provider file.
Gather concrete examples of how the skill will be used. Ask:
Skip only if usage patterns are already clear.
For each use case, identify reusable resources:
| If you find yourself... | Add to... |
|---|---|
| Rewriting same code | scripts/ |
| Re-discovering schemas/docs | references/ |
| Copying same templates | assets/ |
Examples:
pdf-editor: "Rotate this PDF" → scripts/rotate_pdf.pybigquery: "How many users today?" → references/schema.mdfrontend-builder: "Build me a todo app" → assets/react-template/Create the skill directory and SKILL.md manually:
# Global skill (personal tools)
mkdir -p ~/.config/opencode/skill/my-skill
# Project skill (team-specific)
mkdir -p .opencode/skill/my-skill
Create SKILL.md with frontmatter:
---
name: my-skill
description: |-
[Workflow/capabilities]. Use for [specific cases]. Use proactively when [contexts].
Examples:
- user: "query" → action
- user: "query" → action
---
# [Skill Name]
[Instructions start here]
Description template example:
---
name: typescript-advanced
description: |-
Handle TypeScript 5.9 advanced typing, generics, strict configs, type errors, migrations,
and test writing. Use proactively for complex generics, conditional types, utility types, TS compiler
config, or test authoring.
Examples:
- user: "Create a type-safe event emitter" → implement with generics and mapped types
- user: "Migrate to strict TypeScript" → add discriminated unions, exhaustive checks
- user: "Build typed API client from OpenAPI" → generate request/response types with inference
- user: "Write unit tests" → create strict, typed tests with realistic fixtures
---
Add optional directories as needed:
cd my-skill
mkdir scripts references assets # only create what you'll actually use
Writing guidelines:
Frontmatter requirements:
name: lowercase-hyphen format, must match directory name exactlydescription: CRITICAL — follow the format specified in Verify the skill is discoverable:
Check structure:
SKILL.md exists in skill directoryname: in frontmatter exactlyTest discovery:
<available_skills> sectionVerify triggers:
Note: Skills are used directly from their directories. No packaging or installation step required.
After real usage:
description to include missing trigger contextsControl skill access per-agent in agent config:
{
"permission": {
"skill": { "*": "deny", "my-skill": "allow" }
}
}
Values: "allow", "deny", "ask". Use "*" as wildcard default.
Batching: Use the question tool for 2+ related questions. Single questions → plain text.
Syntax: header ≤12 chars, label 1-5 words, add "(Recommended)" to default.
When to ask: Ambiguous request, multiple skill patterns apply, or scope unclear.