intermediate45 minLesson 3 of 5

Building and Registering Custom Skills

Master the skill system: structure, manifests, instructions, tools, resources, parameters, discovery, and registration.

Building and Registering Custom Skills

Skill Structure

A skill is a directory containing a manifest file and optional resources:

skills/ my-custom-skill/ skill.yaml # Manifest (required) instructions.md # Extended instructions (optional) templates/ # Resource files (optional) scaffold.py references/ # Reference documents (optional) api-guide.md
ℹ️Note

While skill.yaml is the conventional format, OpenCode also supports JSON manifests (skill.json). YAML is recommended for readability, especially for long instruction blocks. JSON is preferable when you need to generate manifests programmatically or validate them with JSON Schema.


Skill Loading Lifecycle

Understanding how skills are loaded helps you design efficient skills that don't waste context window.

100%
💡Tip

Skills with overly broad descriptions may be loaded unintentionally, consuming context window and tokens. Keep descriptions specific and focused. Use matchPattern for precise control over when a skill activates.


Skill Manifest

The manifest defines the skill's identity, purpose, and components.

yaml
# skill.yaml name: my-custom-skill description: Guides the agent in performing custom scaffold generation author: NUniversity version: 1.0.0 instructions: | When the user asks to scaffold a new Python project: 1. Use the template files in the `templates/` directory 2. Ask the user for the project name and package name 3. Generate the directory structure with pyproject.toml, src/, tests/ 4. Initialize a git repository tools: - bash - write - read - glob resources: - templates/scaffold.py - references/api-guide.md
📌Important

The instructions field is the most critical part of a skill. It is injected directly into the agent's context. Keep instructions concise and actionable — every token consumed by the skill is a token not available for the conversation. Aim for no more than 500-1000 words per skill.

Comparison: YAML vs JSON Manifest Formats

AspectYAML (skill.yaml)JSON (skill.json)
ReadabilityExcellent — natural for long textGood — familiar to JS/TS devs
CommentsSupported (# comment)Not supported
Multi-lineNative (`and>` block scalars)
Schema validateLimited toolingJSON Schema, many validators
Best forHand-written skills with instructionsAuto-generated or validated skills
File sizeTypically smallerSlightly larger (quotes, commas)
ToolingYAML linters availableNative JSON in most editors

Writing Skill Instructions

Instructions are the core of a skill. They guide the agent step by step.

markdown
# instructions.md ## Goal Scaffold a production-ready Python project. ## Steps 1. Ask the user for: project name, package name, Python version 2. Create directory: `{project_name}/` 3. Generate `pyproject.toml` with: - Project metadata - Dependencies (click, pytest, black) - Build system config 4. Create `src/{package_name}/__init__.py` with version string 5. Create `tests/test_{package_name}.py` with a placeholder test 6. Run `git init` and `git add -A` ## Constraints - Do not overwrite existing files without asking - Use the latest Python packaging standards (PEP 621)
bash
# Instructions can reference scripts bundled as resources # Example: running the scaffold template python skills/my-custom-skill/templates/scaffold.py \ --project-name "$PROJECT_NAME" \ --package-name "$PACKAGE_NAME"

Skill Tools and Resources

Skills can declare required tools and bundle resource files:

json
{ "name": "db-migration-skill", "description": "Database migration generation and management", "version": "2.1.0", "instructions": "When managing database migrations...", "tools": ["bash", "read", "write", "grep"], "resources": [ "templates/migration_template.sql", "templates/rollback_template.sql", "config/migration.config.json" ], "parameters": { "db_type": { "type": "string", "description": "Database type (postgres, mysql, sqlite)", "required": true }, "migration_name": { "type": "string", "description": "Descriptive name for the migration", "required": true } } }
⚠️Warning

Each resource file loaded into context consumes tokens. Bundle only essential files. Large reference documents should be linked rather than embedded. A 100KB reference file consumes roughly 25,000 tokens of context window.


Skill Parameters

Parameters allow skills to be configurable and reusable:

yaml
name: api-client-generator description: Generates API client libraries from OpenAPI specs version: 1.0.0 instructions: | Generate an API client based on the provided OpenAPI specification. Use the language parameter to determine the output format. parameters: language: type: string description: "Target language (python, typescript, go)" required: true default: python spec_path: type: string description: "Path to OpenAPI specification file" required: true output_dir: type: string description: "Output directory for generated client" required: false default: "./generated"
💡Tip

Use required: false with a sensible default value for parameters that have obvious defaults. This reduces friction when using the skill while still allowing customization. Parameters are passed when the skill is invoked through agent instructions.

Skill Execution Flow

100%

Registering Skills in Config

Skills must be registered in opencode.json to be discoverable:

json
{ "skills": { "scaffold-python": { "manifest": "skills/scaffold-python/skill.yaml" }, "db-migration": { "manifest": "skills/db-migration/skill.json" }, "api-client-gen": { "manifest": "skills/api-client-generator/skill.yaml" } } }
typescript
// Skills can also be registered programmatically import { OpenCode } from "opencode"; const opencode = new OpenCode(); opencode.registerSkill({ name: "react-component", manifest: "skills/react-component/skill.yaml", autoLoad: true, matchPattern: "react component|jsx|tsx" }); await opencode.run();

Skill Discovery

OpenCode discovers skills through registration and pattern matching. When a user query matches a skill's description, the skill is automatically loaded.

⚠️Warning

Skills with overly broad descriptions may be loaded unintentionally, consuming context window and tokens. Keep descriptions specific and focused. A skill described as "helps with development" will match nearly every request.

json
{ "skills": { "react-component": { "manifest": "skills/react-component/skill.yaml", "autoLoad": true, "matchPattern": "react component|jsx|tsx component|react hook" } } }
💡Tip

The autoLoad field combined with matchPattern gives you precise control. Without autoLoad, the skill is only loaded when explicitly requested. This is useful for niche skills that shouldn't activate on every vaguely related query. Use autoLoad: false for rarely-used skills to save context.


Comparison: Skill Manifest Fields

FieldTypeRequiredDescription
namestringYesUnique skill identifier
descriptionstringYesShort description for discovery matching
versionstringYesSemantic version (e.g., 1.0.0)
instructionsstringYesStep-by-step guidance for the agent
toolsstring[]NoList of required tools
resourcesstring[]NoBundled file paths relative to skill dir
parametersobjectNoConfigurable parameters with defaults
authorstringNoCreator name for attribution
matchPatternstringNoRegex pattern for auto-load triggering
autoLoadbooleanNoWhether skill activates on pattern match
ℹ️Note

A skill can have both instructions inline in the manifest and an external instructions.md file. If both exist, the external file takes precedence. Use inline instructions for short skills and external files for complex, multi-step procedures.


Practice Questions

Practice Question

A developer wants to create the smallest possible custom skill. What is the minimum requirement?

Practice Question

How do skill parameters differ from skill tools in a manifest?

Practice Question

When registering a skill in opencode.json, which two optional fields control whether the skill loads automatically when a user query matches?

Practice Question

A skill's description is 'handles various development tasks.' Why is this problematic?

Practice Question

A skill bundles a 500KB API reference PDF as a resource. What is the likely consequence when this skill loads?


**Key Takeaways**
  • A skill is a directory with a manifest file (YAML or JSON) and optional resource files
  • The manifest defines name, description, version, instructions, tools, resources, and parameters
  • Instructions provide step-by-step guidance that directs agent behavior during a task
  • Skills are registered in opencode.json under the skills key with a path to the manifest
  • Parameters make skills reusable across different contexts with configurable inputs
  • Resources bundle reference files, templates, and scripts alongside the skill
  • Skill discovery uses description matching and optional matchPattern fields for auto-loading
  • Overly broad descriptions cause skills to load unnecessarily, consuming context tokens
  • YAML is recommended for hand-written skills; JSON is better for auto-generated ones
  • The skill loading lifecycle goes: registration, matching, manifest validation, resource loading, instruction injection
Progress60%