Skill Development Best Practices
What You'll Learn
After completing this tutorial, you will be able to:
- Write skill names that follow naming conventions
- Write descriptions that are easily recognized by automatic recommendations
- Organize clear skill directory structures
- Use script features appropriately
- Avoid common Frontmatter errors
- Improve skill discoverability and usability
Why Best Practices Matter
The OpenCode Agent Skills plugin doesn't just store skills—it also:
- Auto-discovery: Scans skill directories from multiple locations
- Semantic matching: Recommends skills based on description similarity to user messages
- Namespace management: Supports coexistence of skills from multiple sources
- Script execution: Automatically scans and executes runnable scripts
Following best practices ensures your skills:
- ✅ Are correctly recognized and loaded by the plugin
- ✅ Receive higher recommendation priority in semantic matching
- ✅ Avoid conflicts with other skills
- ✅ Are more easily understood and used by team members
Naming Conventions
Skill Name Rules
Skill names must conform to the following specifications:
Naming Rules
- ✅ Use lowercase letters, numbers, and hyphens
- ✅ Start with a letter
- ✅ Use hyphens to separate words
- ❌ Don't use uppercase letters or underscores
- ❌ Don't use spaces or special characters
Examples:
| ✅ Good Examples | ❌ Bad Examples | Reason |
|---|---|---|
git-helper | GitHelper | Contains uppercase letters |
docker-build | docker_build | Uses underscores |
code-review | code review | Contains spaces |
test-utils | 1-test | Starts with a number |
Source reference: src/skills.ts:106-108
name: z.string()
.regex(/^[\p{Ll}\p{N}-]+$/u, { message: "Name must be lowercase alphanumeric with hyphens" })
.min(1, { message: "Name cannot be empty" }),Directory Name vs. Frontmatter Relationship
The skill directory name and the name field in frontmatter can be different:
---
# Directory is my-git-tools, but frontmatter name is git-helper
name: git-helper
description: Git common operations helper
---Recommended practices:
- Keep directory name and
namefield consistent for easier maintenance - Use short, memorable identifiers for directory names
- The
namefield can be more specific about skill purpose
Source reference: src/skills.ts:155-158
Description Writing Tips
Purpose of Descriptions
Skill descriptions are not just for user guidance—they're also used for:
- Semantic matching: The plugin calculates similarity between description and user messages
- Skill recommendation: Automatically recommends relevant skills based on similarity
- Fuzzy matching: Used to recommend similar skills when skill name is misspelled
Good vs. Bad Descriptions
| ✅ Good Descriptions | ❌ Bad Descriptions | Reason |
|---|---|---|
| "Automate Git branch management and commit workflow, supports auto-generating commit messages" | "Git tool" | Too vague, lacks specific functionality |
| "Generate type-safe API client code for Node.js projects" | "A useful tool" | Doesn't specify use case |
| "Translate PDF to Chinese while preserving original formatting" | "Translation tool" | Doesn't mention special capabilities |
Description Writing Principles
Description Writing Principles
- Be specific: Explain the specific purpose and use cases of the skill
- Include keywords: Include keywords users might search for (e.g., "Git", "Docker", "translation")
- Highlight unique value: Explain advantages compared to similar skills
- Avoid redundancy: Don't repeat the skill name
Examples:
---
name: pdf-translator
description: Translate English PDF documents to Chinese while preserving original layout, image positions, and table structures. Supports batch translation and custom glossaries.
---This description includes:
- ✅ Specific features (PDF translation, format preservation)
- ✅ Use cases (English documents)
- ✅ Unique value (format preservation, batch, glossaries)
Source reference: src/skills.ts:109
description: z.string()
.min(1, { message: "Description cannot be empty" }),Directory Organization
Basic Structure
A standard skill directory contains:
my-skill/
├── SKILL.md # Main skill file (required)
├── README.md # Detailed documentation (optional)
├── tools/ # Runnable scripts (optional)
│ ├── setup.sh
│ └── run.sh
└── docs/ # Supporting documentation (optional)
├── guide.md
└── examples.mdSkipped Directories
The plugin automatically skips the following directories (doesn't scan for scripts):
Automatically Skipped Directories
node_modules- Node.js dependencies__pycache__- Python bytecode cache.git- Git version control.venv,venv- Python virtual environments.tox,.nox- Python testing environments- Any hidden directory starting with
.
Source reference: src/skills.ts:61
const skipDirs = new Set(['node_modules', '__pycache__', '.git', '.venv', 'venv', '.tox', '.nox']);Recommended Directory Naming
| Purpose | Recommended Directory Name | Description |
|---|---|---|
| Script files | tools/ or scripts/ | Store runnable scripts |
| Documentation | docs/ or examples/ | Store supporting documentation |
| Configuration | config/ | Store configuration files |
| Templates | templates/ | Store template files |
Script Usage
Script Discovery Rules
The plugin automatically scans for executable files in skill directories:
Script Discovery Rules
- ✅ Scripts must have executable permissions (
chmod +x script.sh) - ✅ Maximum recursion depth is 10 levels
- ✅ Skips hidden directories and dependency directories
- ❌ Non-executable files are not recognized as scripts
Source reference: src/skills.ts:86
if (stats.mode & 0o111) {
scripts.push({
relativePath: newRelPath,
absolutePath: fullPath
});
}Setting Script Permissions
Bash scripts:
chmod +x tools/setup.sh
chmod +x tools/run.shPython scripts:
chmod +x tools/scan.pyAnd add shebang at the beginning of the file:
#!/usr/bin/env python3
import sys
# ...Script Invocation Examples
When a skill is loaded, AI sees the available script list:
Available scripts:
- tools/setup.sh: Initialize development environment
- tools/build.sh: Build project
- tools/deploy.sh: Deploy to productionAI can call these scripts using the run_skill_script tool:
run_skill_script({
skill: "project-builder",
script: "tools/build.sh",
arguments: ["--release", "--verbose"]
})Frontmatter Best Practices
Required Fields
name: Skill unique identifier
- Lowercase letters, numbers, and hyphens
- Short but descriptive
- Avoid generic names (like
helper,tool)
description: Skill description
- Specifically explain functionality
- Include use cases
- Appropriate length (1-2 sentences)
Optional Fields
license: License information
license: MITallowed-tools: Restrict tools available to the skill
allowed-tools:
- read
- write
- bashmetadata: Custom metadata
metadata:
author: "Your Name"
version: "1.0.0"
category: "development"Source reference: src/skills.ts:105-114
const SkillFrontmatterSchema = z.object({
name: z.string()
.regex(/^[\p{Ll}\p{N}-]+$/u, { message: "Name must be lowercase alphanumeric with hyphens" })
.min(1, { message: "Name cannot be empty" }),
description: z.string()
.min(1, { message: "Description cannot be empty" }),
license: z.string().optional(),
"allowed-tools": z.array(z.string()).optional(),
metadata: z.record(z.string(), z.string()).optional()
});Complete Example
---
name: docker-deploy
description: Automate Docker image building and deployment process, supports multi-environment configuration, health checks, and rollbacks
license: MIT
allowed-tools:
- read
- write
- bash
metadata:
version: "2.1.0"
author: "DevOps Team"
category: "deployment"
---
# Docker Auto-Deployment
This skill helps you automate the Docker image build, push, and deployment process.
## Usage
...Avoiding Common Mistakes
Mistake 1: Name Doesn't Follow Conventions
Bad example:
name: MyAwesomeSkill # ❌ Uppercase lettersFix:
name: my-awesome-skill # ✅ Lowercase + hyphensMistake 2: Description Too Vague
Bad example:
description: "A useful tool" # ❌ Too vagueFix:
description: "Automate Git commit workflow, auto-generate standard-compliant commit messages" # ✅ Specific and clearMistake 3: Scripts Without Execution Permissions
Problem: Scripts aren't recognized as executable
Solution:
chmod +x tools/setup.shVerify:
ls -l tools/setup.sh
# Should show: -rwxr-xr-x (has x permission)Mistake 4: Directory Name Conflicts
Problem: Multiple skills use the same name
Solution:
- Use namespaces (via plugin config or directory structure)
- Or use more descriptive names
Source reference: src/skills.ts:258-259
// Only keep the first skill with the same name, subsequent ones are ignored
if (skillsByName.has(skill.name)) {
continue;
}Improving Discoverability
1. Optimize Description Keywords
Include keywords users might search for in your description:
---
name: code-reviewer
description: Automated code review tool that checks code quality, potential bugs, security vulnerabilities, and performance issues. Supports multiple languages including JavaScript, TypeScript, Python, and more.
---Keywords: code review, code quality, bugs, security vulnerabilities, performance issues, JavaScript, TypeScript, Python
2. Use Standard Skill Locations
The plugin discovers skills in the following priority order:
.opencode/skills/- Project-level (highest priority).claude/skills/- Project-level Claude~/.config/opencode/skills/- User-level~/.claude/skills/- User-level Claude
Recommended practices:
- Project-specific skills → Place at project-level
- General-purpose skills → Place at user-level
3. Provide Detailed Documentation
Beyond SKILL.md, you can also provide:
README.md- Detailed instructions and usage examplesdocs/guide.md- Complete usage guidedocs/examples.md- Real-world examples
Summary
This tutorial covered best practices for skill development:
- Naming conventions: Use lowercase letters, numbers, and hyphens
- Description writing: Be specific, include keywords, highlight unique value
- Directory organization: Clear structure, skip unnecessary directories
- Script usage: Set executable permissions, note depth limits
- Frontmatter conventions: Correctly fill required and optional fields
- Avoid mistakes: Common problems and solutions
Following these best practices ensures your skills:
- ✅ Are correctly recognized and loaded by the plugin
- ✅ Receive higher recommendation priority in semantic matching
- ✅ Avoid conflicts with other skills
- ✅ Are more easily understood and used by team members
Next Up
In the next lesson, we'll learn about API Tool Reference.
You'll see:
- Detailed parameter descriptions for all available tools
- Tool invocation examples and return value formats
- Advanced usage and important considerations
Appendix: Source Reference
Click to expand source code locations
Last updated: 2026-01-24
| Feature | File Path | Line Numbers |
|---|---|---|
| Skill name validation | src/skills.ts | 106-108 |
| Skill description validation | src/skills.ts | 109-110 |
| Frontmatter Schema definition | src/skills.ts | 105-114 |
| Skipped directories list | src/skills.ts | 61 |
| Script executable permission check | src/skills.ts | 86 |
| Duplicate skill deduplication logic | src/skills.ts | 258-259 |
Key constants:
- Skipped directories:
['node_modules', '__pycache__', '.git', '.venv', 'venv', '.tox', '.nox']
Key functions:
findScripts(skillPath: string, maxDepth: number = 10): Recursively find executable scripts in skill directoryparseSkillFile(skillPath: string): Parse SKILL.md and validate frontmatter